Close the uncached readonly adapter after every Desktop export so Windows can delete the session without restarting. Add regression coverage for the successful export lifecycle.
Match ownerless QQ exports safely across UID and UIN drift, preserve merged message scopes through single and batch imports, and apply only sender mappings proven by overlapping platform message IDs. Reject incomplete group mappings to avoid member identity corruption.
Preserve batch support through telemetry, forward item-scoped progress across Desktop and CLI Web, and retain original backend failure details for diagnostics and unfinished results.
Add self-hosted Umami reporting alongside existing telemetry across Desktop and CLI Web.
Track normalized startup, import, feature, and AI usage with a stable anonymous ID and strict privacy allowlists. Keep incremental usage platform-independent and preserve accurate failure classifications and platform metadata across import paths.
Rebase official Demo timelines against the browser timezone, bound stalled downloads, and roll back partial batches across Desktop, CLI Web, and Web WASM. Document the platform cleanup hook's established best-effort boundary.
Route Desktop JSON dry-runs through a shared read-only push analyzer so validation, deduplication, and member inference match actual writes. Keep JSONL on the file analyzer path and cover new and incremental predictions without database mutations.
Use the long-running worker timeout and refresh Desktop caches after successful push imports.
Align auto-created member metadata and counts across initial and incremental imports, exclude SYSTEM from member updates, and keep existing-session writes validated and atomic.
- capture worker reference in sendToWorkerWithProgress to match
sendToWorker and avoid stale-closure risk on worker restart
- replace `as any` casts with typed SupportedLocale / BatchSegmentOptions
assertions in debug-executor
- destructure params.params as toolParams to remove unused testId binding
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The desktop worker kept a second analytics result cache in the same
cacheDir/query directory but invalidated it with a fragile scheme:
app-version .cache_version file, a dev-startup wipe, and explicit
invalidateAnalysisCache() calls after import. Replace it with the shared
getOrComputeAnalysisCache, fingerprinting entries by product version plus
the session DB file state, so the worker (still used by AI tools and the
desktop public REST API) and the shared HTTP routes share one cache and
one invalidation model. Fold the product version into the HTTP-route
fingerprint too, preserving the cross-release invalidation that
.cache_version used to provide, and drop the now-dead invalidation code.
Co-authored-by: Cursor <cursoragent@cursor.com>
The /_web/sessions route never called getAIChatCountsBySession() to
enrich session DTOs, leaving aiConversationCount always 0 in the
data management UI. Use the existing enrichSession callback and
AIChatManager to fill real counts for both list and detail endpoints.
Co-authored-by: Cursor <cursoragent@cursor.com>
Overview cache had no self-invalidation: once written it would return
stale lastMessageTs forever if the postImportHook failed silently.
Analysis query cache (17 chart/stats queries) was never cleared on
import, so charts showed stale data until the user triggered a manual
invalidate.
Add MAX(message.id) fingerprint to OverviewCache and introduce
getValidatedOverviewCache(), which recomputes automatically when new
messages are inserted. Update resolveOverview() in the Electron worker
to use this instead of bare getCache().
In both postImportHooks (incrementalImport, streamImport) also call
deleteSessionCache against the query cache directory so chart data is
fresh after every import.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Include assistant messages with tool content blocks in getHistoryForAgent
even when text content is empty, so multi-turn tool results are not lost
- Append Date.now() timestamp to export filenames to prevent silent overwrites
- Pass 600s timeout to exportFilterResultToFile worker call to match the
actual upper bound of large-session exports
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Harden the startup migration path: fail fast and show an error dialog if
schema migration cannot complete. Repair the gate retroactively for
databases that were already migrated before the gate system existed.
Raise the gate after every import path (full import, incremental import,
stream import) and after opening any database that already carries a
current-segment schema. Centralise gate-raising inside DatabaseManager so
call sites cannot accidentally skip it.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use the packaged app version (not Electron's dev-mode 0.0.0) across all
compatibility checks. Make DatabaseManager require a RuntimeIdentity so
every gate write carries a verified version and kind.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
After incremental import via Electron IPC, the sidebar session list
showed stale message counts. Three contributing gaps:
1. The chat:incrementalImport IPC handler did not notify the renderer
to refresh the session list (unlike the API route which calls
notifySessionListChanged). Added win.webContents.send('api:importCompleted')
to trigger the Sidebar's existing onImportCompleted listener.
2. The postImportHook in worker adapters was async (due to dynamic
import()) but the caller did not await it, causing a race condition
where loadSessions() could read stale overview cache before
computeAndSetOverviewCache() finished. Converted to static import
making the hook synchronous, and updated the type to void | Promise<void>
with await at call sites in both incremental-importer and
streaming-importer.
3. The @imported handlers on group-chat and private-chat pages only
refreshed local analysis data without calling sessionStore.loadSessions().
Added the call so the sidebar updates immediately on the client side.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>