Skip to content

v0.4.0

Choose a tag to compare

@youssefvdel youssefvdel released this 11 Jun 16:45
· 41 commits to main since this release

Authentication & Account Management

  • Refactored authentication to read tokens exclusively from Chromium browser profiles instead of cookie files (src/services/auth.ts, src/services/accountManager.ts)
  • Removed cookie folder system -- no more qwen_profile/cookies/ directory fallback (src/services/accountManager.ts)
  • Added browser profile authorization on account creation via openBrowserProfile before falling back to API login (src/services/accountManager.ts) (@studi929)
  • Added loadCookiesFromProfile function to extract tokens from persistent Chromium profiles (src/services/auth.ts) (@studi929)
  • Added parallel profile/cookie extraction at startup (batch 3 concurrent) with phased initialization (src/services/auth.ts)
  • Added automatic cookie refresh from Chromium profile on every boot (src/services/browserProfiles.ts)
  • Fixed refresh_token extraction and saving during profile-based auth (src/services/browserProfiles.ts, src/services/auth.ts)
  • Fixed Token TTL showing 0 for session cookies from browser profiles (src/services/browserProfiles.ts)
  • Added HOST config option for binding the server to a custom hostname (src/services/configService.ts)
  • Added validation in ConfigService for PORT range and negative values for numeric config keys (src/services/configService.ts)
  • Added warning on unknown config keys in config.json (src/services/configService.ts)
  • Removed double inFlight increment in pickAccount() on the account manager side (src/services/accountManager.ts)
  • Made pickAccount() async with mutex-guarded account selection and inFlight tracking (src/services/accountManager.ts)
  • Made getTokenWithAccount() async to match async pickAccount() (src/services/accountManager.ts, src/services/playwright.ts)
  • Fixed rate limiting on account add/delete endpoints (src/routes/accounts.ts) (@studi929)
  • Replaced loginFresh call in account login route with openBrowserProfile + loadCookiesFromProfile (src/routes/accounts.ts) (@studi929)
  • Updated manual login (autofill) flow to open non-headless browser and poll for auth completion (src/routes/accounts.ts) (@studi929)
  • Added AES-256-GCM encryption for stored account passwords using API_KEY or machine-based key derivation (src/services/accountManager.ts)
  • Added migrateFromOldPaths() to move accounts from qwen_profile/ to .qwen/ directory (src/services/accountManager.ts)
  • Changed account watcher to watch .qwen/accounts.json instead of the old cookie directory (src/services/accountManager.ts)
  • Added removeAccountContext and removeAccountContext to properly clean up Playwright contexts on account removal (src/services/playwright.ts, src/services/accountManager.ts)
  • Added watcher retry logic with debounced timer for filesystem watch failures (src/services/accountManager.ts)
  • Fixed getAccountByEmail to normalize email casing before lookup (src/services/accountManager.ts) (@studi929)
  • Fixed silent autoFillLogin export removal -- removed unused function (src/services/browserProfiles.ts)
  • Migrated all console.error/warn calls to logStore.log in auth-related services (src/services/loginHelpers.ts, src/services/tokenRefresh.ts, src/services/auth.ts, src/services/browserProfiles.ts, src/services/accountManager.ts) (@studi929)
  • Fixed auth navigation to only clear specific auth cookies instead of ALL cookies (src/services/loginHelpers.ts) (@studi929)
  • Added JSON response body token extraction in signin route interception (faster than set-cookie headers) (src/services/loginHelpers.ts) (@studi929)
  • Replaced blind 2s sleep with polling loop (10 attempts, 500ms intervals) in temp context login (src/services/loginHelpers.ts) (@studi929)
  • Reduced auth page timeouts from 30s to 20s and selector waits from 15s to 10s (src/services/loginHelpers.ts) (@studi929)
  • Fixed loginFresh to try fetch-based login before browser-based login (src/services/auth.ts) (@studi929)
  • Added autoLoginAllAccounts to run logins in parallel instead of sequential with delays (src/services/auth.ts)
  • Removed loadSavedCookies function -- no longer reads from cookie files (src/services/auth.ts)
  • Fixed saveCookies to write token persistence to .qwen/tokens/ directory instead of cookie files (src/services/auth.ts)
  • Updated auth fallback in refreshAccountCookies to skip throttling when a valid token exists in memory (src/services/playwright.ts)
  • Added JWT token injection as cookie in browser context during cookie refresh (src/services/playwright.ts)
  • Changed cookie refresh interval from 30s to 120s with jitter (src/services/playwright.ts)

Dashboard & UI

  • Removed API_KEY-based authentication from dashboard log, health, metrics, account stats, and config read endpoints (src/routes/dashboard/dashboardRoutes.ts)
  • Added conditional bearer auth on admin-only endpoints (reload accounts, delete-all-chats) only when API_KEY is configured (src/routes/dashboard/dashboardRoutes.ts)
  • Sanitized sensitive data in dashboard log entries -- mask emails, truncate large content, strip credentials (src/routes/dashboard/dashboardRoutes.ts)
  • Exposed config without API_KEY value in the /api/config endpoint (src/routes/dashboard/dashboardRoutes.ts)
  • Reformatted overview.css from single-line to multi-line with proper indentation (src/routes/dashboard/public/overview.css)
  • Changed overview grid layout from 2fr 1fr to 3fr 2fr (src/routes/dashboard/public/overview.css)
  • Added max-height: 100vh and max-height: 80vh constraints to panels and system logs container (src/routes/dashboard/public/overview.css, src/routes/dashboard/public/accounts.css)
  • Added scrollable system logs container with overflow-y auto (src/routes/dashboard/public/overview.css)
  • Fixed system logs to append new entries via insertAdjacentHTML instead of full innerHTML replacement (src/routes/dashboard/public/overview.js)
  • Added notification dedup -- caps at 5 visible notifications at a time (src/routes/dashboard/public/overview.js)
  • Added createPoller utility with exponential backoff on failures and pause-on-hidden (src/routes/dashboard/public/shared.js)
  • Replaced all setInterval pollers with createPoller for adaptive polling across dashboard pages (src/routes/dashboard/public/overview.js, src/routes/dashboard/public/logs.js, src/routes/dashboard/public/accounts.js, src/routes/dashboard/public/network.js)
  • Added toast limit to 5 on accounts page (src/routes/dashboard/public/accounts.js)
  • Fixed login button state management -- removed stale setTimeout resets (src/routes/dashboard/public/accounts.js) (@studi929)
  • Added active poll timer tracking to prevent duplicate pollAuth intervals (src/routes/dashboard/public/accounts.js)
  • Removed API_KEY from logs page fetch headers and EventSource URL (src/routes/dashboard/public/logs.js)
  • Added hidden entries buffer and Load More functionality for log entries (src/routes/dashboard/public/logs.js)
  • Fixed network.js duration classification -- changed threshold from 3000ms to 500ms for slow (src/routes/dashboard/public/network.js)
  • Added textarea support in settings form with proper styling and box-sizing (src/routes/dashboard/public/settings.css)
  • Removed inline textarea styles in favor of CSS classes (src/routes/dashboard/public/settings.js)
  • Moved Delete All Chats button to a separate Danger Zone section with warning styling (src/routes/dashboard/public/settings.js)
  • Added confirmation modal for delete-all-chats with progress display (src/routes/dashboard/public/settings.js)
  • Added error handling for delete-all-chats HTTP failures in the modal flow (src/routes/dashboard/public/settings.js)
  • Added escape for single quotes and backticks in escHtml (XSS hardening) (src/routes/dashboard/public/shared.js)
  • Changed modal visibility to use hidden CSS class instead of inline style.display (src/routes/dashboard/public/settings.js, src/routes/dashboard/settings.ts)
  • Added toast limit cap on settings page (src/routes/dashboard/public/settings.js)

API & Streaming

  • Added per-message size validation (100KB limit) to prevent OOM during token estimation (src/routes/chat.ts) (@studi929)
  • Moved logIncomingRequest call removal -- no longer logs every request body (src/routes/chat.ts)
  • Fixed pickAccount to be async in session setup, with proper decrementInFlight on acquire failure (src/routes/chat.ts) (@studi929)
  • Added error type and code to error responses (src/routes/chat.ts) (@studi929)
  • Fixed createQwenStreamWithRetry to forward toolChoice parameter (src/routes/chat.ts, src/routes/chatHelpers.ts) (@studi929)
  • Fixed buildQwenMessages to serialize complex parameter values with JSON.stringify instead of String() (src/routes/chatHelpers.ts) (@studi929)
  • Limited think/thought tag patterns in buildQwenMessages -- removed tool_call, tool_use, function_call, tool from think tag stripping (src/routes/chatHelpers.ts) (@studi929)
  • Removed createLogEntry function -- consolidated into caller (src/routes/chatHelpers.ts)
  • Fixed detectCumulativeChunk with multi-size fingerprint matching for robust delta detection (src/routes/chatHelpersCore.ts) (@studi929)
  • Fixed getSnapshotDelta to handle cases where cleaned content becomes shorter than previous snapshot (src/routes/chatHelpersCore.ts) (@studi929)
  • Restricted think tag patterns in cleanThinkTags -- only think, thinking, thought (removed tool_call, tool_use, function_call, tool) (src/routes/chatHelpersCore.ts) (@studi929)
  • Added history trim to ToolSpamGuard to prevent unbounded growth (src/routes/chatHelpersCore.ts) (@studi929)
  • Added periodic cleanup of pendingCorrections map (trim to 500 entries every 5 minutes) (src/routes/chatHelpersCore.ts) (@studi929)
  • Made processToolCallsThroughGuard accept configurable maxToolCalls parameter (src/routes/chatHelpersCore.ts) (@studi929)
  • Fixed non-streaming delta processing to only parse new content since last parsed position (src/routes/chatNonStreaming.ts) (@studi929)
  • Added lastParsedPosition tracking in non-streaming processor (src/routes/chatNonStreaming.ts) (@studi929)
  • Added handling for local_tool phase (skip to avoid duplicate content) (src/routes/chatNonStreaming.ts) (@studi929)
  • Added stable-args dedup for flush-time tool call detection to avoid corrupted guard state (src/routes/chatNonStreaming.ts) (@studi929)
  • Added parallel loop detection with valid call filtering to remove duplicate tool calls from response (src/routes/chatNonStreaming.ts) (@studi929)
  • Added filterContentPipeline shared utility standardizing the clean path: xmlStripper -> filterContent -> cleanThinkTags (src/routes/chatStreamingHelpers.ts)
  • Replaced per-chunk filter pipeline with filterContentPipeline in streaming data processing (src/routes/chatStreamingHelpers.ts)
  • Added reasoning buffer length cap (20,000 chars) and lastVStrRaw cap (100,000 chars) (src/routes/chatStreamingHelpers.ts) (@studi929)
  • Added lastParsePosition tracking in streaming state to only parse new XML tool calls (src/routes/chatStreamingHelpers.ts)
  • Added lastFullContent truncation at 100,000 chars with snapshot reset to prevent unbounded growth (src/routes/chatStreamingHelpers.ts)
  • Fixed tool call index in SSE events to use emittedToolCallCount instead of local index (src/routes/chatStreamingHelpers.ts)
  • Added loggedToolCalls set clear at 500 entries to limit memory (src/routes/chatStreamingHelpers.ts) (@studi929)
  • Removed handleToolCalls function -- consolidated into caller (src/routes/chatStreamingHelpers.ts) (@studi929)
  • Added lastParsePosition to streaming state type (src/routes/chatStreaming.ts)
  • Replaced per-chunk filter calls with filterContentPipeline in streamLoop.ts (src/routes/streamLoop.ts)
  • Removed imports of deleted files (StreamingContentFilter, cleanThinkTags from old location, filterContent direct usage) (src/routes/streamLoop.ts)
  • Fixed cleanup scheduling from 200ms delay to 0ms (src/routes/cleanupHelpers.ts)
  • Improved JSON array compression in compressToolResult -- shows head/mid/tail samples instead of just the first 3 items (src/routes/compressToolResult.ts)
  • Fixed parseXmlToolCalls regex to handle malformed functions without closing tag (src/tools/xmlToolParser.ts)
  • Added crypto import to xmlToolParser.ts (src/tools/xmlToolParser.ts)
  • Reduced filterContent thinking line threshold from >=2 to >=3 with majority check to prevent false-positive prose stripping (src/utils/contentFilter.ts)
  • Added JWT regex recognition redaction in error text to prevent token leakage in upstream errors (src/services/qwen.ts) (@studi929)
  • Added timeout handling for AbortError in fetch requests (src/services/qwen.ts) (@studi929)
  • Added decrementInFlight call after rate-limit account rotation in qwen.ts to prevent inFlight counter leak (src/services/qwen.ts) (@studi929)
  • Fixed toolChoice type from string to unknown in qwen.ts (src/services/qwen.ts) (@studi929)
  • Fixed URL construction for chat completions with query parameter (src/services/qwen.ts) (@studi929)

Tool Calling

  • Removed dead-code tool parsing system: deleted src/tools/parser.ts (316 lines), src/tools/parserHelpers.ts (62 lines), src/tools/toolRunner.ts (145 lines)
  • Removed validateToolCalls, detectToolCallLoop, detectProviderToolLeak from guard.ts -- no longer needed (src/tools/guard.ts) (@studi929)
  • Removed corresponding tests for deleted functions (src/tools/guard.test.ts) (@studi929)
  • Removed parallel.test.ts test content referencing deleted executeToolCalls (src/tests/parallel.test.ts)
  • Kept validateSingleToolCall and detectParallelToolLoop in guard.ts (src/tools/guard.ts, src/tools/guard.test.ts)
  • Made buildCorrectionPrompt private in guard.ts (src/tools/guard.ts) (@studi929)
  • Removed function_call, tool_use, tool from think tag patterns to prevent tool_result leaking into thinking path (src/utils/thinkTagStripper.ts, src/routes/chatHelpers.ts, src/routes/chatHelpersCore.ts, src/routes/chatStreamingHelpers.ts) (@studi929)
  • Improved stripToolCallArtifacts in xmlStripper.ts -- specific partial tag stripping instead of aggressive patterns (src/utils/xmlStripper.ts)
  • Added JSON tool result echo block stripping to xmlStripper.ts (src/utils/xmlStripper.ts)
  • Replaced broad partial tag regexes with targeted patterns for tool_result, tool_call, tool_use, function, parameter (src/utils/xmlStripper.ts)
  • Fixed stripStreamingDelta to use targeted partial tag patterns instead of aggressive char-level matching (src/utils/xmlStripper.ts) (@studi929)
  • Deleted src/routes/pipeline/StreamingContentFilter.ts (141 lines) -- replaced by filterContentPipeline approach

Security

  • Added AES-256-GCM encryption for stored account passwords with API_KEY or machine-based key derivation (src/services/accountManager.ts)
  • Added JWT token redaction from upstream error messages (src/services/qwen.ts)
  • Added per-message content size validation (100KB) to prevent OOM attacks (src/routes/chat.ts)
  • Added in-flight counter safety valve (reset if >20) to prevent counter drift (src/services/accountManager.ts)
  • Added sanitizeLogEntry function to dashboard routes -- mask emails, truncate credentials, strip sensitive fields (src/routes/dashboard/dashboardRoutes.ts)
  • Added API_KEY exclusion from /api/config response (src/routes/dashboard/dashboardRoutes.ts)
  • Added conditional bearer auth on admin dashboard endpoints when API_KEY is set (src/routes/dashboard/dashboardRoutes.ts)
  • Removed API_KEY from dashboard log stream and API requests in frontend JS (src/routes/dashboard/public/logs.js, src/routes/dashboard/public/settings.js)
  • Added XSS hardening in escHtml -- escape single quotes and backticks (src/routes/dashboard/public/shared.js)
  • Added email masking in delete-all-chats progress events (src/routes/dashboard/dashboardRoutes.ts)
  • Added query parameter token fallback for EventSource authentication (src/utils/auth.ts)
  • Fixed checkApiKeyAuth to allow Authorization header OR query token (src/utils/auth.ts)

Performance

  • Parallelized profile/cookie extraction at startup with max 3 concurrent Chromium instances (src/services/auth.ts)
  • Added parallel login for unauthenticated accounts at startup (src/services/auth.ts)
  • Parallelized post-login callbacks with Promise.allSettled (src/services/auth.ts)
  • Parallelized autoLoginAllAccounts with Promise.allSettled instead of sequential (src/services/auth.ts)
  • Added write queue with 500ms flush timer to qwenLogger to batch disk writes (src/services/qwenLogger.ts)
  • Added 7-day log rotation to qwenLogger (daily check, delete files older than 7 days) (src/services/qwenLogger.ts)
  • Added model health state cleanup interval (60s) to evict stale entries (src/services/modelHealth.ts)
  • Deferred session deletion with 60-second timer instead of immediate delete, allowing reuse (src/services/sessionPool.ts) (@studi929)
  • Added AbortSignal.timeout(30000) to session pool health check requests (src/services/sessionPool.ts) (@studi929)
  • Added reasoning buffer cap (20,000 chars) and lastVStrRaw cap (100,000 chars) in streaming (src/routes/chatStreamingHelpers.ts)
  • Added lastFullContent truncation at 100,000 chars with snapshot reset to prevent unbounded memory growth (src/routes/chatStreamingHelpers.ts) (@studi929)
  • Added loggedToolCalls set clear at 500 entries (src/routes/chatStreamingHelpers.ts)
  • Added pendingCorrections periodic cleanup (trim to 500, every 5 minutes) (src/routes/chatHelpersCore.ts)
  • Added ToolSpamGuard history trim to prevent unbounded growth (src/routes/chatHelpersCore.ts)
  • Added request log file rotation -- keep max 1000 files in request log directory (src/services/logStore.ts)
  • Switched request log writes to async writeFile (non-blocking) (src/services/logStore.ts)
  • Changed cookie refresh interval from 30s to 120s with random jitter to reduce overhead (src/services/playwright.ts)
  • Added fingerprint-based recovery with multiple sizes in detectCumulativeChunk for robust delta detection (src/routes/chatHelpersCore.ts)
  • Optimized non-streaming delta parsing to only check new content since last parse position (src/routes/chatNonStreaming.ts)
  • Optimized streaming delta parsing to only check new content since last parse position (src/routes/chatStreamingHelpers.ts)
  • Removed console.log filter (grep --line-buffered -v 'injected env') from start script (package.json)
  • Reduced auth signin request timeout from 30s to 15s and page load timeout from 30s to 20s (src/services/loginHelpers.ts)

DevOps & Infrastructure

  • Added multi-stage Dockerfile with Chromium for production deployment (Dockerfile)
  • Added .dockerignore with 6 lines of ignore patterns (.dockerignore)
  • Added GitHub Actions CI workflow -- runs typecheck and tests on push/PR (.github/workflows/ci.yml)
  • Added Husky pre-commit hook -- runs typecheck and tests before commits (.husky/pre-commit)
  • Added dotenv dependency for .env file support (package.json)
  • Added start:prod script for running compiled production build (package.json)
  • Added test:coverage script for test coverage reporting (package.json)
  • Added husky-init script (package.json)
  • Added dotenv import at entry point -- import 'dotenv/config' (src/index.tsx)
  • Added hostname support to server -- accepts --host CLI arg or HOST config, binds to hostname, shows in banner (src/index.tsx)
  • Added port-in-use fallback -- tries port+1 if configured port is busy (EADDRINUSE) (src/index.tsx)
  • Added PID file support -- writes .qwen/gate.pid on start, removes on graceful shutdown (src/index.tsx, src/cli.ts)
  • Changed CLI restart to use PID file for precise process termination instead of pkill (src/cli.ts)
  • Added 5-second timeout to CLI status check fetch (src/cli.ts)
  • Added unhandled Promise rejection handler logging (src/index.tsx)
  • Updated .gitignore for .qwen/ directory (src/index.tsx)
  • Added install.sh with significant updates (2782 lines) (install.sh)
  • Added CHANGELOG.md with unreleased section (CHANGELOG.md)
  • Removed entire TODO/ directory (7 files, 906 lines deleted) -- completed items
  • Added audit report directory .qwen/reports/ with 10 quality investigation reports (.qwen/reports/)

Testing

  • Set non-empty API_KEY (test-key-for-testing) in test environment to prevent auth bypass (src/tests/index.test.ts) (@studi929)
  • Added Authorization: Bearer header to all test requests to match new auth requirements (src/tests/index.test.ts) (@studi929)
  • Updated model endpoint test URL path (src/tests/index.test.ts) (@studi929)
  • Added configService.test.ts tests for PORT validation and unknown key warnings (src/services/configService.test.ts)
  • Updated auth.test.ts (200+ lines modified) for new profile-based auth flow (src/services/auth.test.ts)
  • Removed dead-code tests for deleted validateToolCalls, detectToolCallLoop, detectProviderToolLeak (src/tools/guard.test.ts) (@studi929)
  • Replaced dead-code parallel test with placeholder (src/tests/parallel.test.ts)
  • Replaced dead-code parser test file with comment noting parser.ts was deleted (src/tools/parser.test.ts)

Code Quality & Cleanup

  • Removed 12 deleted files: TODO/* (7 files), src/routes/pipeline/StreamingContentFilter.ts, src/tools/parser.ts, src/tools/parserHelpers.ts, src/tools/toolRunner.ts
  • Migrated all console.error/warn calls to structured logStore.log across all services (src/services/loginHelpers.ts, src/services/tokenRefresh.ts, src/services/browserProfiles.ts, src/services/accountManager.ts, src/services/qwen.ts, src/services/playwright.ts)
  • Removed autoFillLogin function export (src/services/browserProfiles.ts)
  • Removed loginToQwen function from playwright.ts (src/services/playwright.ts)
  • Removed getBrowserContext, injectCookies, setCachedCookies, setCachedUserAgent functions (src/services/playwright.ts)
  • Removed logDebug, streamDebugLog debug stubs from chatHelpersCore (src/routes/chatHelpersCore.ts) (@studi929)
  • Removed logIncomingRequest function from chatHelpers (src/routes/chatHelpers.ts)
  • Removed unused safeTruncate export from chatHelpersCore (made private to module) (src/routes/chatHelpersCore.ts)
  • Removed ROBUST_THINK_PATTERN and unused thinking patterns from thinkTagStripper (src/utils/thinkTagStripper.ts)
  • Removed tool/function-related tags from think tag patterns across 4 files (src/utils/thinkTagStripper.ts, src/utils/contentFilter.ts, src/routes/chatHelpers.ts, src/routes/chatHelpersCore.ts, src/routes/chatStreamingHelpers.ts) (@studi929)
  • Fixed type error in processToolCallsThroughGuard call in chatNonStreaming (src/routes/chatNonStreaming.ts)
  • Removed CookieData type export from auth.ts (src/services/auth.ts)
  • Removed ProviderToolLeakResult interface and FunctionEqExtractResult from guard.ts (src/tools/guard.ts)
  • Formatted package.json keywords array to multiline (package.json)
  • Fixed configService.ts unused resolve import (src/services/configService.ts)