Commit Graph

275 Commits

Author SHA1 Message Date
ZhenYi
96b92fe487 feat(workspace): initialize Rust workspace with core services and dependencies
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-05-01 00:40:29 +08:00
ZhenYi
59f9b66360 feat(workspace): initialize Rust workspace with core services and dependencies
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-05-01 00:15:55 +08:00
ZhenYi
c48f7319ca fix(chat): handle multi-byte character truncation in tool result preview
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-30 23:37:13 +08:00
ZhenYi
5c2369ff47 fix(billing): correct monthly usage calculation query
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-30 19:39:26 +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
08045eef63 refactor(agent): enhance chat service with state management and billing
Add persistent chat session state (ChatState, sequence tracking, tool
calls). Introduce basic billing record in agent crate. Refine chat
service to route messages through state machine with tool support.
2026-04-30 19:16:44 +08:00
ZhenYi
abcfc5b3bb refactor(room): simplify room core modules and connection handling
Extract connection pool management and helper utilities.
Remove redundant metrics indirection, expose counters directly.
Trim room.rs boilerplate and move AI queue logic to room_ai_queue.
2026-04-30 19:16:33 +08:00
ZhenYi
5b81e7d774 refactor(room): refactor AI service modules for cleaner separation
Simplify ai_streaming by delegating to ai_mode_streaming.
Extract sequence coordination into dedicated module.
Add worker pool management for concurrent AI task handling.
Refine ai_react_streaming for better delta chunk handling.
2026-04-30 19:16:23 +08:00
ZhenYi
4ba47370be feat(room): add mode-dispatched AI service orchestration
Add RoomAiService as the central dispatcher that selects execution
path based on mode (react/chat/cot/reflexion/rewoo) and streams
vs nonstreaming preference. Replace monolithic ai_streaming with
mode-aware dispatch and dedicated streaming implementation.
2026-04-30 19:16:11 +08:00
ZhenYi
27b9d3e4bd feat(agent): add CoT, Reflexion, and ReWOO reasoning modes
Implement three alternative reasoning strategies:
- Chain-of-Thought (cot): explicit step-by-step reasoning
- Reflexion: self-critique with revise cycle
- ReWOO: reasoning with external observation tokens
2026-04-30 19:15:55 +08:00
ZhenYi
009ccee72b fix(embed): add debug tracing to all embed methods
Added tracing::debug/info calls to embed_issue, embed_repo,
embed_issues, embed_skill to track embedding API calls and upsert completion.
2026-04-29 15:35:25 +08:00
ZhenYi
6a60d02263 fix(qdrant): reject empty vectors in upsert_points
Prevent Qdrant from rejecting entire batches when any point
has an empty vector. Log error with count before failing.
2026-04-29 15:35:22 +08:00
ZhenYi
395832118e fix(embed): add comprehensive diagnostic tracing for Qdrant
- client.rs: detect document mismatch in embed_batch, warn on empty vectors
- qdrant.rs: reject empty vectors with error logging
- service.rs: add debug/info tracing to embed_issue, embed_repo, embed_issues, embed_skill
2026-04-29 15:35:18 +08:00
ZhenYi
03f97c9221 fix(agent): spawn tool execution in separate task for heartbeat
Move tool execution to a spawned task so synchronous git2 operations
don't block the tokio worker thread, allowing heartbeat chunks to be
sent every 10s during long tool execution.

Also add analysis-first reasoning prompt to system messages.
2026-04-29 09:03:29 +08:00
ZhenYi
30822bbd7d fix(skill): support bare repo scanning via git tree traversal
Add scan_repo_tree_for_skills and scan_skills_from_tree functions that
traverse git objects directly instead of filesystem, enabling skill
discovery in bare repositories created via git2::Repository::init_bare.
2026-04-29 09:03:22 +08:00
ZhenYi
b673c31485 feat(fctool): register new git tools in mod.rs
Register repo_analysis, kb, and repo_util tool modules in the
git_tools register_all function.
2026-04-29 09:03:13 +08:00
ZhenYi
a5704c9730 feat(fctool): add repo utility tools for AI
Add repo_search, repo_readme, repo_commit_log, repo_contributors,
and repo_diff_summary function call tools for AI to search code,
read README, query commit history, list contributors, and diff revisions.
2026-04-29 09:03:03 +08:00
ZhenYi
4ef0d5b570 feat(fctool): add knowledge base tools for AI
Add repo_doc_index, repo_doc_read, and repo_doc_search function call
tools for AI to index, read, and search through documentation repos.
2026-04-29 09:02:56 +08:00
ZhenYi
5f12b07120 feat(fctool): add repo analysis tools for AI
Add repo_overview, repo_file_tree, repo_languages, and repo_dependencies
function call tools for AI to quickly analyze repository structure,
language breakdown, and dependency manifests.
2026-04-29 09:02:51 +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
5351df773b fix(api): register skill routes inside project scope to fix 404
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
In actix-web, separate web::scope() trees don't merge. The /projects
scope was intercepting /api/projects/{name}/skills before the separate
skill scope could match, causing 404 on all skill endpoints.

Move skill routes into init_project_routes as /{project_name}/skills/*
and remove the standalone configure(skill::init_skill_routes) call.
2026-04-28 22:58:57 +08:00
ZhenYi
108dd714d3 fix(room): include @user mentions in AI prompt context
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
- Extend extract_mention_context to handle user mentions
- Both @[repo:xxx] and @[user:xxx] are now included in AI context
2026-04-28 22:25:25 +08:00
ZhenYi
76e3d19cf5 fix(room): require @ai mention to trigger AI response
- process_message_ai now returns early if no @ai mention is found
- Verify mentioned AI exists in the room before responding
2026-04-28 22:21:12 +08:00
ZhenYi
55d33862f6 fix(room): support multiple AIs per room in should_ai_respond
- Add get_room_ai_configs() to fetch all AI configs for a room
- Check all AI model IDs against @ai mentions
2026-04-28 22:16:04 +08:00
ZhenYi
46a0bdc21e fix(room): should_ai_respond only triggers on @ai mention 2026-04-28 22:14:10 +08:00
ZhenYi
c2c079c74d fix(room): invert use_exact logic so it controls all-message mode
Previously: use_exact=false → respond to all messages (wrong default)
Now: use_exact=true → respond to all messages; use_exact=false → only @ai
2026-04-28 22:10:21 +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
b3fb027848 fix(git): deduplicate skills by repo_id+blob_hash in hook sync
- Apply same deduplication logic as service scanner
- Keep latest version by commit_sha when duplicates found
- Fix type error: Ok("skill.md") → Some("skill.md".to_string())
2026-04-28 21:28:19 +08:00
ZhenYi
2db7934596 fix(skill): deduplicate skills by repo_id+blob_hash
- Change deduplication key from slug to {repo_id}+{blob_hash}
- Keep latest version by commit_sha when duplicates found
- Use git2 to open repos and get correct workdir and commit_sha
- Fix case-insensitive SKILL.md detection in scanner
2026-04-28 21:27:38 +08:00
ZhenYi
18917b6de1 feat(room): 修改 AI use_exact 默认值为 true
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
- room/src/ai.rs: use_exact 默认值从 false 改为 true
- 新增 migration: m20260428_000002_default_use_exact_true
2026-04-28 20:00:12 +08:00
ZhenYi
4571d4d042 fix(service): 修复扣费结果类型处理
- service/agent/billing.rs: 适配新的 BillingResult 枚举类型
- 将 InsufficientBalance 错误转换为 AppError::BadRequest
2026-04-28 19:59:17 +08:00
ZhenYi
c6bb72682b fix(agent): 修复扣费链路并实现级联扣费策略
- billing.rs: 修复参数传递 (model_id -> version_id)
- billing.rs: 新增 BillingResult 枚举支持 InsufficientBalance 错误
- billing.rs: 实现级联扣费 (优先 project 余额,不足时 fallback 到 workspace)
- billing.rs: 余额不足时创建系统消息并持久化
- chat/service.rs: 捕获 InsufficientBalance 错误并调用 create_system_message
- client/mod.rs: 超时时间从 60s 改为 120s
2026-04-28 19:59:06 +08:00
ZhenYi
13523762aa fix(fctool): 修复 git tools 中的类型不匹配问题
- blob.rs: 修复 resolve_oid 返回 commit OID 而非 blob OID 的问题
- tree.rs: 修复 git_tree_ls_exec 直接传递 commit OID 给 tree_list 的问题
- 所有修改使类型合约与 git domain API 匹配
2026-04-28 19:58:52 +08:00
ZhenYi
5a90a475a4 feat(migrate): add content_tsv backfill migration for full-text search
Populate content_tsv column on existing messages for PostgreSQL FTS support.
2026-04-28 13:12:38 +08:00
ZhenYi
3643991955 fix(triage): improve AI issue triage with better prompt and label handling 2026-04-28 13:12:34 +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
bbeaea6614 fix(billing): remove old billing module, delegate to record_ai_session
Billing is now handled internally by chat_service.process via record_ai_session.
Remove the old billing.rs file and explicit record_ai_usage calls from all 4
AI streaming modes (nonstreaming, react_nonstreaming, react_streaming, streaming).
2026-04-28 13:12:25 +08:00
ZhenYi
2a9ec6d509 feat(tag): vectorize repo tags after hook sync with incremental embedding + FC tool
- HookWorker gains optional embed_service field
- Captures changed tag names during webhook dispatch, batch-embeds after completion
- HookService auto-inits EmbedService from config for standalone git-hook binary
- Adds agent dep to git crate (no circular dep)
- SSH/HTTP servers no longer call start_worker (dedicated git-hook handles it)
- git_tag_search FC tool for agent semantic tag search with project isolation
2026-04-28 13:04:10 +08:00
ZhenYi
62727a93a1 feat(service): trigger Qdrant embedding on issue/repo/skill creation
- After issue_create: spawn embed_issue_chunked (non-blocking)
- After skill_create/update: spawn embed_skill
- After repo create/update in fctool: spawn embed_repo
- Wire EmbedService through AppService, available for all triggers
2026-04-28 13:04:04 +08:00
ZhenYi
93ec515f29 feat(room): batch-embed all room messages into Qdrant on persist
- make_persist_fn now accepts embed_service, collects persisted text messages
- Filters non-text, non-empty, non-system/tool messages
- Groups by room→project_name, batch-embeds via embed_memories_batch
- Removes old per-message synchronous embed_memory call
- Workers thread embed_service through to persist_fn
2026-04-28 13:03:59 +08:00
ZhenYi
026f5cf32d feat(context): thread embed_service through ToolContext for FC tool access
Add with_embed_service() builder and embed_service() accessor to ToolContext,
wired through ChatService so function-calling tools can access Qdrant vector search.
2026-04-28 13:03:55 +08:00
ZhenYi
bfdb934443 feat(embed): add chunked embedding, batch memory embed, and tag vectorization support
- chunk_text(): char-boundary-safe text chunking at paragraph/sentence breaks (7000 char limit)
- embed_memories_batch(): groups messages by room, batch-embeds all texts to reduce Qdrant calls
- embed_issue_chunked(): auto-chunks long issue bodies
- embed_skill(): upgraded with auto-chunking via chunk_text
- TagEmbedInput struct for batch tag embedding
- embed_tags_batch() / search_tags() with project isolation
- ensure_collections() now creates embed_repo_tag collection
2026-04-28 13:03:51 +08:00
ZhenYi
32d7b3b902 fix(billing): use actual tokens in nonstreaming ReAct billing
- ai_react_nonstreaming now passes real input/output tokens to billing
- Was passing hardcoded 0,0 despite destructuring token data
- Also fix unused variable warnings
2026-04-28 11:06:57 +08:00
ZhenYi
8a6ec1f62f fix(billing): add transaction isolation and fix race conditions
Critical fixes:
- Wrap balance updates in database transactions with SELECT FOR UPDATE
- Move history insert after balance validation to prevent orphaned records
- Use Decimal throughout to avoid silent conversion failures
- Prevent concurrent requests from causing negative balances

Tasks resolved:
- Task #4: Silent Decimal conversion failures
- Task #5: Missing transaction isolation (race conditions)
- Task #6: History inserted before validation
2026-04-28 10:12:24 +08:00
ZhenYi
6edacbcdf2 fix(billing): track actual tokens in ReAct mode instead of hardcoded 0/0
- process_react now returns (String, i64, i64) tuple with token counts
- Extract token stats from rig Agent FinalResponse usage field
- Both streaming and non-streaming ReAct modes now bill correctly
2026-04-28 10:04:54 +08:00
ZhenYi
7f927a4b6b fix(billing): pass real project_id instead of Uuid::nil() for cost calculation 2026-04-28 09:57:45 +08:00
ZhenYi
211cf0ee3e fix(agent): calculate and record cost in ai_session table
- Add record_ai_session() helper calling billing::record_ai_usage()
- Replace all Set(None) cost/currency with actual calculated values
- Cost computed from model_pricing via Decimal precision
2026-04-28 09:50:44 +08:00
ZhenYi
7b43f55f41 refactor(fctool): add descriptions to tools and simplify model sync
- Add description field to all fctool file and git tools
- Simplify extract_model_name in sync.rs (use upstream id directly)
2026-04-28 09:43:15 +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
5b3a6700be refactor(agent): replace custom ReAct loop with rig::agent::Agent
- Use AgentBuilder for native tool-calling with stream_prompt()
- Add RecordingTool wrapper preserving retry + DB recording
- Fix tool_choice bug in do_completion (same as call_stream_once)
- Add seq field to RoomMessageStreamChunkEvent for strict ordering
- Map streaming events: Text→Answer, Reasoning→Thought, ToolCall→Action
- Only final event has done=true, removed premature stream ending
- Store __chunks__ JSON in thinking_content for ordered replay
2026-04-28 09:42:36 +08:00
ZhenYi
bc7a5a6549 fix: resolve remaining warnings and fix API method name
- issue_triage.rs: use check_project_access instead of nonexistent get_project_member
- email/lib.rs: make EMAIL_REGEX pub to suppress dead_code warning
- tracing_fmt.rs: minor import ordering cleanup and code formatting
2026-04-27 16:42:01 +08:00
ZhenYi
afad0ab55d feat(agent): implement built-in skills system (16 skills)
Add built-in skills with trigger-based activation system:

Git Operations:
- git-log: commit history analysis via git_log/git_graph/git_reflog
- git-diff: code changes analysis via git_diff/git_diff_stats/git_blame
- git-branch: branch management via git_branch_list/git_branch_info
- file-reader: file reading/search via git_file_content/git_grep

Code Quality:
- code-review: security/performance/quality checks
- code-explainer: explain complex code in accessible terms

Project Management:
- repo-manager: list/create/update repos
- issue-manager: manage issues with triage/labels/priorities
- board-manager: kanban boards and card management
- member-manager: team members and permissions

Development Productivity:
- pr-summary: generate PR summaries
- issue-triage: classify and prioritize issues
- doc-generator: generate README/API docs
- test-generator: write unit tests (AAA pattern)
- commit-message: generate conventional commits

Utilities:
- http-requester: HTTP requests and API testing

Skills integrated via PerceptionService with active/passive/auto triggers
Built-in skills automatically available to all projects
Database skills override built-in skills with same slug
2026-04-27 16:40:59 +08:00
ZhenYi
e7a250357f fix(room): add cascade deletes and fix QuerySelect trait import
- Import room_message_reaction, room_message_edit_history, room_notifications modules
- Fix room_message_edit_history: no Room column, use subquery via messages
- Change publish_project_room_event from Result to () handling
- Add QuerySelect import for limit() method in workers.rs
2026-04-27 16:40:28 +08:00
ZhenYi
e022240757 feat(agent): model sync improvements - deduplication and offline status
- Add Offline status to ModelStatus enum
- Sync marks all models offline first, then activates found ones
- Deduplicate by model name (ignoring provider)
- Deactivate orphaned models (offline -> deprecated)
- Add models_offline and models_deactivated to SyncModelsResponse
- Add deduplicate_existing_models() for cleanup
- Rename upsert_model to upsert_model_by_name
2026-04-27 16:40:10 +08:00
ZhenYi
52a0131b56 fix(git): LFS token validation and remove IP rate limiting
- Implement proper token validation via user_token table (SHA256+base64 hash)
- Query token_hash, check IsRevoked, validate expiry
- Remove IP-based rate limiting (handled by k8s ingress)
- Remove unused client_ip() helper function
- user_uid() now async and queries database for real user
2026-04-27 16:40:01 +08:00
ZhenYi
ef529d772b fix(service): resolve backend compilation errors
- access_key.rs: use rand::rng() and random_range() for rand 0.10 API
- access_key.rs: fix update() returns DbErr, add .map_err(AppError::from)
- sync.rs: upsert_provider expects &str not String
- sync.rs: add QueryOrder import for order_by_asc
- issue.rs: change %e to ?e for Debug trait instead of Display
- workspace/info.rs: add missing closing brace in struct literal
2026-04-27 16:39:52 +08:00
ZhenYi
88dd3a5f61 fix: log silently dropped errors in compaction and SSH path handling
- Add tracing::warn! when conversation compaction fails (was let _ = e)
- Add tracing::debug! when SSH path canonicalize fails (was let _ = e)
2026-04-27 14:01:25 +08:00
ZhenYi
0a272ed63a fix: start SSH rate limiter cleanup and fix ToolContext reset per tool call
- Start SSH rate limiter cleanup task that was missing (prevent memory leak)
- Create single ToolContext outside tool execution loop so max_tool_calls
  and max_depth guards actually fire across batch tool calls (was creating
  fresh context per call, bypassing all limits)
2026-04-27 13:57:47 +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
f36f08e3c4 fix: remaining unwrap panics and new bugs discovered during audit
- email worker: replace Mailbox::parse().unwrap() with match to
  handle invalid recipient addresses gracefully
- metrics middleware: RwLock poison recovery on read/write locks
  to prevent panic on thread panic
- access key: SystemTime::now() unwrap_or_default instead of unwrap
  for clock-before-epoch edge case
- chpc: NaiveDateTime and_hms_opt unwrap_or MIN/MAX fallbacks
- push notification: second code path fixed for let-chain unwrap
- ai_streaming: constant UUID parse use expect() instead of unwrap
2026-04-27 11:30:01 +08:00
ZhenYi
df42af2ed0 fix: remaining push notification unwrap in second code path
- Fix second copy of push_subscription unwrap that was in a
  tokio::spawn block with different indentation
- Replace constant UUID parse unwrap with expect()
2026-04-27 11:23:48 +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
763d47dc45 fix: silent AI billing failures — add tracing::warn for billing errors 2026-04-27 11:15:15 +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
3f1f0d5e23 chore(service/git): minor fixes in service layer git operations
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
Small adjustments to commit, init, refs, star, and watch operations
in the service layer.
2026-04-27 08:28:27 +08:00
ZhenYi
64dc27161b chore(git): minor fixes and improvements across git library modules
Apply small fixes across multiple git ops files: handle errors, improve
type safety, and refine HTTP handler and SSH git operations.
2026-04-27 08:28:09 +08:00
ZhenYi
adbc0705db feat(room): inject repository details into AI system prompt on mention
When a user mentions a repository in room chat, extract the repo name
from @[repo:name:label] brackets, look up the full repo model from the
database, and inject its details (name, description, default branch,
visibility) into the AI message context. Works independently of
embed_service availability.
2026-04-26 23:58:52 +08:00
ZhenYi
d72019e39f feat(room): add WS events for AI config and repo lifecycle changes
Add RoomAiUpdated, RepoCreated, RepoUpdated, RepoDeleted event types.
Publish RoomAiUpdated after room_ai upsert/delete and repo events
after repo create/update. Always set model_name in AI list response
(fallback to "AI {uuid}" when model lookup fails) so frontend never
displays a raw UUID.
2026-04-26 23:58:33 +08:00
ZhenYi
283835eb26 fix(agent/sync): avoid double /v1/ prefix in model sync URL
When APP_AI_BASIC_URL already ends with /v1 (e.g. openrouter.ai/api/v1),
appending /v1/models produces /v1/v1/models. Detect trailing /v1 and
only append /models in that case.
2026-04-26 23:58:25 +08:00
ZhenYi
c7a8bc0458 refactor(fctool): extract tool modules into standalone fctool crate
Move git_tools, file_tools, and project_tools from libs/service into a
new libs/fctool crate with correct workspace dependencies. Fixes the
rev.len() >= 40 bug in all git tool resolve functions (OID check needs
exact 40-char hex, not just >= 40). Adds 4 new git blob tools
(blob_get, blob_exists, blob_content, blob_create). Fixes parameter
naming inconsistency in repos.rs and adds project_name to list_repos
output. Removes unused excel/pdf/ppt/word file tools.
2026-04-26 23:58:16 +08:00
ZhenYi
0e53f4a69f fix(room): fix two major memory leaks
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
1. WS disconnect now unsubscribes from user_notification_inner.
   Previously, every WebSocket connection created a broadcast channel
   for user notifications that was never removed on disconnect, causing
   unbounded growth proportional to unique connected users over time.

2. Room worker tasks now use the manager's room_shutdown_txs channel
   instead of a local broadcast channel. shutdown_room() sends on this
   channel, so when a room is deleted the worker task receives the signal
   and terminates, releasing its DashMap (capacity 10,000) and all
   captured closures. Previously the worker ran forever.
2026-04-26 16:52:20 +08:00
ZhenYi
7d7103e271 feat(observability): use human-readable log format for terminals
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
When stdout is connected to a TTY, use tracing_subscriber's pretty
format with colors instead of single-line JSON. Non-TTY (container
logs, pipes) continue to output JSON for log aggregation.

Override auto-detection via APP_LOG_FORMAT=json|pretty.

Also adds APP_LOG_PRETTY=true to use serde_json::to_string_pretty
for human-readable JSON output (useful for development/debugging).
2026-04-26 16:39:03 +08:00
ZhenYi
ecf9f33b26 refactor(agent/sync): remove OpenRouter dependency, use upstream /v1/models directly
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 upstream AI endpoint already returns complete model metadata:
- name, owned_by, context_length, max_output_tokens
- capabilities (vision, tool_call, reasoning)
- pricing (input, output, cache_read, cache_write, currency)

Remove the OpenRouter fallback entirely and parse the upstream
response directly for all sync operations. Both sync_upstream_models
(API) and sync_once (background task) now use a single unified path.

Changes:
- Remove OpenRouter types and fetch_openrouter_models()
- Add UpstreamModel / UpstreamCapabilities / UpstreamPricing types
- Parse capabilities from upstream instead of inferring from name
- Use real pricing from upstream instead of defaulting to 0.00
- Simplify sync flow: list → parse → upsert (no filtering/matching)
- Add provider normalizations for moonshot, zai, minimax, qwen
2026-04-26 16:30:41 +08:00
ZhenYi
a8e3b0f5a8 fix(agent/sync): handle multiple /v1/models response formats
The upstream AI endpoint returns an OpenAI-compatible format, but the
response body parsing was fragile. Make it resilient:
1. Try standard OpenAI format: { "data": [{id}, ...] }
2. Try raw array: [{id}, ...]
3. Try alternate format: { "models": [{id}, ...] }
4. Log actual response body (first 500 chars) when all formats fail

Also adds a warning log with the raw response on parse failure so
future debugging is straightforward.
2026-04-26 16:26:57 +08:00
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