Commit Graph

32 Commits

Author SHA1 Message Date
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
a0ab16e6ea feat(agent): pass AppConfig through ToolContext and fix tool call handling 2026-04-20 19:32:03 +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
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
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
3de4fff11d feat(service): improve model sync and harden git HTTP/SSH stability
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
Model sync:
- Filter OpenRouter models by what the user's AI client can actually access,
  before upserting metadata (avoids bloating with inaccessible models).
- Fall back to direct endpoint sync when no OpenRouter metadata matches
  (handles Bailian/MiniMax and other non-OpenRouter providers).

Git stability fixes:
- SSH: add 5s timeout on stdin flush/shutdown in channel_eof and
  cleanup_channel to prevent blocking the event loop on unresponsive git.
- SSH: remove dbg!() calls from production code paths.
- HTTP auth: pass proper Logger to SshAuthService instead of discarding
  all auth events to slog::Discard.

Dependencies:
- reqwest: add native-tls feature for HTTPS on Windows/Linux/macOS.
2026-04-17 00:13:40 +08:00
ZhenYi
a09ff66191 refactor(room): remove NATS, use Redis pub/sub for message queue
- Remove async-nats from Cargo.toml dependencies
- Rename nats_publish_failed metric → redis_publish_failed
- Update queue lib doc comment: Redis Streams + Redis Pub/Sub
- Add Paused/Cancelled task statuses to agent_task model
- Add issue_id and retry_count fields to agent_task
- Switch tool executor Mutex from std::sync → tokio::sync (async context)
- Add timeout/rate-limited/retryable/tool-not-found error variants
2026-04-16 17:24:04 +08:00
ZhenYi
93cfff9738 init 2026-04-15 09:08:09 +08:00