Tool and parameter descriptions were handed to the LLM in Chinese on every
runtime regardless of locale: the English metadata table in
packages/tools/src/tool-metadata.ts had no caller, the desktop translateTool
looked up i18n keys that exist in no locale file, and the MCP server had no
locale at all.
Fill the table for every tool whose definition text is Chinese (37 entries,
only translating what the definitions write in Chinese so the two copies
cannot drift), and route the four consumers through getLocalizedToolMetadata:
the cross-chat agent adapters, the CLI Web agent adapter, the desktop shared
tool adapter (replacing the dead translateTool), and the MCP server, which
now resolves its locale from config.locale.lang or the system locale for both
the standalone binary and the chatlab mcp subcommand.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sort each indexed segment once per request instead of scanning and sorting it for every hit. Preserve backfilled chronological neighbors and segment boundaries in both query adapters, with a large-segment regression test.
Preserve partial output and token usage in CLI turns and edited UI rounds while leaving ordinary failures and cancellation unchanged. Use OutputLimitError across agent runners so incomplete turns remain visibly unsuccessful but can be reloaded and continued.
Cover real stream handling, SQLite persistence, reload, CLI continuation, and unsuccessful one-shot JSON output.
POST /_web/cache/save-to-downloads joined the caller-supplied `filename`
straight into the downloads directory:
const filePath = path.join(downloadsDir, filename)
`path.join` collapses `..`, so `{"filename":"../escaped.txt"}` resolved
one level above the downloads directory and the route wrote
attacker-chosen bytes there, returning `{ success: true }`. Any client
that can reach the route could therefore write outside the downloads
directory as the app user.
The route is registered by the shared web routes on both CLI Web and the
Electron internal API, so the fix covers both. Its own siblings already
constrain this input — merge.ts and the CLI upload route both run the
name through `path.basename` — so the missing guard here was an
oversight rather than a documented allowance.
Reject anything that is not a plain file name, and join only the
validated basename. Names the app itself sends stay unchanged: every
caller (conversation export, SQL export, screen capture) already passes a
flat file name.
Reusing emoji cleaning also removed ordinary bracketed labels from language vocabulary. Preserve unknown bracketed text for language profiles while retaining known emoji filtering and the existing word-frequency behavior. Add a regression for annotated chat messages.
Voice transcription normalization can remove every phrase for a member while leaving an empty member entry. Filter those entries from the result so overview and selected-member views retain their empty states.
Add a regression test for single-use transcriptions alongside another member with valid catchphrases.
Clamp cluster look-ahead values at the shared core boundary so invalid inputs cannot create oversized candidate matrices. Add a regression test that keeps oversized values equivalent to the supported maximum.
Preserve repeated same-second WeFlow and EchoTrace messages while consuming existing fallback occurrences one for one across overlapping imports and merged sources.
Capture the conversation active message when the agent turn completes so an automatically persisted compression summary becomes the expected parent for the pending user message. Add an integration regression covering summary persistence, memory creation, message-pair persistence, and source linking.
Remove the wall-clock expiry from in-flight memory provenance so long agent investigations can still link memories to their source messages. Clean up completed turns without memory changes immediately and retain changed turns until the client consumes them.
Keep compression summaries before the in-flight question and let the Node runtime validate and atomically replace only the terminal question-answer round.
Replace the edited user message, old assistant response, and regenerated response in one SQLite transaction. This prevents a failed replacement insert from leaving a partially rewritten conversation.
中文:将用户与助手消息合并为单事务写入,失败时不再留下孤儿消息或误报成功。
English: Persist user and assistant messages in one transaction so failures leave no orphaned turn or false success.
中文:避免同秒消息跨摘要边界,防止已压缩内容重复回放或后续消息丢失。
English: Keep equal-timestamp messages on one boundary side so compressed content is not replayed and later messages remain visible.
Use dependency-independent Chinese tokenization, preserve prompt capacity for the highest relevance match, and handle short symbolic and numeric terms without distorting bounded recall.
中文:同名 LLM 配置此前会覆盖同一 auth profile;现在按稳定 config ID 隔离,并保留旧 profile 恢复。
English: LLM configs with the same name previously overwrote one auth profile; new profiles are scoped by stable config ID while legacy restoration remains compatible.
Remove the proactive-memory preference and its cross-platform runtime plumbing so memory behavior has one clear contract. Normalize away the obsolete setting and keep source type limited to provenance.
Share entities resolved during one Agent run so natural-language subject changes can safely use memory. Validate entity memory scope before permanent deletion to prevent stale IDs from deleting another subject's memory.
Include the normalized time-filter request in structural-inspection fingerprints while retaining the cursor's resolved absolute range, so stable relative pagination works but changed filters are rejected.
Interpret recent-day filters as complete local calendar days and persist the first resolved range in structural-inspection cursors so pagination remains stable across clock and date changes.