Commit Graph

146 Commits

Author SHA1 Message Date
ZhenYi
30713786bf revert(db): remove check_compatibility — method not available in sqlx 0.8
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
The check_compatibility(false) method was added in the previous commit
but does not exist in sqlx 0.8.x used by sea-orm 2.0. The warning
"Failed to obtain server version" is cosmetic and does not affect
functionality.
2026-04-26 15:49:51 +08:00
ZhenYi
8a23a22c9b fix(agent/sync): make OpenRouter fetch optional, fallback to direct sync
When OpenRouter's public /api/v1/models endpoint fails (network error,
timeout, parse failure), the entire sync was aborted — meaning models
accessible from the user's AI endpoint were never synced.

Now: if OpenRouter fetch fails, fall back to sync_models_direct for all
available models instead of returning an error. Both sync_upstream_models
(API) and sync_once (background task) have this fix.
2026-04-26 15:49:34 +08:00
ZhenYi
31ed420186 fix(db): disable sqlx check_compatibility for non-standard PostgreSQL servers
Cloud-managed PostgreSQL variants (PolarDB, CockroachDB, etc.) may
not return a standard version string, causing:
  "Failed to obtain server version. Unable to check client-server
   compatibility."

Setting check_compatibility(false) on both writer and reader
connections silences this harmless warning.
2026-04-26 15:36:13 +08:00
ZhenYi
638dfd7a6e feat(agent/sync): sync non-OpenRouter models from upstream endpoint
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
When upstream /v1/models returns models not yet in OpenRouter's catalog
(e.g. brand-new models like DeepSeek-V4), also upsert them through the
same pipeline (provider → model → version → pricing → capabilities →
parameter_profile) with inferred defaults, instead of silently dropping
them. Previously the direct-sync fallback only triggered when *zero*
OpenRouter matches existed.
2026-04-26 15:17:33 +08:00
ZhenYi
fb27918285 feat(admin): remove daily report, add platform metrics endpoint
Remove daily report system (page, API routes, cron scheduler) as it is
no longer needed. Add /api/metrics endpoint exposing total and time-
windowed counts (27h, 7d, 30d) for users, workspaces, projects, repos,
rooms, and skills.

Also clean up dead code:
- Remove OpenRouter sync and alerts check routes
- Remove syncModels/checkAlerts from adminrpc client
- Remove unused adminRpcAvailable state from platform sessions page
- Fix handleEdit displayName comparison bug in platform users page
- Simplify pricing sync to create 0-price defaults
2026-04-26 14:44:21 +08:00
ZhenYi
660ffd6acb chore(api): remove entire admin module
Admin Next.js app handles all admin tasks directly via database access.
Only health check endpoint was remaining, not worth maintaining.
2026-04-26 14:08:15 +08:00
ZhenYi
8ea826e6ad chore(api): remove admin billing endpoint
Admin Next.js app handles billing directly via database access now.
2026-04-26 14:05:52 +08:00
ZhenYi
ef767297f7 chore(api): remove admin AI model CRUD routes
Admin Next.js app now handles DB access directly for provider/model/
version/pricing management. Keep only health, sync, alerts, and billing.
2026-04-26 14:04:01 +08:00
ZhenYi
6eb65a5c65 feat(observability): inject _msg field for VictoriaLogs compatibility
Add MsgJsonFormat custom event formatter that outputs JSON with _msg as
the first field, required by VictoriaLogs for full-text search. HTTP
middleware stores interpolated "METHOD /path" in thread-local buffer
for the formatter to read on span-close events.
2026-04-26 13:31:05 +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
f5e3da35b0 feat(room): store ordered streaming chunks + billing integration
- Save thinking_content as {"__chunks__": [{type, content}]} for replay
- Tool call sanitization — don't expose raw results to frontend
- Billing record_ai_usage integration
- Room service module refactoring into service/ directory
2026-04-26 13:10:42 +08:00
ZhenYi
b4b5538447 feat(agent): add ordered stream chunk collection + retry for HTTP errors
- StreamChunk/StreamChunkType types for preserving arrival order
- Chunk collection in call_stream_once and process_stream
- Add "error sending request" and "Http client error" to retryable errors
- StreamResult includes chunks vector for ordered replay
2026-04-26 13:10:26 +08:00
ZhenYi
0b5dc98ce5 refactor(db): simplify read-replica to single connection for CNPG
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
CNPG's cluster-ro service already handles load balancing and failover,
so the application-level Vec + random_range is redundant.

- db_read: Vec<DatabaseConnection> → Option<DatabaseConnection>
- database_read_replicas returns Option<String> instead of Vec<String>
- health checks now explicitly ping both writer() and reader()
- remove unused rand dependency from libs/db
2026-04-26 01:03:39 +08:00
ZhenYi
02b7a5beda feat(gitserver): add /robots.txt to disallow all crawlers
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
- Returns Disallow: / for all user-agents
- Points crawlers to main site sitemap via APP_GIT_HTTP_DOMAIN
2026-04-26 00:16:21 +08:00
ZhenYi
d593354ba9 feat: add sitemap index with static/users/projects/repos sub-sitemaps
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
- Main sitemap index at /sitemap.xml referencing 4 sub-sitemaps
- /sidemap/static: fixed routes (homepage, auth, marketing pages)
- /sidemap/users: public user profiles sorted alphabetically
- /sidemap/projects: public projects sorted alphabetically
- /sidemap/repos: public repos sorted alphabetically
- Redis cache with 8h TTL (no refresh on access), key: sidemap:{type}
- robots.txt Sitemap URL uses main_domain() with https:// forced
- All sitemap loc entries use https:// base URL
2026-04-26 00:06:18 +08:00
ZhenYi
a8494cc032 chore(api): add sidemap module 2026-04-25 23:50:23 +08:00
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