Commit Graph

180 Commits

Author SHA1 Message Date
ZhenYi
da9e96f6dd feat: add /robots.txt blocking sensitive paths from crawlers
Disallows: /api/, /health, /metrics, /ws/, /avatar/, /blob/,
/media/, /static/, /assets/
2026-04-25 23:49:50 +08:00
ZhenYi
10836730ed feat: add health endpoints and Prometheus metrics to git-hook and email-worker
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
Health monitoring:
- gitserver: /health endpoint on port 8021 (DB + Redis ping)
- git-hook: hyper health server on port 8083 with /health
- email-worker: hyper health server on port 8084 with /health
- K8s probes updated to httpGet for all three services

Metrics (via /metrics endpoint):
- git-hook: hook_tasks_total/success/failed/locked/retried/exhausted,
  hook_sync_branches/tags_changed_total
- email: email_queued/consumed/sent/failed_total,
  email_validation_skipped/build_errors/send_attempts_total
2026-04-25 23:45:48 +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
78eee672a4 feat(room): AI typing indicator with 60s Redis TTL and WS replay
- Add sender_type field to TypingEvent (user/ai)
- Change Redis TTL from 10s to 60s for AI typing persistence
- Broadcast typing.start/stop with sender_type=ai when AI stream starts/ends
- Replay active AI typing events from Redis on new WS subscribe
- Fix ai.stream_chunk WS payload missing display_name and chunk_type
- Add initial thinking chunk on AI stream start for immediate indicator
2026-04-25 22:45:03 +08:00
ZhenYi
881fbdb6ea refactor(service): clean up agent modules, use agent crate types
- service now delegates model/provider/pricing logic to agent crate
- ChatService built at startup with EmbedService (graceful degradation)
- RoomService wired with EmbedService for Qdrant embedding
- Add error types for embedding service
2026-04-25 20:09:45 +08:00
ZhenYi
10c0cc007b refactor(agent): split into submodules and add Qdrant embedding
- Split agent crate into client/, model/, agent/ subdirs
- Add billing.rs for token usage recording
- Add sync.rs for upstream model sync
- EmbedService: Qdrant-backed vector memory for semantic search
- ChatService: wire EmbedService for memory lookup, passive skill awareness
- ReAct loop: streamline with tokio::select! and proper error handling
2026-04-25 20:09:33 +08:00
ZhenYi
01285ca9ce feat(room): inject text messages into Qdrant for vector search
- message.rs: after creating a text message, spawn async task to
  embed and upsert into Qdrant collection "room:{project}:{room_id}"
- service.rs: RoomService now takes optional EmbedService, embed on
  every message creation
2026-04-25 20:09:16 +08:00
ZhenYi
215846b1db feat(api): pre-compress static assets with brotli and gzip
- build.rs: generate .gz and .br compressed variants at build time,
  embed both into the FRONTEND constant
- dist.rs: content-type for SPA fallback uses index.html path explicitly,
  explicit extension mapping for Vite content-hashed filenames
- frontend lib: get_frontend_asset_compressed returns (data, encoding, etag)
2026-04-25 20:09:09 +08:00
ZhenYi
76de013a60 fix(git): add offset_minutes to reflog entry for timezone-correct timestamps
CommitReflogEntry now includes offset_minutes field, populated from
sig.when().offset_minutes() — matches git's internal timezone offset
representation. Used by git_tools for accurate reflog timestamps.
2026-04-25 09:54:30 +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
f7e087e066 fix(agent/service): retry jitter, tool executor ordering, curl SSRF, grep/JSON
- agent/client: full jitter backoff (random(0, base_ms)) instead of equal jitter
- agent/tool/executor: fix buffer_unordered ordering mismatch with
  HashMap-by-index approach for concurrent tool execution
- agent/chat: AiChunkType emit fixes, is_retryable_tool_error refinements,
  process_react uses request.max_tool_depth
- agent/chat/context: fix Function message sender_name field
- file_tools/curl: shared reqwest::Client via OnceLock, manual redirect
  following with per-hop SSRF validation, blocked sensitive headers
- file_tools/grep: fix case-insensitive glob matching, segment consumption
- file_tools/json: bracket notation support, remove .vscodeignore from JSONC
- git_tools: git_diff_stats resolve base/head independently,
  DiffFileOut old_file.path for Deleted, reflog offset_minutes
- git/repo: create_commit read parent tree into index, bare repo init
- project_tools/repos: branch/path validation, .git/ prefix check
- service/agent: tokent integration, billing, pr_summary, code_review fixes
2026-04-25 09:53:31 +08:00
ZhenYi
57d0fc371e fix(room): include display_name in RoomMessageEnvelope for AI streaming
RoomMessageEvent was losing the AI model name because the
From<RoomMessageEnvelope> impl hardcoded display_name: None.
Add display_name to RoomMessageEnvelope and propagate it through
all AI streaming code paths (chat, ReAct, non-streaming).
Member messages keep display_name: None.
2026-04-25 09:52:41 +08:00
ZhenYi
6b3b77384e chore(rpc): regenerate after removing metrics 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
2026-04-24 13:22:01 +08:00
ZhenYi
4fb58de1a0 chore(rpc): remove metrics-related RPC endpoints
- Drop GetMetrics and ExportMetricsCsv from proto, build.rs, client
- These endpoints are no longer needed in the admin gRPC service
2026-04-24 13:21:55 +08:00
ZhenYi
beee62832f fix(room): reasoning chain fallback, streaming error messages, borrow fixes
Some checks are pending
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Rust Lint & Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions
- ReAct streaming: collect all ReactStep chunks into reasoning_buffer;
  if no Answer step is emitted, persist the full reasoning chain instead
  of empty content
- All AI error paths (reasoning loop failure, non-streaming errors) now
  send user-visible [AI error: ...] messages instead of silently dropping
- Fix borrow checker: clone content before struct init, use should_log bool
  to avoid double-borrow on err_msg
2026-04-24 13:17:20 +08:00
ZhenYi
d89d02e81b fix(agent): surface FC/tool errors as observations to continue ReAct loop
- Streaming path: on tool_call execution error, emit an [Observation]
  chunk so the model sees the failure and can retry/adapt
- Non-streaming path: inject error as a user message so the loop
  continues with error context, not silently stop
2026-04-24 13:17:13 +08:00
ZhenYi
94825316dc fix(agent): extract JSON from model output even with leading text prefix
ReAct loop was terminating early when the model returned:
  [Agent ran through N steps...]
  {"thought": "...", "action": {...}}

The extract_json function only checked the string start or code fences.
Now scans for { or [ at non-word positions and uses depth-counting
to strip trailing text, allowing JSON buried anywhere in the response.
2026-04-24 13:17:06 +08:00
ZhenYi
5776af18ca perf: sequence generation Redis-only + session MGET batch
service.rs: Replace per-message Lua+DB seq with simple INCR, only
reconcile DB every 1000 messages (99.9% queries eliminated).

storage.rs: Replace N+1 GET loop with single MGET for both
get_user_sessions and get_workspace_sessions (N+1 → 2 roundtrips).
2026-04-24 00:04:27 +08:00
ZhenYi
33ab7b058d fix(ws): replace unreachable_unchecked with safe fallback for TypingStart/TypingStop
TypingStart/TypingStop actions are intercepted in ws_universal.rs so
this match arm is never reached, but we need a safe fallback instead
of std::hint::unreachable_unchecked().
2026-04-24 00:04:18 +08:00
ZhenYi
fb28fdd056 feat(room): implement typing indicator broadcast with Redis 10s TTL
RoomConnectionManager now holds a cache field and typing_inner broadcast
map. broadcast_typing() persists start/stop to Redis (SETEX 10s / DEL)
and broadcasts via tokio channel. ws_universal.rs handles TypingStart/
TypingStop actions and streams typing events to WS clients.
2026-04-24 00:04:09 +08:00
ZhenYi
e83512382f feat(room): add TypingEvent type and TypingStart/TypingStop event variants
Add TypingEvent struct in queue::types for broadcast-based typing
indicators, and TypingStart/TypingStop variants in RoomEventType for
WebSocket event dispatch.
2026-04-24 00:04:01 +08:00
ZhenYi
ae601774df chore(admin): remove all metrics/observability features
- Delete admin metrics dashboard page (admin/metrics/page.tsx)
- Delete LineChart component (used only by metrics)
- Remove "指标监控" nav link from Sidebar
- Remove getMetrics/exportMetricsCsv from admin-rpc.ts client
- Remove /api/admin/metrics and /api/admin/metrics/export HTTP routes
  from adminrpc (was also leaking metrics via HTTP)
- Remove metrics RPC methods (get_metrics, export_metrics_csv) from
  adminrpc gRPC server and their helper functions
- Remove spawn_redis_metrics_flusher from app/main.rs
- Remove redis_metrics module from observability crate
- Remove redis/deadpool-redis deps from observability Cargo.toml
2026-04-23 15:42:00 +08:00
ZhenYi
7187638c10 chore(adminrpc): regenerate proto with latest admin service methods
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
Regenerate admin.rs from admin.proto to include the SyncModels and
CheckAlerts RPC methods added in the gRPC migration commit.
2026-04-22 23:30:31 +08:00
ZhenYi
8defac98ad fix(observability): resolve tracing double-init runtime panic
Both init_tracing_subscriber() and init_otlp() were calling try_init()
on the global tracing dispatcher, causing "global default trace dispatcher
has already been set" at runtime when APP_OTEL_ENABLED=true.

Fix: simplify the API so init_tracing_subscriber() never installs the
subscriber — it either calls try_init() immediately (non-OTLP mode) or
returns without installing (OTLP mode, defer=true).  init_otlp() now
builds the complete subscriber stack (registry + env_filter + fmt_layer +
otel_layer) and calls try_init() once.

init_tracing_subscriber() signature: (level, defer) → ()
init_otlp() signature: (endpoint, service_name, _, log_level) → Result

The fmt layer is replicated inside init_otlp() for the OTLP path.
2026-04-22 23:28:56 +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
f67c788cbe feat(gRPC): migrate admin RPC from Redis Pub/Sub to Tonic gRPC
- libs/rpc/admin: tonic-prost generated server + client wrappers
- apps/adminrpc: standalone binary with all 8 admin RPC methods
- Redis Pub/Sub JSON-RPC code removed from admin module
- libs/agent: add React agent loop for ReAct pattern
- proto/admin.proto: updated with list_workspace_sessions, is_user_online
2026-04-22 22:39:06 +08:00
ZhenYi
aef5280ae8 fix(projects): include project_members when listing user projects
Users who accepted a project invitation could not see that project
on their /user/{username} page because get_user_projects only queried
projects where created_by == user_uid, ignoring project_members entries.
Now unions created_projects and member_projects with privacy filtering.
2026-04-22 22:38:52 +08:00
ZhenYi
962bf0312d feat(observability): Phase 6 OTLP tracing + Prometheus metrics endpoint
OTLP tracing:
- libs/observability/otlp.rs: SdkTracerProvider via HTTP/proto OTLP exporter
- libs/observability/tracing_middleware.rs: Actix-web span with trace_id propagation
- libs/observability/tracing_fmt.rs: JSON fmt + registry.try_init for layered init
- libs/rpc: gRPC method spans via info_span
- libs/agent, libs/room, libs/service, libs/api: structured tracing throughout

Prometheus metrics:
- libs/observability/prometheus_exporter.rs: /metrics HTTP handler + metrics crate
- libs/observability/metrics_middleware.rs: HttpMetrics middleware + AtomicU64
- libs/observability/redis_metrics.rs: Redis counter poller via RedisMetrics
- libs/room/metrics.rs: RoomMetrics (connections, messages, presence counters)

Config env vars: APP_OTEL_ENABLED, APP_OTEL_ENDPOINT, APP_OTEL_SERVICE_NAME
2026-04-22 10:27:54 +08:00
ZhenYi
beae9bdea0 feat(observability): Phase 6 OTLP tracing for gRPC + config helper
- libs/rpc: slog → tracing; 8 gRPC methods instrumented with
  info_span + Instrument for W3C trace propagation
- libs/session_manager: slog → tracing dependency
- libs/config: add redis_url() singleton helper for adminrpc
2026-04-21 23:05:37 +08:00
ZhenYi
1e6ba34827 fix(project): invitation accept always 404 due to wrong column filter
Column::Project was used twice instead of Column::User in the query,
causing the filter to be project_id = X AND project_id = user_uid
which never matches.
2026-04-21 23:05:18 +08:00
ZhenYi
aeb765d2ac chore(deps): replace slog with tracing in workspace Cargo.toml and crates
- Cargo.toml: update root dependencies
- libs/agent/Cargo.toml: slog -> tracing
- libs/api/Cargo.toml: slog -> tracing
- Cargo.lock: update lockfile
2026-04-21 22:31:30 +08:00
ZhenYi
c850adb4eb refactor(api,agent): migrate libs/api room ws and libs/agent client to tracing
- api/room/ws.rs, ws_universal.rs: replace slog macros with tracing
- agent/client.rs: replace slog macros with tracing for AI retry logs
2026-04-21 22:31:13 +08:00
ZhenYi
e99feb236b refactor(core): migrate session_manager, email, rpc from slog to tracing
- session_manager/manager.rs: remove slog::Logger field, update new()
  and with_config() to remove log parameter
- email/lib.rs: remove slog::Logger from AppEmail::init()
- rpc/admin/server.rs: remove slog::Logger from serve() and spawn(),
  replace with tracing::info!/error!
2026-04-21 22:29:43 +08:00
ZhenYi
0c1a9ddf98 refactor(git): migrate libs/git from slog to tracing
- Remove all use slog::* imports and log: slog::Logger fields
- ssh/handle.rs: replace slog macro chains with tracing::{info!, warn!,
  error!, debug!}; remove log field from GitSshHandle
- ssh/authz.rs, ssh/mod.rs, ssh/server.rs: remove slog Logger fields
- http/: auth.rs, handler.rs, mod.rs, routes.rs: remove slog usage
- hook/: pool worker, sync modules, webhook_dispatch.rs: remove slog
2026-04-21 22:29:26 +08:00
ZhenYi
9a03cded8d refactor(queue): migrate from slog to tracing
- Remove all slog::Logger imports and log fields from RedisPubSub,
  MessageProducer structs
- Remove log parameter from MessageProducer::new()
- Replace slog::info!/warn!/error! with tracing equivalents
- worker.rs: remove log: slog::Logger from start(), room_worker_task(),
  start_email_worker(), run_once(), email_run_once()
2026-04-21 22:29:09 +08:00
ZhenYi
57779822dc refactor(room): migrate from slog to tracing + upgrade metrics to 0.22
- Remove all use slog::* imports and log: slog::Logger fields
- Replace slog macros with tracing::{info!, warn!, error!, debug!}
- metrics.rs: upgrade metrics 0.21→0.22, remove register_*! macros,
  use functional API: metrics::gauge!(), metrics::counter!(),
  metrics::histogram!(), metrics::describe_gauge!() etc.
- RoomMetrics: all fields now use functional metrics API, dynamic
  room_id labels passed as owned String to avoid lifetime issues
- RoomService: remove pub log: slog::Logger field
- connection.rs: remove log from subscribe_room_events,
  subscribe_project_room_events, subscribe_task_events_fn
2026-04-21 22:28:52 +08:00
ZhenYi
773da34fab refactor(service): migrate auth, git service, agent from slog to tracing
- Remove all use slog::* imports and slog::Logger fields/parameters
- Replace slog::info!/warn!/error! with tracing::info!/warn!/error!
- AppService: remove pub logs: slog::Logger field, update callers of
  AppEmail::init(), MessageProducer::new(), RoomService::new(),
  start_email_worker(), start_room_workers()
- auth/: captcha, email, login, logout, password, register, rsa, totp
- git/: archive, blame, blob, branch, commit, contributors, diff,
  refs, star, tag, tree, watch
- agent/: billing (ai_usage_recorded), code_review, pr_summary, sync
- project/activity.rs, workspace/alert.rs
2026-04-21 22:28:33 +08:00
ZhenYi
b4024aa690 feat(observability): Phase 6 OTLP tracing + Prometheus /metrics endpoint
- Add HTTP OTLP exporter (opentelemetry-otlp 0.31) via SdkTracerProvider +
  BatchSpanProcessor + tracing_opentelemetry layer
- Add Prometheus /metrics handler via metrics-exporter-prometheus 0.13
- Replace slog with tracing throughout: HttpMetrics, TracingSpanMiddleware
- Replace .init() with .try_init() to allow OTLP layer registration after
  init_tracing_subscriber()
- otlp.rs: SpanExporter::builder().with_http().with_endpoint(),
  Resource::builder().with_service_name(), .with_attribute(KeyValue::new(...))
- prometheus_exporter.rs: install_recorder(), prometheus_handler(),
  spawn_http_metrics_poller()
2026-04-21 22:28:15 +08:00
ZhenYi
418f9a5d8b feat(rpc): migrate admin from Redis Pub/Sub JSON-RPC to Tonic gRPC
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
- libs/rpc/proto/: admin.proto with 8 RPC methods
- libs/rpc/admin/: tonic server impl (SessionAdminService), client
  wrapper (AdminGrpcClient), types, generated/ tonic-prost build output
- libs/rpc/build.rs: tonic-prost-build two-step (proto -> message types
  + manual service defs)
- libs/rpc/lib.rs: module re-exports
- libs/session_manager/: session manager types used by admin service
2026-04-21 13:44:25 +08:00
ZhenYi
81e6ee3d48 feat(observability): Phase 1-5 slog structured logging across platform
Phase 1: add libs/observability crate (build_logger, instance_id);
  remove duplicate logger init from 4 crates
Phase 2: Actix-web RequestLogger with trace_id; MetricsMiddleware + HttpMetrics
Phase 3: Git SSH handle.rs slog struct; HTTP handler Logger kv
Phase 4: AI client eprintln -> slog warn; billing ai_usage_recorded log
Phase 5: SessionManager slog; workspace alert slog 2.x syntax
2026-04-21 13:44:12 +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
d1e5245e4e fix: room attachment upload (Set Uuid::nil, NotFound with msg, Ok wrapper) and silence dead_code warnings
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:48:05 +08:00
ZhenYi
33a4a5c6c9 feat(service): register project_tools in chat service, add AppStorage::read method 2026-04-20 19:32:29 +08:00
ZhenYi
b23c6a03c3 feat(room): add attachment_ids to messages, pass AppConfig, increase max_tool_depth to 1000 2026-04-20 19:32:22 +08:00
ZhenYi
dee79f3f7f feat(room): add attachment upload/download API and attach files to messages 2026-04-20 19:32:11 +08:00
ZhenYi
a0ab16e6ea feat(agent): pass AppConfig through ToolContext and fix tool call handling 2026-04-20 19:32:03 +08:00
ZhenYi
4e955d9ae3 chore: add mime_guess2, quick-xml serialize feature, and config crate to room lib 2026-04-20 19:31:52 +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
d4b0a9ae67 feat(room): read model_id in search results, register m20260420_000003 migration
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 16:08:35 +08:00
ZhenYi
3c8e9e3674 fix(migrate): use Statement::from_string in down method for SeaORM 2.0
Some checks are pending
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Rust Lint & Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions
2026-04-20 16:02:18 +08:00
ZhenYi
8316fe926f feat(service): add push and storage service modules, update project/user/workspace services 2026-04-20 15:45:40 +08:00
ZhenYi
0c64122b80 chore(frontend): update frontend build configuration 2026-04-20 15:45:35 +08:00
ZhenYi
26865f8dcf chore(api): update dist.rs 2026-04-20 15:45:30 +08:00
ZhenYi
0e4631ec75 chore(api/user): update user notification endpoint 2026-04-20 15:45:26 +08:00
ZhenYi
26c86f0796 feat(api/room): add upload handler and update websocket handler 2026-04-20 15:45:22 +08:00
ZhenYi
cec8d486f1 feat(room): update room lib (connection, helpers, member, message, notification, reaction, room, search, service, types) 2026-04-20 15:45:18 +08:00
ZhenYi
1b863a9f65 chore(queue): update queue types 2026-04-20 15:45:13 +08:00
ZhenYi
2186960002 chore(models/users): update user notification model 2026-04-20 15:45:08 +08:00
ZhenYi
a2e8f5bf5b feat(models/rooms): add room attachment model and update room message/notifications 2026-04-20 15:45:03 +08:00
ZhenYi
98e6f77341 feat(migrate): add room attachment, push subscription, and model_id migrations 2026-04-20 15:44:59 +08:00
ZhenYi
d09af7c326 feat(config): add storage configuration module 2026-04-20 15:44:54 +08:00
ZhenYi
ba15324603 chore: update dependencies (cargo + npm) 2026-04-20 15:44:49 +08:00
ZhenYi
e612043e5f feat(room): auto-add new project members to all rooms
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 22:27:57 +08:00
ZhenYi
fb91f5a6c5 feat(admin): add admin panel with billing alerts and model sync
- Add libs/api/admin with admin API endpoints:
  sync models, workspace credit, billing alert check
- Add workspace_alert_config model and alert service
- Add Session::no_op() for background tasks without user context
- Add admin/ Next.js admin panel (AI models, billing, workspaces, audit)
- Start billing alert background task every 30 minutes
2026-04-19 20:48:59 +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
66006d842e feat(agent): inject project context and sender info into AI chat messages 2026-04-19 01:04:19 +08:00
ZhenYi
b740e2884d feat(room): auto-inherit project members as room members on room creation 2026-04-19 01:04:15 +08:00
ZhenYi
39d30678b5 fix(email): resolve SMTP connection failures (port 465 SMTPS, URL double scheme, retry backoff) 2026-04-19 01:04:11 +08:00
ZhenYi
882e86dc33 refactor(email): switch to async channel-based email queue with retry
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
Converts AppEmail from blocking sync sends to a background worker via
mpsc channel, adds SMTP pool tuning (min_idle 5, max_size 100), and
3-retry backoff on send failures.
2026-04-19 00:10:38 +08:00
ZhenYi
b693bd6beb fix(auth): use explicit user_uid in login flow instead of context.user()
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
The login function calls auth_2fa_status before set_user(user.uid), so
context.user() returns None and causes Unauthorized error on subsequent
logins after logout. Extracts auth_2fa_status_by_uid as an internal
helper accepting a Uuid, preserving the context-based wrapper for API
endpoints that require an authenticated user.
2026-04-19 00:03:18 +08:00
ZhenYi
2a2600859f dbg(email): add email error printrack
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
2026-04-18 23:30:17 +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
1af796ac75 feat(service): add file_tools module and git_blob_get tool
Add AI-accessible tools for reading structured files (CSV, JSON/JSONC,
Markdown, SQL) and searching repository content (git_grep). Also adds
git_blob_get to retrieve raw blob text content with binary detection.

Deferred: Excel, Word, PDF, PPT modules are stubbed out due to library
API incompatibilities (calamine 0.26, lopdf 0.34, quick-xml 0.37).
2026-04-18 23:02:10 +08:00
ZhenYi
767bb10249 feat(agent): wire git_tools into AI tool registry with full schemas
- ChatService: add tools() method to expose registered tool definitions
- RoomService: populate AiRequest.tools from chat_service.tools(), enable tools
  with max_tool_depth=3 (was always None)
- ToolHandler: add pub new() constructor so git_tools modules can register
  handlers with full schema metadata
- Add description + JSON schema params to all 16 git tools:
  git_log, git_show, git_search_commits, git_commit_info, git_graph,
  git_reflog, git_branch_list, git_branch_info, git_branches_merged,
  git_branch_diff, git_diff, git_diff_stats, git_blame, git_file_content,
  git_tree_ls, git_file_history, git_tag_list, git_tag_info
2026-04-18 21:42:33 +08:00
ZhenYi
9336250f1c fix(agent): skip reasoning_effort when think=false to avoid API errors
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-18 19:41:59 +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
c4fb943e07 fix(backend): add project_name and invited_by_username to InvitationResponse
InvitationResponse was missing project_name and invited_by_username fields,
causing /invitations accept to redirect to /project/undefined.
Now populated via async from_model() with batch DB lookups.
2026-04-18 19:24:43 +08:00
ZhenYi
5579e6c58e feat(backend): add git_tools service module
Add git_tools module with Git operations: branch, commit, diff, tag, tree, types, ctx
2026-04-18 19:08:06 +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
9b9c12ffc8 feat(backend): add workspace invitation list and slug-based accept APIs
- Add workspace_my_pending_invitations() for listing pending invites
- Add workspace_accept_invitation_by_slug() to accept by slug without token
- Register new routes: GET /workspaces/me/invitations, POST /workspaces/invitations/accept-by-slug
2026-04-18 19:05:07 +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
26682973e7 feat(room): redesign mention system with AST-based format
Backend:
- Add MENTION_TAG_RE matching new `<mention type="..." id="...">label</mention>` format
- Extend extract_mentions() and resolve_mentions() to parse new format (legacy backward-compatible)

Frontend:
- New src/lib/mention-ast.ts: AST types (TextNode, MentionNode, AiActionNode),
  parse() and serialize() functions for AST↔HTML conversion
- MentionPopover: load @repository: from project repos, @ai: from room_ai configs
  (not room members); output new HTML format with ID instead of label
- MessageMentions: use AST parse() for rendering (falls back to legacy parser)
- ChatInputArea: insertMention now produces `<mention type="user" id="...">label</mention>`
- RoomParticipantsPanel: onMention passes member UUID to insertMention
- RoomContext: add projectRepos and roomAiConfigs for mention data sources
2026-04-17 23:43:26 +08:00
ZhenYi
4f1ea95b58 fix(room): add missing stream column to room_ai table
Create migration m20260417_000001_add_stream_to_room_ai that adds
the `stream BOOLEAN NOT NULL DEFAULT true` column to room_ai.
The model definition includes this field but the original migration
was missing it.

Also format libs/api/room/ws.rs and add gitdata.ai to allowed
WS origins.
2026-04-17 23:09:55 +08:00
ZhenYi
a171d691c6 fix(room): align ReactionGroup types with frontend and guard reaction update handler
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
- Fix ReactionGroup.count: i64 -> i32 and users: Vec<Uuid> -> Vec<String>
  to match frontend ReactionItem (count: number, users: string[]).
  Mismatched types caused the WS reaction update to silently fail.
  Also update ReactionItem in api/ws_types.rs to match.
- Add activeRoomIdRef guard in onRoomReactionUpdated to prevent stale
  room state from processing outdated events after room switch.
- Switch from prev.map() to targeted findIndex+spread in onRoomReactionUpdated
  to avoid unnecessary array recreation.
2026-04-17 23:00:52 +08:00
ZhenYi
0cbf6d6aa1 fix(room): accept comma-separated message_ids string in batch reaction endpoint 2026-04-17 22:28:24 +08:00
ZhenYi
a1ddb5d5bc fix(room): add HTTP batch reactions endpoint and clean up dead code
Backend:
- Add reaction_batch handler: GET /api/rooms/{room_id}/messages/reactions/batch?message_ids=...
- Register route in libs/api/room/mod.rs
- Backend already had message_reactions_batch service method, just needed HTTP exposure

Frontend:
- Add ReactionListData import to room-context.tsx
- Fix thisLoadReactions client type (was using broken NonNullable<ReturnType<>>)
- Remove unused oldRoomId variable
- Delete unused useRoomWs.ts hook (RoomWsClient has no on/off methods)
- Remove unused EmojiPicker function and old manual overlay picker from RoomMessageBubble
- Remove unused savedToken variable in room-ws-client
2026-04-17 22:12:10 +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
afb1bbeb71 fix(service): use default_branch for graph and reflog 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
- git_commit_graph: use default_branch when rev is None
- git_commit_graph_react: use default_branch when rev is None
- git_commit_reflog: fall back to default_branch when HEAD is detached

Fixes errors:
- reference 'refs/heads/master' not found (graph-react endpoint)
- HEAD has no name (reflog endpoint when HEAD is detached)
2026-04-17 16:36:44 +08:00
ZhenYi
a4dc507b66 fix(git): multiple branch and upstream query bugs
1. branch_list: Fix is_head comparison
   - head_name now keeps full ref (e.g., "refs/heads/main")
   - Previously stripped to short name causing is_head to always be false

2. branch_get/branch_exists: Fix name resolution for branches with '/'
   - Previously, "feature/testing" was assumed to be a remote branch
   - Now tries both refs/heads/ and refs/remotes/ candidates
   - Correctly handles local branches like "feature/testing"

3. sync_refs: Fix upstream reference format
   - Was storing "refs/remotes/{}/branch" (broken pattern)
   - Now properly queries git2 for actual upstream branch name
2026-04-17 16:30:58 +08:00
ZhenYi
ee4ff6c752 fix(api): fix branch route order to prevent shadowing
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
Move all specific branch routes before /branches/{name} to prevent
route shadowing. Previously, routes like /branches/rename, /branches/move,
/branches/upstream, /branches/diff, etc. were shadowed by /branches/{name}.
2026-04-17 16:11:23 +08:00
ZhenYi
1272615d50 fix(api): fix refs route order to prevent shadowing
Move specific routes (/refs/rename, /refs/update) before parameterized
routes (/refs/{name}) to avoid route shadowing.
2026-04-17 16:10:23 +08:00
ZhenYi
4cee9975d5 fix(api): fix commit route order to prevent InvalidOid("reflog") error
Move specific routes (/commits/reflog, /commits/branches, /commits/tags)
before parameterized routes (/commits/{oid}) to avoid route shadowing.
Previously, /commits/reflog was matched by /commits/{oid} with oid="reflog",
causing InvalidOid("reflog") errors.

Also fixes other potential route shadowing issues in commit routes.
2026-04-17 16:07:01 +08:00
ZhenYi
82ed726848 fix(git): convert default_branch to full ref name (refs/heads/*)
The database stores short branch names (e.g., "main"), but git2's push_ref()
requires full reference names (e.g., "refs/heads/main"). This fixes all
service-layer endpoints to convert default_branch to the full ref format.

Fixed endpoints:
- git_readme: convert to refs/heads/{branch}
- git_commit_count: convert to refs/heads/{branch}
- git_contributors: convert to refs/heads/{branch}
- git_commit_log: convert to refs/heads/{branch}
- git_commit_walk: convert to refs/heads/{branch}

Resolves errors:
- Internal("the given reference name 'main' is not valid")
2026-04-17 15:56:08 +08:00
ZhenYi
4c49953572 fix(git): use default_branch in git_commit_log and update API docs
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
- git_commit_log: default to repo.default_branch when rev is None
- Update API documentation to reflect default_branch instead of HEAD
2026-04-17 15:16:18 +08:00
ZhenYi
2bd1339d6c fix(git): use repo.default_branch instead of HEAD to avoid master/branch mismatch
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 #[serde(default)] to MergeAnalysisQuery.their_oid and MergeRefAnalysisQuery fields
  since they come from path parameters, not query strings
- git_readme/git_commit_count/git_contributors: default to repo.default_branch
  instead of HEAD to avoid errors when HEAD points to refs/heads/master but
  the actual default branch is main
2026-04-17 15:13:08 +08:00
ZhenYi
be423aabb6 feat(error): add error print info to system command
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-17 14:42:51 +08:00
ZhenYi
7a2a3c51c4 fix(git/hook): make sync_tags Send-safe by collecting git2 data synchronously
sync_tags held git2 types (StringArray, Repository) across .await points
on sea-orm DB operations. Applied the same pattern as sync_refs:
- Added collect_tag_refs() sync helper that collects all tag metadata
  (name, oid, description, tagger) into owned TagTip structs.
- sync_tags now calls collect_tag_refs() before any .await, so no git2
  types cross the async boundary.
- Removed #[allow(dead_code)] from TagTip now that it's consumed.
2026-04-17 13:48:05 +08:00