81 lines
9.1 KiB
Markdown
81 lines
9.1 KiB
Markdown
---
|
||
session: ses_2338
|
||
updated: 2026-04-27T01:04:57.050Z
|
||
---
|
||
|
||
# Session Summary
|
||
|
||
## Goal
|
||
Produce a detailed architectural review report of the Gemini Nexus Electron + NestJS backend, including subsystem ratings (SOLID/NEEDS_WORK/RISKY), specific bugs with file:line references, and concrete refactoring steps.
|
||
|
||
## Constraints & Preferences
|
||
- Focus on coupling between Electron main and NestJS (registry bridge pattern), service decomposition, data flow integrity, error handling, DB transaction safety, and circuit breaker/rate limiter effectiveness
|
||
- Use exact file paths and line numbers where possible
|
||
- Return findings as a detailed markdown report with the requested structure
|
||
- Preserve all previous analysis context when continuing
|
||
|
||
## Progress
|
||
### Done
|
||
- [x] Read `src/main.ts` — Electron main process bootstraps NestJS as child process via `bootstrapNestServer()`, stops via `stopNestServer()`; creates MessagePort for ORPC IPC; installs native modules via Sentry; manages window lifecycle
|
||
- [x] Read `src/server/main.ts` — NestFactory creates Fastify app, enables CORS, registers API logging plugin; exports `stopNestServer` and `getCurrentProxyPort`; no graceful shutdown beyond `app.close()`
|
||
- [x] Read `src/ipc/proxy-advanced/service-registry.ts` — global mutable `proxyAdvancedRegistry` object with `tokenManager`, `proxyMetrics`, `proxyReplay`, `proxyIdeConfig` all initialized to `null`; services register themselves via `registerProxyAdvancedService()` in constructors
|
||
- [x] Read `src/ipc/proxy-advanced/handler.ts` — IPC handlers for traffic logs, metrics, replay, IDE configs, model capabilities; uses `proxyAdvancedRegistry` for IDE config, metrics, replay; directly calls `TrafficLogsRepo` and `CloudAccountRepo` for logs
|
||
- [x] Read `src/ipc/proxy-advanced/router.ts` — ORPC Zod schemas for IPC routes; defines `getModelCapabilities` calling handler; `CapabilitiesResponseSchema` uses hardcoded zod shapes, no dynamic model discovery
|
||
- [x] Read `src/server/modules/proxy/proxy.service.ts` (2222+ lines) — Core proxy logic: request transformation (Claude/OpenAI ↔ Gemini), streaming/non-streaming paths, tool call handling, fallback to non-streaming on stream error, retry logic with `calculateRetryDelay`, circuit breaker check via `tokenManager.getNextToken()`, token refresh, traffic logging via `trafficLogger`
|
||
- [x] Read `src/server/modules/proxy/proxy.controller.ts` (~1700 lines) — HTTP routes for OpenAI (`/chat/completions`, `/models`), Anthropic (`/v1/messages`), Gemini (`/models/:model:generateContent`, etc.); SSE streaming via RxJS; `listModelCapabilities` uses hardcoded `capabilitiesMap` (lines 1316–1352); multipart/form-data proxy; error response normalization; heavy controller with private utility methods mixed in
|
||
- [x] Read `src/server/modules/proxy/token-manager.service.ts` (1303 lines) — Round-robin token scheduling with `schedulingMode` (`cache-first`, `balance`, `performance-first`), circuit breaker per token (`CircuitBreakerEntry` with `failureCount`, `state`, `requestLog`), rate limit tracking via `RateLimitTracker`, model quota/limit management, account refresh via `GoogleAPIService`, auto-registers into `proxyAdvancedRegistry` in constructor
|
||
- [x] Read `src/server/modules/proxy/rate-limit-tracker.ts` — In-memory `failureCounts` map with `FAILURE_COUNT_EXPIRY_MS` (1 hour); parses Google error details; `cleanupExpired()` exists but no scheduled caller found in any read file
|
||
- [x] Read `src/server/modules/proxy/proxy-replay.service.ts` — In-memory circular buffer (`buffer: ReplayEntry[]`, `maxSize = 20`); records requests for replay; auto-registers into `proxyAdvancedRegistry`; no persistence
|
||
- [x] Read `src/services/CloudMonitorService.ts` — 5-minute interval polling (`monitorIntervalMs = 300000`) via `setInterval`; checks account quotas via `GoogleAPIService.getAllQuotaData()`; sends Electron `Notification` on low quota; triggers `AutoSwitchService.findBestAccount()` and `switchCloudAccount()`; updates DB via `CloudAccountRepo.updateAccount()`
|
||
- [x] Read `src/services/AutoSwitchService.ts` — Static methods only; `findBestAccount()` filters by status `active`, checks `quota.models` for `< 5%`, sorts by average quota; calls `switchCloudAccount()` directly from main process context
|
||
- [x] Read `src/ipc/database/cloudHandler.ts` (first ~600 lines) — `CloudAccountRepo` with AES-256-GCM encryption via `encrypt`/`decryptWithMigration`; retry logic for SQLite busy errors (`SQLITE_MAX_RETRIES = 3`); Drizzle ORM operations; no explicit `BEGIN TRANSACTION` wrappers observed in read sections; updates happen via individual `db.update()` calls
|
||
|
||
### In Progress
|
||
- [ ] Synthesizing findings into the final markdown report with subsystem ratings and concrete refactoring proposals
|
||
|
||
### Blocked
|
||
- (none)
|
||
|
||
## Key Decisions
|
||
- **Prioritize reading source over generating report immediately**: Needed exact line numbers and behavior confirmation before making claims about race conditions, transaction safety, and registry nullability.
|
||
|
||
## Next Steps
|
||
1. Synthesize all read file contents into the requested markdown report structure:
|
||
- Deep architectural review (coupling, decomposition, data flow, error handling, DB transactions, circuit breaker/rate limiter)
|
||
- Specific bugs/anti-patterns with file:line references
|
||
- Subsystem ratings (IPC, Proxy, DB, Auth)
|
||
- Concrete refactoring steps
|
||
2. Cross-reference `proxyAdvancedRegistry` null-handling paths in `handler.ts` with specific fallback behavior
|
||
3. Verify `RateLimitTracker.cleanupExpired()` caller absence and document as finding
|
||
4. Document proxy monolith splitting strategy based on observed responsibilities in `proxy.service.ts` and `proxy.controller.ts`
|
||
|
||
## Critical Context
|
||
- **Registry null hazard**: `proxyAdvancedRegistry` starts all-null; IPC handlers return empty fallbacks when NestJS is not running. In `handler.ts`, `generateIdeConfig` and `getProxyMetrics` guard against null registry entries; `getModelCapabilities` does not use registry but ProxyController hardcodes capabilities.
|
||
- **No scheduled `cleanupExpired()`**: `rate-limit-tracker.ts:107` defines `cleanupExpired()`, but no `setInterval` or cron job was found in `token-manager.service.ts`, `proxy.service.ts`, `main.ts`, or `CloudMonitorService.ts`. Failure counts may leak memory over long uptimes.
|
||
- **In-memory only state**: `ProxyReplayService` uses a 20-entry in-memory buffer; `switchMetrics.ts` mentioned in exploration but file not read yet; `RateLimitTracker` is in-memory only (no SQLite persistence).
|
||
- **Proxy monolith responsibilities observed**:
|
||
- `proxy.service.ts`: Request transformation (Claude/Gemini/OpenAI), streaming state machine (`PartProcessor`), retry logic, token acquisition, tool call normalization, schema normalization, user-agent resolution, traffic logging
|
||
- `proxy.controller.ts`: Route handling, SSE emission, multipart proxy, model listing, capability hardcoding, error response formatting (OpenAI/Anthropic/Gemini shapes), request parsing
|
||
- **AutoSwitch race potential**: `AutoSwitchService.findBestAccount()` is static and reads from DB; `CloudMonitorService` runs on a 5-minute timer in main process and calls `switchCloudAccount()` directly. If multiple monitors or manual switches run concurrently, there is no distributed lock or transaction around the switch operation.
|
||
- **Circuit breaker implementation**: `token-manager.service.ts` maintains per-token `CircuitBreakerEntry` with `failureCount`, `lastFailureTime`, `state` (`healthy`/`degraded`/`unhealthy`), and a `requestLog` array. No external library used; custom logic.
|
||
- **CloudAccountRepo retry pattern**: Uses `SQLITE_MAX_RETRIES = 3` with `SQLITE_BUSY_TIMEOUT_MS = 3000` for busy/locked errors, but reads showed Drizzle individual operations without explicit transaction boundaries around multi-step updates.
|
||
|
||
## File Operations
|
||
### Read
|
||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\ipc\database\cloudHandler.ts`
|
||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\ipc\proxy-advanced\handler.ts`
|
||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\ipc\proxy-advanced\router.ts`
|
||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\ipc\proxy-advanced\service-registry.ts`
|
||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\main.ts`
|
||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\server\main.ts`
|
||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\server\modules\proxy\proxy-replay.service.ts`
|
||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\server\modules\proxy\proxy.controller.ts`
|
||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\server\modules\proxy\proxy.service.ts`
|
||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\server\modules\proxy\rate-limit-tracker.ts`
|
||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\server\modules\proxy\token-manager.service.ts`
|
||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\services\AutoSwitchService.ts`
|
||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\services\CloudMonitorService.ts`
|
||
|
||
### Modified
|
||
- (none)
|