Use native Window Controls Overlay geometry and sampled background colors so caption hover and drag regions track the system title bar.
Forward original Windows close-handler errors to the shared logger so failures retain their stack traces.
Remove the one-time close prompt and remembered-choice path so Windows close behavior is always explicit and predictable. New installations now minimize to the system tray by default, while users can still choose to quit from settings.
Compress oversized browser history in model-sized stages so switching to a smaller model can recover. Bound the recent-history fallback when summarization fails without deleting persisted messages.
Avoid matching OpenAI-compatible model IDs across providers. Use an 8K fallback so automatic compression runs before unknown providers reject long conversations.
Limit prereleases to desktop artifacts, keep stable releases gated on CLI success, and start Docker publishing as soon as the npm package is available.
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.
Carry owner metadata through merge exports when every source agrees and the owner resolves to a merged member. Drop conflicting or unmappable owner identifiers.
QCE exports can mix UIN and UID namespaces while exposing only observed senders. Keep owner metadata unset across TypeScript, chunked, and native parser paths unless it can be mapped safely.
Keep one-member private exports source-local until exact message overlap proves they belong to the same chat. This prevents unrelated outgoing-only chats from losing messages when platform IDs collide.
Forward the selected keywords through the shared HTTP route without persistent caching, keep large templates out of the request URL, and reject empty keyword sets before building a regular expression. Ignore superseded analysis responses so rapid keyword changes cannot restore stale rankings or loading state.
getKeywordColor() indexed KEYWORD_COLORS with indexOf() result, which
returns -1 for types not present in currentKeywords (e.g. the
server-generated '其他' aggregate in typeDistribution). KEYWORD_COLORS[-1]
is undefined, so reading .wrapBg threw a TypeError when enabling
multi-color mode. Fall back to a stable keyword hash for unknown types.
Record background preload polling failures with the original Error and clarify that logging review severity and tests should follow user impact rather than mechanical rules.
The CLI tsup build inlines @openchatlab/node-runtime into dist chunks.
Both sqlite-vec and @huggingface/transformers load platform-specific
native packages at runtime (sqlite-vec-linux-arm64, onnxruntime-node,
sharp), so inlining them breaks global/npm and Docker installs of
chatlab-cli: the bundled chunks reference native packages that were
never installed, and configuring the semantic index vector model fails
with HTTP 500 (Cannot find package 'sqlite-vec-linux-arm64').
Declare both packages as chatlab-cli dependencies and mark them as tsup
external so they are installed from npm with their native bindings,
matching how better-sqlite3 and @node-rs/jieba are already handled.