style(design): apply Minimal Dark Mode design system\n\n- Switched to complete Dark Mode (OLED-friendly)\n- Established standard color palette matching modern technical aesthetics\n- Changed font to Plus Jakarta Sans for increased legibility\n- Enforced dark mode as default in App.tsx\n- Fixed several React cascading render (setState in useEffect) warnings
This commit is contained in:
1 parent
b80531f8a8
commit
bac7b5591e
738 files changed
+138513
-138123
No files matched your search
@@ -1,74 +1,74 @@
|
||||
---
|
||||
session: ses_2337
|
||||
updated: 2026-04-27T01:38:43.330Z
|
||||
---
|
||||
|
||||
# Session Summary
|
||||
|
||||
## Goal
|
||||
Implement all Package C — Backend Architecture (Quick Wins) fixes in the Gemini Nexus codebase and verify with `npm run lint`, `npm run type-check`, and `npm test`.
|
||||
|
||||
## Constraints & Preferences
|
||||
- Make minimal, focused changes; do not touch files outside Package C scope
|
||||
- Do not run `git commit` or `git push`
|
||||
- Run `npm run lint` and `npm run type-check` after changes and fix any introduced issues
|
||||
- `npm test` must not break any existing tests (update test expectations if needed to match new behavior)
|
||||
|
||||
## Progress
|
||||
### Done
|
||||
- [x] **C-P0-1** — `src/ipc/proxy-advanced/handler.ts`: Replaced silent empty fallbacks with explicit errors for `getParityCounters`, `getCircuitBreakerStatus`, `getProxyMetrics`, `getRecentRequests`, `replayRequest`, and `generateIdeConfig`. Added `normalizeServiceError()` helper to map `getServiceOrThrow` errors to `{ success: false, error: 'Proxy advanced service not initialized' }`.
|
||||
- [x] **C-P0-2** — `src/server/modules/proxy/rate-limit-tracker.ts`: Extended `cleanupExpired()` to iterate `this.failureCounts` and delete stale entries where `entry.lastFailureMs + FAILURE_COUNT_EXPIRY_MS <= now`. Return value now counts both lockouts and failureCounts deletions.
|
||||
- [x] **C-P0-3** — `src/server/modules/proxy/request-user-agent.ts`: Replaced hardcoded `FALLBACK_VERSION = '1.22.2'` with `import { version } from '../../../../package.json'` and `export const FALLBACK_VERSION = version`. `resolveJsonModule` is already enabled in `tsconfig.json`.
|
||||
- [x] **C-P1-1** — `src/server/modules/proxy/proxy.controller.ts`: Replaced hardcoded `capabilitiesMap` with `const capabilitiesMap = this.buildCapabilitiesMap()`. Added private `buildCapabilitiesMap()` that iterates `this.tokenManager?.getAllTokens()` and derives capabilities from `quota.models` metadata.
|
||||
- [x] **C-P1-1 prerequisite** — `src/server/modules/proxy/token-manager.service.ts`: Exported `TokenData` and `TokenEntry` types; added `getAllTokens(): TokenEntry[]` method returning `Array.from(this.tokens.entries())`.
|
||||
- [x] **C-P1-2** — `src/ipc/proxy-advanced/service-registry.ts`: Added typed `getServiceOrThrow<K extends keyof ProxyAdvancedRegistry>(key: K)` helper. Refactored `handler.ts` to use it; a `normalizeServiceError` wrapper preserves the exact P0 error message.
|
||||
|
||||
### In Progress
|
||||
- [ ] Update `src/tests/unit/ipc/proxy-advanced-handler.test.ts` expectations to match the new error responses (null-registry tests now expect `success: false` and `'Proxy advanced service not initialized'` instead of empty success data or old service-specific messages).
|
||||
- [ ] Run `npm run type-check` to validate changed backend files.
|
||||
- [ ] Run `npm run lint` to validate changed backend files.
|
||||
- [ ] Run `npm test` to ensure no regressions.
|
||||
|
||||
### Blocked
|
||||
- (none)
|
||||
|
||||
## Key Decisions
|
||||
- **Reconciled P0 and P1-2 in handler.ts**: Since `getServiceOrThrow` throws a different message than the P0-required `'Proxy advanced service not initialized'`, added a `normalizeServiceError` helper that detects the "is not registered" substring and rewrites it to the P0 message before returning in the success/error envelope. This allows `getServiceOrThrow` to be used (satisfying P1-2) while preserving the exact P0 contract.
|
||||
- **Dynamic capabilities heuristic**: `buildCapabilitiesMap()` derives `vision` from `modelInfo.supports_images`, sets `streaming`/`jsonMode` to `false` only for `gemini-3-pro-image` models, and sets `imageGeneration: true` only for `gemini-3-pro` variants that do not include `flash`. Falls back to a default `gemini-3-flash` entry when no models are discovered.
|
||||
|
||||
## Next Steps
|
||||
1. Update `src/tests/unit/ipc/proxy-advanced-handler.test.ts` null-registry tests for `getParityCounters`, `getCircuitBreakerStatus`, `getProxyMetrics`, `getRecentRequests`, `replayRequest`, and `generateIdeConfig` to expect `success: false` and error `'Proxy advanced service not initialized'`.
|
||||
2. Run `npm run type-check` and fix any TypeScript errors introduced.
|
||||
3. Run `npm run lint` and fix any lint errors introduced.
|
||||
4. Run `npm test` and fix any remaining test failures.
|
||||
|
||||
## Critical Context
|
||||
- `proxyAdvancedRegistry` properties (`tokenManager`, `proxyMetrics`, `proxyReplay`, `proxyIdeConfig`) are set to `null` in tests when verifying null-registry behavior; `getServiceOrThrow` will throw, and the catch blocks (via `normalizeServiceError`) will return the unified P0 message.
|
||||
- `tsconfig.json` already has `"resolveJsonModule": true`, so importing `package.json` version in `request-user-agent.ts` requires no additional config changes.
|
||||
- `TokenEntry` and `TokenData` are now exported from `token-manager.service.ts` so `getAllTokens()` is usable externally.
|
||||
- The `proxy.controller.ts` change preserves the existing API response shape (`Record<string, { vision, streaming, jsonMode, audio, imageGeneration }>`) while making the map dynamic.
|
||||
|
||||
## File Operations
|
||||
### Read
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\package.json`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\ipc\proxy-advanced\handler.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\ipc\proxy-advanced\service-registry.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\rate-limit-tracker.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\server\modules\proxy\request-user-agent.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\server\modules\proxy\token-manager.service.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\tests\unit\google-api-timeout.test.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\tests\unit\ipc\proxy-advanced-handler.test.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\tests\unit\rate-limit-tracker.test.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\tests\unit\server\google-api.service.test.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\tests\unit\token-manager-parity-scheduling.test.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\types\cloudAccount.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\tsconfig.json`
|
||||
|
||||
### Modified
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\ipc\proxy-advanced\handler.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\ipc\proxy-advanced\service-registry.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\rate-limit-tracker.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\server\modules\proxy\request-user-agent.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\server\modules\proxy\token-manager.service.ts`
|
||||
---
|
||||
session: ses_2337
|
||||
updated: 2026-04-27T01:38:43.330Z
|
||||
---
|
||||
|
||||
# Session Summary
|
||||
|
||||
## Goal
|
||||
Implement all Package C — Backend Architecture (Quick Wins) fixes in the Gemini Nexus codebase and verify with `npm run lint`, `npm run type-check`, and `npm test`.
|
||||
|
||||
## Constraints & Preferences
|
||||
- Make minimal, focused changes; do not touch files outside Package C scope
|
||||
- Do not run `git commit` or `git push`
|
||||
- Run `npm run lint` and `npm run type-check` after changes and fix any introduced issues
|
||||
- `npm test` must not break any existing tests (update test expectations if needed to match new behavior)
|
||||
|
||||
## Progress
|
||||
### Done
|
||||
- [x] **C-P0-1** — `src/ipc/proxy-advanced/handler.ts`: Replaced silent empty fallbacks with explicit errors for `getParityCounters`, `getCircuitBreakerStatus`, `getProxyMetrics`, `getRecentRequests`, `replayRequest`, and `generateIdeConfig`. Added `normalizeServiceError()` helper to map `getServiceOrThrow` errors to `{ success: false, error: 'Proxy advanced service not initialized' }`.
|
||||
- [x] **C-P0-2** — `src/server/modules/proxy/rate-limit-tracker.ts`: Extended `cleanupExpired()` to iterate `this.failureCounts` and delete stale entries where `entry.lastFailureMs + FAILURE_COUNT_EXPIRY_MS <= now`. Return value now counts both lockouts and failureCounts deletions.
|
||||
- [x] **C-P0-3** — `src/server/modules/proxy/request-user-agent.ts`: Replaced hardcoded `FALLBACK_VERSION = '1.22.2'` with `import { version } from '../../../../package.json'` and `export const FALLBACK_VERSION = version`. `resolveJsonModule` is already enabled in `tsconfig.json`.
|
||||
- [x] **C-P1-1** — `src/server/modules/proxy/proxy.controller.ts`: Replaced hardcoded `capabilitiesMap` with `const capabilitiesMap = this.buildCapabilitiesMap()`. Added private `buildCapabilitiesMap()` that iterates `this.tokenManager?.getAllTokens()` and derives capabilities from `quota.models` metadata.
|
||||
- [x] **C-P1-1 prerequisite** — `src/server/modules/proxy/token-manager.service.ts`: Exported `TokenData` and `TokenEntry` types; added `getAllTokens(): TokenEntry[]` method returning `Array.from(this.tokens.entries())`.
|
||||
- [x] **C-P1-2** — `src/ipc/proxy-advanced/service-registry.ts`: Added typed `getServiceOrThrow<K extends keyof ProxyAdvancedRegistry>(key: K)` helper. Refactored `handler.ts` to use it; a `normalizeServiceError` wrapper preserves the exact P0 error message.
|
||||
|
||||
### In Progress
|
||||
- [ ] Update `src/tests/unit/ipc/proxy-advanced-handler.test.ts` expectations to match the new error responses (null-registry tests now expect `success: false` and `'Proxy advanced service not initialized'` instead of empty success data or old service-specific messages).
|
||||
- [ ] Run `npm run type-check` to validate changed backend files.
|
||||
- [ ] Run `npm run lint` to validate changed backend files.
|
||||
- [ ] Run `npm test` to ensure no regressions.
|
||||
|
||||
### Blocked
|
||||
- (none)
|
||||
|
||||
## Key Decisions
|
||||
- **Reconciled P0 and P1-2 in handler.ts**: Since `getServiceOrThrow` throws a different message than the P0-required `'Proxy advanced service not initialized'`, added a `normalizeServiceError` helper that detects the "is not registered" substring and rewrites it to the P0 message before returning in the success/error envelope. This allows `getServiceOrThrow` to be used (satisfying P1-2) while preserving the exact P0 contract.
|
||||
- **Dynamic capabilities heuristic**: `buildCapabilitiesMap()` derives `vision` from `modelInfo.supports_images`, sets `streaming`/`jsonMode` to `false` only for `gemini-3-pro-image` models, and sets `imageGeneration: true` only for `gemini-3-pro` variants that do not include `flash`. Falls back to a default `gemini-3-flash` entry when no models are discovered.
|
||||
|
||||
## Next Steps
|
||||
1. Update `src/tests/unit/ipc/proxy-advanced-handler.test.ts` null-registry tests for `getParityCounters`, `getCircuitBreakerStatus`, `getProxyMetrics`, `getRecentRequests`, `replayRequest`, and `generateIdeConfig` to expect `success: false` and error `'Proxy advanced service not initialized'`.
|
||||
2. Run `npm run type-check` and fix any TypeScript errors introduced.
|
||||
3. Run `npm run lint` and fix any lint errors introduced.
|
||||
4. Run `npm test` and fix any remaining test failures.
|
||||
|
||||
## Critical Context
|
||||
- `proxyAdvancedRegistry` properties (`tokenManager`, `proxyMetrics`, `proxyReplay`, `proxyIdeConfig`) are set to `null` in tests when verifying null-registry behavior; `getServiceOrThrow` will throw, and the catch blocks (via `normalizeServiceError`) will return the unified P0 message.
|
||||
- `tsconfig.json` already has `"resolveJsonModule": true`, so importing `package.json` version in `request-user-agent.ts` requires no additional config changes.
|
||||
- `TokenEntry` and `TokenData` are now exported from `token-manager.service.ts` so `getAllTokens()` is usable externally.
|
||||
- The `proxy.controller.ts` change preserves the existing API response shape (`Record<string, { vision, streaming, jsonMode, audio, imageGeneration }>`) while making the map dynamic.
|
||||
|
||||
## File Operations
|
||||
### Read
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\package.json`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\ipc\proxy-advanced\handler.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\ipc\proxy-advanced\service-registry.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\rate-limit-tracker.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\server\modules\proxy\request-user-agent.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\server\modules\proxy\token-manager.service.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\tests\unit\google-api-timeout.test.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\tests\unit\ipc\proxy-advanced-handler.test.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\tests\unit\rate-limit-tracker.test.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\tests\unit\server\google-api.service.test.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\tests\unit\token-manager-parity-scheduling.test.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\types\cloudAccount.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\tsconfig.json`
|
||||
|
||||
### Modified
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\ipc\proxy-advanced\handler.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\ipc\proxy-advanced\service-registry.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\rate-limit-tracker.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\server\modules\proxy\request-user-agent.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\server\modules\proxy\token-manager.service.ts`
|
||||
@@ -1,80 +1,80 @@
|
||||
---
|
||||
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)
|
||||
---
|
||||
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)
|
||||
@@ -1,103 +1,103 @@
|
||||
---
|
||||
session: ses_2344
|
||||
updated: 2026-04-27T01:42:26.030Z
|
||||
---
|
||||
|
||||
# Session Summary
|
||||
|
||||
## Goal
|
||||
Complete a comprehensive review of all Gemini Nexus app functionality (frontend + backend) via 8 agents (3 reviewers, 2 validators, 1 re-evaluator, 3 implementers), apply all fixes, and verify with passing type-check, lint, and tests.
|
||||
|
||||
## Constraints & Preferences
|
||||
- Do not run `git commit` or `git push`
|
||||
- Run `npm run lint` and `npm run type-check` after changes
|
||||
- Make minimal, focused changes
|
||||
- Do not touch files outside assigned package scope
|
||||
- Use exact file paths and identifiers when known
|
||||
- Prefer terse bullets over paragraphs
|
||||
|
||||
## Progress
|
||||
### Done
|
||||
- [x] Phase 0: Mapped codebase features (frontend, backend, integrations) with 3 parallel explorer agents
|
||||
- [x] Phase 1: Delegated 3 review agents (Backend/Architecture, Frontend/UX, Quality/Infra) — all reports received
|
||||
- [x] Phase 2: Delegated 2 validation agents (Backend, Frontend/Infra) — all reports received
|
||||
- [x] Phase 3: Delegated 1 re-evaluation agent — Master Implementation Plan generated with 3 parallel packages
|
||||
- [x] Phase 4: Delegated 3 implementation agents — all executed changes:
|
||||
- **Package A (Frontend UI/UX)**: Removed StrictMode, fixed SortIcon anti-pattern, fixed broken `/accounts` link, added gateway error feedback, removed dead components (`AccountCard.tsx`, `navigation-menu.tsx`), fixed responsive grids, fixed hardcoded badge colors, added aria-labels, fixed collapsible code headers, added pt-BR language option, fixed auth race condition, fixed ProxyAdvancedTab prop passing, fixed MonitorTab grid mismatch
|
||||
- **Package B (Quality/Infra)**: Removed gRPC deps, fixed `node-linker` warning, re-enabled `@typescript-eslint/no-explicit-any` as warn, fixed `catch (error: any)` to `unknown` in `cloud/handler.ts`, `cloud/router.ts`, `device/handler.ts`, `QuotaService.ts`, fixed `cloudHandler-sync.test.ts` mock (`getAgentDir`), unskipped `database.test.ts`, added `vitest/globals` types to `tsconfig.json`, added `device-handler.test.ts`, removed dead code from `proxy-replay.service.ts`
|
||||
- **Package C (Backend Quick Wins)**: Added `getServiceOrThrow` to `service-registry.ts`, replaced silent empty fallbacks with explicit errors in `proxy-advanced/handler.ts`, added `failureCounts` TTL cleanup to `rate-limit-tracker.ts`, derived `FALLBACK_VERSION` from `package.json` in `request-user-agent.ts`, replaced hardcoded `capabilitiesMap` with dynamic `buildCapabilitiesMap()` in `proxy.controller.ts` (iterates `tokenManager.getAllTokens()`), added `getAllTokens()` to `token-manager.service.ts`
|
||||
- [x] Initial verification run executed (`npm run type-check`, `npm run lint`, `npm test`)
|
||||
|
||||
### In Progress
|
||||
- [ ] Phase 5: Verify all changes and fix remaining issues:
|
||||
- `proxy-advanced-handler.test.ts`: 15 failing tests due to `service-registry` mock not including `getServiceOrThrow`
|
||||
- Type-check: 30 errors remaining, all in test files (`database.test.ts` missing Database properties, `useCloudAccounts.test.ts` argument count mismatches, `database-handler.test.ts` type errors)
|
||||
- Lint: 11 errors remaining (6 in JS scripts using `require()`, 2 in `useCloudAccounts.test.ts` Function type, 2 in `device-handler.test.ts` unused imports, 1 misc)
|
||||
|
||||
### Blocked
|
||||
- (none)
|
||||
|
||||
## Key Decisions
|
||||
- **Re-enable `no-explicit-any` as 'warn' instead of 'off'**: Exposes ~292 `any` warnings but prevents new `any` from being introduced silently; avoids breaking CI immediately with hundreds of errors.
|
||||
- **Keep proxy monolith decomposition as P2**: `proxy.service.ts` (2222 lines) and `proxy.controller.ts` (~1700 lines) were flagged as too large but left for future architectural work to keep the current cycle focused on quick wins.
|
||||
- **Use `getServiceOrThrow` helper in registry**: Centralizes null-check logic and returns explicit error messages instead of silent empty fallbacks, making startup failures visible to the UI.
|
||||
|
||||
## Next Steps
|
||||
1. Fix `proxy-advanced-handler.test.ts` mock to include `getServiceOrThrow` and update test expectations to match new explicit-error behavior
|
||||
2. Fix remaining type-check errors in `database.test.ts`, `useCloudAccounts.test.ts`, and `database-handler.test.ts`
|
||||
3. Fix remaining lint errors: either add `eslint-disable` for JS scripts or convert to ESM, fix Function type in `useCloudAccounts.test.ts`, remove unused imports in `device-handler.test.ts`
|
||||
4. Re-run full verification suite (`npm run type-check`, `npm run lint`, `npm test`) and confirm all green
|
||||
5. Do a final git diff review to ensure no unintended changes (e.g., image binary modifications from `forge.config.ts` changes)
|
||||
|
||||
## Critical Context
|
||||
- **Repository root**: `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\`
|
||||
- **Test runner**: Vitest with `globals: true` (now properly typed via `tsconfig.json`)
|
||||
- **Database mocking**: `better-sqlite3` is mocked in `src/tests/unit/mocks/better-sqlite3.ts`; real module fails in Node.js test env
|
||||
- **gRPC dependencies removed**: `@grpc/grpc-js` and `@grpc/proto-loader` removed from `package.json`
|
||||
- **node-linker removed**: from `.npmrc`
|
||||
- **Auth listener race fixed**: `mountedRef` + `isSubmittingRef` added in `CloudAccountList.tsx`
|
||||
- **FALLBACK_VERSION**: Now dynamically reads from `package.json` via `import { version }`
|
||||
- **RateLimitTracker**: Now cleans both `lockoutByKey` and `failureCounts` in `cleanupExpired()`
|
||||
|
||||
## File Operations
|
||||
### Read
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\forge.config.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\package.json`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\scripts\build-windows.js`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\scripts\generate-assets.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\actions\process.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\components\StatusBar.tsx`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\components\proxy\advanced\CapabilitiesTab.tsx`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\hooks\useCloudAccounts.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\ipc\cloud\handler.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\ipc\process\handler.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\ipc\switchFlow.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\ipc\tray\handler.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\layouts\MainLayout.tsx`
|
||||
- `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\services\GoogleAPIService.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\tests\unit\hooks\useCloudAccounts.test.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\tests\unit\ipc\device-handler.test.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\tests\unit\ipc\proxy-advanced-handler.test.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\tests\unit\process.test.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\types.d.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\types\cloudAccount.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\tsconfig.json`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\vite.renderer.config.mts`
|
||||
|
||||
### Modified
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\forge.config.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\package.json`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\ipc\process\handler.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\layouts\MainLayout.tsx`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\main.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\tests\unit\process.test.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\types.d.ts`
|
||||
- `src/components/proxy/advanced/CapabilitiesTab.tsx`
|
||||
- `src/tests/unit/ipc/proxy-advanced-handler.test.ts`
|
||||
---
|
||||
session: ses_2344
|
||||
updated: 2026-04-27T01:42:26.030Z
|
||||
---
|
||||
|
||||
# Session Summary
|
||||
|
||||
## Goal
|
||||
Complete a comprehensive review of all Gemini Nexus app functionality (frontend + backend) via 8 agents (3 reviewers, 2 validators, 1 re-evaluator, 3 implementers), apply all fixes, and verify with passing type-check, lint, and tests.
|
||||
|
||||
## Constraints & Preferences
|
||||
- Do not run `git commit` or `git push`
|
||||
- Run `npm run lint` and `npm run type-check` after changes
|
||||
- Make minimal, focused changes
|
||||
- Do not touch files outside assigned package scope
|
||||
- Use exact file paths and identifiers when known
|
||||
- Prefer terse bullets over paragraphs
|
||||
|
||||
## Progress
|
||||
### Done
|
||||
- [x] Phase 0: Mapped codebase features (frontend, backend, integrations) with 3 parallel explorer agents
|
||||
- [x] Phase 1: Delegated 3 review agents (Backend/Architecture, Frontend/UX, Quality/Infra) — all reports received
|
||||
- [x] Phase 2: Delegated 2 validation agents (Backend, Frontend/Infra) — all reports received
|
||||
- [x] Phase 3: Delegated 1 re-evaluation agent — Master Implementation Plan generated with 3 parallel packages
|
||||
- [x] Phase 4: Delegated 3 implementation agents — all executed changes:
|
||||
- **Package A (Frontend UI/UX)**: Removed StrictMode, fixed SortIcon anti-pattern, fixed broken `/accounts` link, added gateway error feedback, removed dead components (`AccountCard.tsx`, `navigation-menu.tsx`), fixed responsive grids, fixed hardcoded badge colors, added aria-labels, fixed collapsible code headers, added pt-BR language option, fixed auth race condition, fixed ProxyAdvancedTab prop passing, fixed MonitorTab grid mismatch
|
||||
- **Package B (Quality/Infra)**: Removed gRPC deps, fixed `node-linker` warning, re-enabled `@typescript-eslint/no-explicit-any` as warn, fixed `catch (error: any)` to `unknown` in `cloud/handler.ts`, `cloud/router.ts`, `device/handler.ts`, `QuotaService.ts`, fixed `cloudHandler-sync.test.ts` mock (`getAgentDir`), unskipped `database.test.ts`, added `vitest/globals` types to `tsconfig.json`, added `device-handler.test.ts`, removed dead code from `proxy-replay.service.ts`
|
||||
- **Package C (Backend Quick Wins)**: Added `getServiceOrThrow` to `service-registry.ts`, replaced silent empty fallbacks with explicit errors in `proxy-advanced/handler.ts`, added `failureCounts` TTL cleanup to `rate-limit-tracker.ts`, derived `FALLBACK_VERSION` from `package.json` in `request-user-agent.ts`, replaced hardcoded `capabilitiesMap` with dynamic `buildCapabilitiesMap()` in `proxy.controller.ts` (iterates `tokenManager.getAllTokens()`), added `getAllTokens()` to `token-manager.service.ts`
|
||||
- [x] Initial verification run executed (`npm run type-check`, `npm run lint`, `npm test`)
|
||||
|
||||
### In Progress
|
||||
- [ ] Phase 5: Verify all changes and fix remaining issues:
|
||||
- `proxy-advanced-handler.test.ts`: 15 failing tests due to `service-registry` mock not including `getServiceOrThrow`
|
||||
- Type-check: 30 errors remaining, all in test files (`database.test.ts` missing Database properties, `useCloudAccounts.test.ts` argument count mismatches, `database-handler.test.ts` type errors)
|
||||
- Lint: 11 errors remaining (6 in JS scripts using `require()`, 2 in `useCloudAccounts.test.ts` Function type, 2 in `device-handler.test.ts` unused imports, 1 misc)
|
||||
|
||||
### Blocked
|
||||
- (none)
|
||||
|
||||
## Key Decisions
|
||||
- **Re-enable `no-explicit-any` as 'warn' instead of 'off'**: Exposes ~292 `any` warnings but prevents new `any` from being introduced silently; avoids breaking CI immediately with hundreds of errors.
|
||||
- **Keep proxy monolith decomposition as P2**: `proxy.service.ts` (2222 lines) and `proxy.controller.ts` (~1700 lines) were flagged as too large but left for future architectural work to keep the current cycle focused on quick wins.
|
||||
- **Use `getServiceOrThrow` helper in registry**: Centralizes null-check logic and returns explicit error messages instead of silent empty fallbacks, making startup failures visible to the UI.
|
||||
|
||||
## Next Steps
|
||||
1. Fix `proxy-advanced-handler.test.ts` mock to include `getServiceOrThrow` and update test expectations to match new explicit-error behavior
|
||||
2. Fix remaining type-check errors in `database.test.ts`, `useCloudAccounts.test.ts`, and `database-handler.test.ts`
|
||||
3. Fix remaining lint errors: either add `eslint-disable` for JS scripts or convert to ESM, fix Function type in `useCloudAccounts.test.ts`, remove unused imports in `device-handler.test.ts`
|
||||
4. Re-run full verification suite (`npm run type-check`, `npm run lint`, `npm test`) and confirm all green
|
||||
5. Do a final git diff review to ensure no unintended changes (e.g., image binary modifications from `forge.config.ts` changes)
|
||||
|
||||
## Critical Context
|
||||
- **Repository root**: `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\`
|
||||
- **Test runner**: Vitest with `globals: true` (now properly typed via `tsconfig.json`)
|
||||
- **Database mocking**: `better-sqlite3` is mocked in `src/tests/unit/mocks/better-sqlite3.ts`; real module fails in Node.js test env
|
||||
- **gRPC dependencies removed**: `@grpc/grpc-js` and `@grpc/proto-loader` removed from `package.json`
|
||||
- **node-linker removed**: from `.npmrc`
|
||||
- **Auth listener race fixed**: `mountedRef` + `isSubmittingRef` added in `CloudAccountList.tsx`
|
||||
- **FALLBACK_VERSION**: Now dynamically reads from `package.json` via `import { version }`
|
||||
- **RateLimitTracker**: Now cleans both `lockoutByKey` and `failureCounts` in `cleanupExpired()`
|
||||
|
||||
## File Operations
|
||||
### Read
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\forge.config.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\package.json`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\scripts\build-windows.js`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\scripts\generate-assets.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\actions\process.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\components\StatusBar.tsx`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\components\proxy\advanced\CapabilitiesTab.tsx`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\hooks\useCloudAccounts.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\ipc\cloud\handler.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\ipc\process\handler.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\ipc\switchFlow.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\ipc\tray\handler.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\layouts\MainLayout.tsx`
|
||||
- `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\services\GoogleAPIService.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\tests\unit\hooks\useCloudAccounts.test.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\tests\unit\ipc\device-handler.test.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\tests\unit\ipc\proxy-advanced-handler.test.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\tests\unit\process.test.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\types.d.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\types\cloudAccount.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\tsconfig.json`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\vite.renderer.config.mts`
|
||||
|
||||
### Modified
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\forge.config.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\package.json`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\ipc\process\handler.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\layouts\MainLayout.tsx`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\main.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\tests\unit\process.test.ts`
|
||||
- `D:\Documents\Github\Gemini Proxys\Draculabo-AntigravityManager\src\types.d.ts`
|
||||
- `src/components/proxy/advanced/CapabilitiesTab.tsx`
|
||||
- `src/tests/unit/ipc/proxy-advanced-handler.test.ts`
|
||||
@@ -1,88 +1,88 @@
|
||||
---
|
||||
session: ses_24bf
|
||||
updated: 2026-04-22T08:17:02.015Z
|
||||
---
|
||||
|
||||
# Session Summary
|
||||
|
||||
## Goal
|
||||
|
||||
Fix the Gemini Nexus proxy so that OpenCode IDE (and other AI SDK consumers) correctly receive and display SSE streaming responses from the `/v1/chat/completions` endpoint.
|
||||
|
||||
## Constraints & Preferences
|
||||
|
||||
- Preserve existing proxy behavior for non-OpenCode clients (flat SSE format compatibility)
|
||||
- Keep `trafficLogger` operational; do not break file-based log rotation
|
||||
- Do not remove debug `console.log` statements until OpenCode compatibility is fully verified
|
||||
- Prefer automated tests over manual curl tests for regression coverage
|
||||
|
||||
## Progress
|
||||
|
||||
### Done
|
||||
|
||||
- [x] Identified that OpenCode uses `@ai-sdk/openai-compatible` which requires `delta.role: 'assistant'` on first SSE chunk
|
||||
- [x] Added `hasSentRoleChunk` flag and `pushRoleChunk()` helper in `processStreamResponse` (`proxy.service.ts`) to emit initial role chunk
|
||||
- [x] Added `winston.transports.Console` transport to `traffic-logger.ts` for real-time stdout visibility
|
||||
- [x] Added upstream request/response logging via `trafficLogger.logUpstream()` and `trafficLogger.logUpstreamResponse()` in `proxy.service.ts` (streaming, non-streaming, fallback paths)
|
||||
- [x] Added `console.log` in `writeSseResponse` (`proxy.controller.ts`) to log full SSE payloads sent to client
|
||||
- [x] Fixed `proxy-controller.integration.test.ts` mock `req` object to match new 3-argument `chatCompletions` signature
|
||||
- [x] Updated `proxy-retry-mock.test.ts` to expect `"role":"assistant"` in SSE output
|
||||
- [x] Created comprehensive automated stream debug tests in `src/tests/unit/proxy-stream-debug.test.ts`
|
||||
- [x] **Discovered root cause**: Gemini `v1internal` API returns SSE chunks wrapped in `{"response": {"candidates": [...]}, "traceId": "...", "metadata": {}}`, but `processStreamResponse` accessed `json.candidates` directly → `undefined` → empty content
|
||||
- [x] Fixed `processStreamResponse` to unwrap payload with `const responsePayload = json.response ?? json;` before extracting `candidates`
|
||||
- [x] Added `handles Gemini v1internal wrapped response format (response.candidates)` test case to prevent regression
|
||||
- [x] All 8 stream-debug tests pass; proxy-retry-mock shows 22 passed, 1 pre-existing failure (`maps Anthropic response to OpenAI response with reasoning and tool_calls` — unrelated to this change)
|
||||
|
||||
### In Progress
|
||||
|
||||
- [ ] Awaiting user to restart the Gemini Nexus app and verify the fix with curl / OpenCode IDE
|
||||
|
||||
### Blocked
|
||||
|
||||
- (none)
|
||||
|
||||
## Key Decisions
|
||||
|
||||
- **Emit `role: 'assistant'` chunk before first content**: Required by Vercel AI SDK's `@ai-sdk/openai-compatible` provider which validates `delta.role === 'assistant'` on first chunk
|
||||
- **Support both wrapped and flat response formats**: The fix uses `json.response ?? json` to handle both Gemini `v1internal` (wrapped) and standard (flat) SSE payloads
|
||||
- **Keep traffic logger + console transport dual logging**: File rotation preserved for production, console added for debugging; will remove debug `console.log` statements once verified
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. User restarts the Gemini Nexus app (`pnpm start` or `rs` in terminal)
|
||||
2. Run curl test: `curl -N -X POST http://localhost:8045/v1/chat/completions -H "Content-Type: application/json" -H "Authorization: Bearer <key>" -d '{"model":"gemini-3.1-pro-low","messages":[{"role":"user","content":"diga oi"}],"stream":true}'`
|
||||
3. Verify console output shows `[DEBUG] Extracted parts: [{"text":"..."}]` (non-empty) and `[SSE-OUT ...]` shows content chunks with actual text
|
||||
4. Test with OpenCode IDE to confirm responses now appear
|
||||
5. Once verified, remove temporary `[DEBUG]` `console.log` statements from `proxy.service.ts` and `proxy.controller.ts` (keep trafficLogger calls)
|
||||
6. Clean up todo items and close debugging session
|
||||
|
||||
## Critical Context
|
||||
|
||||
- **Root cause insight**: The Gemini internal streaming endpoint (`v1internal`) wraps each SSE data line as `{"response": {"candidates": [...]}, "traceId": "...", "metadata": {}}` instead of the flat `{"candidates": [...]}` used in public `generateContent` endpoints. The non-streaming path already handled this via `gemini.client.ts` (`payload.response` unwrap), but `processStreamResponse` (streaming path) did not.
|
||||
- **Working format**: After fix, a wrapped SSE line like `{"response":{"candidates":[{"content":{"parts":[{"text":"Oi!"}]}}]}}` correctly extracts `parts = [{"text":"Oi!"}]`
|
||||
- **Broken format (before fix)**: Same wrapped line yielded `json.candidates = undefined` → `parts = []` → empty content chunks
|
||||
- **Test file for regression**: `src/tests/unit/proxy-stream-debug.test.ts` now covers wrapped format, flat format, empty parts, reasoning content, function calls, multi-line buffers, partial lines, and no-content-field chunks
|
||||
- **Pre-existing test failure**: `proxy-retry-mock.test.ts` line 611 `expect(...).toContain(...)` fails because `reasoning_content` is `undefined` on the OpenAI response object — this failure existed before all changes
|
||||
|
||||
## File Operations
|
||||
|
||||
### Read
|
||||
|
||||
- `src/lib/geminiNexus/ClaudeRequestMapper.ts`
|
||||
- `src/lib/geminiNexus/ClaudeResponseMapper.ts`
|
||||
- `src/server/modules/proxy/proxy.controller.ts`
|
||||
- `src/server/modules/proxy/proxy.service.ts`
|
||||
- `src/tests/unit/proxy-controller.integration.test.ts`
|
||||
- `src/tests/unit/proxy-parity-fixtures.test.ts`
|
||||
- `src/tests/unit/proxy-retry-mock.test.ts`
|
||||
- `src/utils/traffic-logger.ts`
|
||||
- `src/server/modules/proxy/clients/gemini.client.ts`
|
||||
|
||||
### Modified
|
||||
|
||||
- `src/server/modules/proxy/proxy.controller.ts` — added `console.log` in `writeSseResponse` for SSE payload visibility; `trafficLogger` call added alongside existing logic
|
||||
- `src/server/modules/proxy/proxy.service.ts` — **critical fix**: `processStreamResponse` now unwraps `json.response ?? json` to extract candidates from Gemini v1internal wrapped format; added `pushRoleChunk()` for initial `role:assistant` delta; added `trafficLogger.logUpstream()` and `trafficLogger.logUpstreamResponse()` calls in streaming, non-streaming, fallback, and project-context-error paths; changed `_requestId` to `requestId` parameter
|
||||
- `src/tests/unit/proxy-controller.integration.test.ts` — fixed tests to pass mock `req` object matching new 3-arg `chatCompletions` signature
|
||||
- `src/tests/unit/proxy-retry-mock.test.ts` — updated stream tests to expect `"role":"assistant"` in output
|
||||
- `src/tests/unit/proxy-stream-debug.test.ts` — created comprehensive stream parsing tests; replaced flaky empty-stream timeout test with wrapped-format regression test
|
||||
- `src/utils/traffic-logger.ts` — added `winston.transports.Console` transport with colorized format for real-time stdout logging
|
||||
---
|
||||
session: ses_24bf
|
||||
updated: 2026-04-22T08:17:02.015Z
|
||||
---
|
||||
|
||||
# Session Summary
|
||||
|
||||
## Goal
|
||||
|
||||
Fix the Gemini Nexus proxy so that OpenCode IDE (and other AI SDK consumers) correctly receive and display SSE streaming responses from the `/v1/chat/completions` endpoint.
|
||||
|
||||
## Constraints & Preferences
|
||||
|
||||
- Preserve existing proxy behavior for non-OpenCode clients (flat SSE format compatibility)
|
||||
- Keep `trafficLogger` operational; do not break file-based log rotation
|
||||
- Do not remove debug `console.log` statements until OpenCode compatibility is fully verified
|
||||
- Prefer automated tests over manual curl tests for regression coverage
|
||||
|
||||
## Progress
|
||||
|
||||
### Done
|
||||
|
||||
- [x] Identified that OpenCode uses `@ai-sdk/openai-compatible` which requires `delta.role: 'assistant'` on first SSE chunk
|
||||
- [x] Added `hasSentRoleChunk` flag and `pushRoleChunk()` helper in `processStreamResponse` (`proxy.service.ts`) to emit initial role chunk
|
||||
- [x] Added `winston.transports.Console` transport to `traffic-logger.ts` for real-time stdout visibility
|
||||
- [x] Added upstream request/response logging via `trafficLogger.logUpstream()` and `trafficLogger.logUpstreamResponse()` in `proxy.service.ts` (streaming, non-streaming, fallback paths)
|
||||
- [x] Added `console.log` in `writeSseResponse` (`proxy.controller.ts`) to log full SSE payloads sent to client
|
||||
- [x] Fixed `proxy-controller.integration.test.ts` mock `req` object to match new 3-argument `chatCompletions` signature
|
||||
- [x] Updated `proxy-retry-mock.test.ts` to expect `"role":"assistant"` in SSE output
|
||||
- [x] Created comprehensive automated stream debug tests in `src/tests/unit/proxy-stream-debug.test.ts`
|
||||
- [x] **Discovered root cause**: Gemini `v1internal` API returns SSE chunks wrapped in `{"response": {"candidates": [...]}, "traceId": "...", "metadata": {}}`, but `processStreamResponse` accessed `json.candidates` directly → `undefined` → empty content
|
||||
- [x] Fixed `processStreamResponse` to unwrap payload with `const responsePayload = json.response ?? json;` before extracting `candidates`
|
||||
- [x] Added `handles Gemini v1internal wrapped response format (response.candidates)` test case to prevent regression
|
||||
- [x] All 8 stream-debug tests pass; proxy-retry-mock shows 22 passed, 1 pre-existing failure (`maps Anthropic response to OpenAI response with reasoning and tool_calls` — unrelated to this change)
|
||||
|
||||
### In Progress
|
||||
|
||||
- [ ] Awaiting user to restart the Gemini Nexus app and verify the fix with curl / OpenCode IDE
|
||||
|
||||
### Blocked
|
||||
|
||||
- (none)
|
||||
|
||||
## Key Decisions
|
||||
|
||||
- **Emit `role: 'assistant'` chunk before first content**: Required by Vercel AI SDK's `@ai-sdk/openai-compatible` provider which validates `delta.role === 'assistant'` on first chunk
|
||||
- **Support both wrapped and flat response formats**: The fix uses `json.response ?? json` to handle both Gemini `v1internal` (wrapped) and standard (flat) SSE payloads
|
||||
- **Keep traffic logger + console transport dual logging**: File rotation preserved for production, console added for debugging; will remove debug `console.log` statements once verified
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. User restarts the Gemini Nexus app (`pnpm start` or `rs` in terminal)
|
||||
2. Run curl test: `curl -N -X POST http://localhost:8045/v1/chat/completions -H "Content-Type: application/json" -H "Authorization: Bearer <key>" -d '{"model":"gemini-3.1-pro-low","messages":[{"role":"user","content":"diga oi"}],"stream":true}'`
|
||||
3. Verify console output shows `[DEBUG] Extracted parts: [{"text":"..."}]` (non-empty) and `[SSE-OUT ...]` shows content chunks with actual text
|
||||
4. Test with OpenCode IDE to confirm responses now appear
|
||||
5. Once verified, remove temporary `[DEBUG]` `console.log` statements from `proxy.service.ts` and `proxy.controller.ts` (keep trafficLogger calls)
|
||||
6. Clean up todo items and close debugging session
|
||||
|
||||
## Critical Context
|
||||
|
||||
- **Root cause insight**: The Gemini internal streaming endpoint (`v1internal`) wraps each SSE data line as `{"response": {"candidates": [...]}, "traceId": "...", "metadata": {}}` instead of the flat `{"candidates": [...]}` used in public `generateContent` endpoints. The non-streaming path already handled this via `gemini.client.ts` (`payload.response` unwrap), but `processStreamResponse` (streaming path) did not.
|
||||
- **Working format**: After fix, a wrapped SSE line like `{"response":{"candidates":[{"content":{"parts":[{"text":"Oi!"}]}}]}}` correctly extracts `parts = [{"text":"Oi!"}]`
|
||||
- **Broken format (before fix)**: Same wrapped line yielded `json.candidates = undefined` → `parts = []` → empty content chunks
|
||||
- **Test file for regression**: `src/tests/unit/proxy-stream-debug.test.ts` now covers wrapped format, flat format, empty parts, reasoning content, function calls, multi-line buffers, partial lines, and no-content-field chunks
|
||||
- **Pre-existing test failure**: `proxy-retry-mock.test.ts` line 611 `expect(...).toContain(...)` fails because `reasoning_content` is `undefined` on the OpenAI response object — this failure existed before all changes
|
||||
|
||||
## File Operations
|
||||
|
||||
### Read
|
||||
|
||||
- `src/lib/geminiNexus/ClaudeRequestMapper.ts`
|
||||
- `src/lib/geminiNexus/ClaudeResponseMapper.ts`
|
||||
- `src/server/modules/proxy/proxy.controller.ts`
|
||||
- `src/server/modules/proxy/proxy.service.ts`
|
||||
- `src/tests/unit/proxy-controller.integration.test.ts`
|
||||
- `src/tests/unit/proxy-parity-fixtures.test.ts`
|
||||
- `src/tests/unit/proxy-retry-mock.test.ts`
|
||||
- `src/utils/traffic-logger.ts`
|
||||
- `src/server/modules/proxy/clients/gemini.client.ts`
|
||||
|
||||
### Modified
|
||||
|
||||
- `src/server/modules/proxy/proxy.controller.ts` — added `console.log` in `writeSseResponse` for SSE payload visibility; `trafficLogger` call added alongside existing logic
|
||||
- `src/server/modules/proxy/proxy.service.ts` — **critical fix**: `processStreamResponse` now unwraps `json.response ?? json` to extract candidates from Gemini v1internal wrapped format; added `pushRoleChunk()` for initial `role:assistant` delta; added `trafficLogger.logUpstream()` and `trafficLogger.logUpstreamResponse()` calls in streaming, non-streaming, fallback, and project-context-error paths; changed `_requestId` to `requestId` parameter
|
||||
- `src/tests/unit/proxy-controller.integration.test.ts` — fixed tests to pass mock `req` object matching new 3-arg `chatCompletions` signature
|
||||
- `src/tests/unit/proxy-retry-mock.test.ts` — updated stream tests to expect `"role":"assistant"` in output
|
||||
- `src/tests/unit/proxy-stream-debug.test.ts` — created comprehensive stream parsing tests; replaced flaky empty-stream timeout test with wrapped-format regression test
|
||||
- `src/utils/traffic-logger.ts` — added `winston.transports.Console` transport with colorized format for real-time stdout logging
|
||||
Reference in new issue
Block a user