mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 20:32:20 +03:00
* test(settings): add unit tests for debugMode and hiddenSidebarItems Tests cover: - PATCH debugMode=true/false - PATCH hiddenSidebarItems with array values - Combined updates with both fields * test(e2e): add Playwright tests for settings toggles Tests cover: - Debug mode toggle on/off - Sidebar visibility toggle - Settings persistence after page reload * fix(tests): address code review issues - Unit tests: fix async/await for getSettings, use direct db functions - E2E tests: remove conditional logic, use Playwright auto-waiting assertions * feat(logging): unify request log retention and artifacts * docs: add dashboard settings toggles to CONTRIBUTING Add section documenting: - Debug Mode toggle (Settings → Advanced) - Sidebar Visibility toggle (Settings → General) * fix(cache): only inject prompt_cache_key for supported providers Only inject prompt_cache_key for providers that support prompt caching (Claude, Anthropic, ZAI, Qwen, DeepSeek). This fixes issue #848 where NVIDIA API rejected the parameter. * fix(model-sync): log only channel-level model changes * feat(providers): add 4 free models to opencode-zen * feat(providers): add explicit contextLength for opencode-zen free models * feat(providers): add contextLength for all opencode-zen models * feat: Improve the Chinese translation * fix: preserve client cache_control for all Claude-protocol providers Previously, the cache control preservation logic only recognized a hardcoded list of providers (claude, anthropic, zai, qwen, deepseek). This caused OmniRoute to inject its own cache_control markers for Claude-protocol providers not in that list (bailian-coding-plan, glm, minimax, minimax-cn, etc.), overwriting the client's cache markers. The fix checks both: 1. Known caching providers list (existing behavior) 2. Whether targetFormat === 'claude' (all Claude-protocol providers) This ensures all Claude-compatible providers properly preserve client cache_control headers when appropriate (Claude Code client, deterministic routing, etc.). Also removes unused CacheStatsCard from settings/components (duplicate of the one in cache/ page). Fixes cache token calculation for GLM, Minimax, and other Claude-compatible providers. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: pure passthrough for Claude→Claude when cache_control preserved The Claude passthrough path round-trips through OpenAI format (claude→openai→claude) for structural normalization. This strips cache_control markers from every content block since OpenAI format has no equivalent, causing ~42k cache creation tokens per request with zero cache reads. When preserveCacheControl is true (Claude Code client, "always" setting, or deterministic combo), skip the round-trip entirely and forward the body as-is. Claude Code sends well-formed Messages API payloads — the normalization was only needed for non-Code clients. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: restore CacheStatsCard — was not a duplicate The first commit incorrectly deleted CacheStatsCard from settings/components/ as a "duplicate". It's the only copy — both settings/page.tsx and cache/page.tsx import from this location. Restored the i18n-ized version from main. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(429): parse long quota reset times from error body - Parse XhYmZs format from antigravity error messages (e.g., 27h41m36s) - Dynamic retry-after threshold (60s default) instead of hardcoded 10s - Add parseRetryFromErrorText() in accountFallback.ts for body parsing - Fix 403 'verify your account' to trigger permanent deactivation - Add keyword matching for 'quota will reset', 'exhausted capacity' - Add unit tests for retry parsing and keyword matching Fixes #858 (Antigravity 429 handling) Fixes #832 (Qwen quota 429 - same underlying bug) * chore: bump version to v3.4.0-dev * fix(migrations): rename 013 to 014 to avoid collision with v3.3.11 * chore(docs): update CHANGELOG for v3.4.0 integrations * fix: Claude token refresh, Antigravity quota, and 429 rate-limit handling - Fix Claude OAuth token refresh to use form-urlencoded format (standard OAuth2) - Add anthropic-beta header required by Claude OAuth API - Switch Antigravity quota to use retrieveUserQuota API (same as Gemini CLI) - Parse quota reset time for all providers (not just Antigravity) - Add quota reset keywords to error classifier - Cap maximum retry time at 24 hours to prevent infinite wait Closes #836, #857, #858, #832 * fix(dashboard): resolve /dashboard/limits hanging UI with 70+ accounts via chunk parallelization (#784) --------- Co-authored-by: oyi77 <oyi77@users.noreply.github.com> Co-authored-by: R.D. <rogerproself@gmail.com> Co-authored-by: kang-heewon <heewon.dev@gmail.com> Co-authored-by: gmw <rorschach1167@qq.com> Co-authored-by: tombii <github@tombii.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
78 lines
2.4 KiB
TypeScript
78 lines
2.4 KiB
TypeScript
// Server startup script
|
|
import initializeCloudSync from "./shared/services/initializeCloudSync";
|
|
import { enforceSecrets } from "./shared/utils/secretsValidator";
|
|
import { initAuditLog, cleanupExpiredLogs, logAuditEvent } from "./lib/compliance/index";
|
|
import { initConsoleInterceptor } from "./lib/consoleInterceptor";
|
|
|
|
async function startServer() {
|
|
// Trigger request-log layout migration during startup, before serving requests.
|
|
await import("./lib/usage/migrations");
|
|
|
|
// Console interceptor: capture all console output to log file (must be first)
|
|
initConsoleInterceptor();
|
|
|
|
// FASE-01: Validate required secrets before anything else (fail-fast)
|
|
enforceSecrets();
|
|
|
|
// Compliance: Initialize audit_log table
|
|
try {
|
|
initAuditLog();
|
|
console.log("[COMPLIANCE] Audit log table initialized");
|
|
} catch (err) {
|
|
console.warn("[COMPLIANCE] Could not initialize audit log:", err.message);
|
|
}
|
|
|
|
// Compliance: One-time cleanup of expired logs
|
|
try {
|
|
const cleanup = cleanupExpiredLogs();
|
|
if (
|
|
cleanup.deletedUsage ||
|
|
cleanup.deletedCallLogs ||
|
|
cleanup.deletedProxyLogs ||
|
|
cleanup.deletedRequestDetailLogs ||
|
|
cleanup.deletedAuditLogs ||
|
|
cleanup.deletedMcpAuditLogs
|
|
) {
|
|
console.log("[COMPLIANCE] Expired log cleanup:", cleanup);
|
|
}
|
|
} catch (err) {
|
|
console.warn("[COMPLIANCE] Log cleanup failed:", err.message);
|
|
}
|
|
|
|
console.log("Starting server with cloud sync...");
|
|
|
|
try {
|
|
// Initialize cloud sync
|
|
await initializeCloudSync();
|
|
console.log("Server started with cloud sync initialized");
|
|
|
|
// Log server start event to audit log
|
|
logAuditEvent({ action: "server.start", details: { timestamp: new Date().toISOString() } });
|
|
} catch (error) {
|
|
console.error("[FATAL] Error initializing cloud sync:", error);
|
|
process.exit(1);
|
|
}
|
|
|
|
// Pricing sync: opt-in external pricing data (non-blocking, never fatal)
|
|
if (process.env.PRICING_SYNC_ENABLED === "true") {
|
|
try {
|
|
const { initPricingSync } = await import("./lib/pricingSync");
|
|
await initPricingSync();
|
|
} catch (err) {
|
|
console.warn(
|
|
"[PRICING_SYNC] Could not initialize:",
|
|
err instanceof Error ? err.message : err
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Start the server initialization
|
|
startServer().catch((err) => {
|
|
console.error("[FATAL] Server initialization failed:", err);
|
|
process.exit(1);
|
|
});
|
|
|
|
// Export for use as module if needed
|
|
export default startServer;
|