github zhukunpenglinyutong/jetbrains-cc-gui 0.6.3

6 hours ago

✨ Features

  • Update the bundled Claude Code SDK from the chat that needs it (#1937): the API rejects requests from a Claude Code older than a model's minimum version (claude_code_version_too_old), and the hint to update Claude Code does not help because the plugin runs the copy bundled in its own SDK — updating the plugin or the terminal CLI leaves it untouched. The diagnostic card now matches that error and offers an Update SDK button that runs the existing dependency update in place and reports the result there. A successful install bumps a shared SDK generation, so every Claude daemon in the IDE reloads before its next request, while a daemon that is mid-reply is left alone (an update no longer ends a reply with “Daemon stopped”); installs of the same SDK run one at a time, a run where every npm attempt timed out reports failure instead of success, the card names the version it replaced and points at a custom Claude CLI override when that is what needs updating, and its state survives a remount (by @EeeasyCode, @zhukunpenglinyutong)
  • Send editor context beside the message instead of inside it: editor state used to be pasted into the user's message text, spending that message's native context budget and polluting history replay. Each Codex turn now freezes structured additionalContext fragments instead (ide_context, open_tabs, workspace_context, referenced_files_<index>, terminal_context_<index>), so every fragment gets its own budget and the request text stays pristine. The bridge sniffs the selected CLI once per child process (app-server generate-json-schema --experimental) to learn whether turn/start accepts additionalContext, re-sniffs after a runtime replacement, and older CLIs still get the official desktop text envelope with UTF-8 byte ranges shifted to match; history replay strips that envelope so users only ever see their own request (by @gadfly3173)

🔧 Improvements

  • Keep the Node version probe off the JCEF UI thread (#1776): sending a message resolved the Node version synchronously on the UI thread on a cache miss, so the webview froze before the message was even dispatched — 58 ms for a warm <node> --version, 80 ms for a full re-detection, and 5 s when the child wedged. The probe now runs at the top of the existing background task in both send paths, with the same error messages, trigger conditions and invokeLater push semantics (by @yibeiqingke)
  • Bound SDK version lookups and show why a lookup failed (#1972): npm view drained both pipes only after the fact, so a stalled registry request kept the 30 s timeout from firing, and a failure was indistinguishable from an empty list. Queries now drain stdout and stderr while enforcing the deadline, kill the process tree when it expires and surface the npm error code; an EPERM/EACCES cache failure is retried once against a plugin-owned cache (converted for WSL) without losing registry, auth or proxy settings; bundled recommendation versions are no longer presented as available remote versions; and Settings > Dependencies shows the failure with a retry button instead of an empty dropdown (by @GGMGG, @zhukunpenglinyutong)
  • Clean up the metadata of deleted sessions in one batch (#1979): deletion used to start two Node processes per session, one after another, each holding a JVM-wide favorites or titles lock, so deleting 100 sessions meant 200 process starts while history loads in other windows queued on the same locks. removeFavorites and deleteTitles now take a list and do one read and one write, and cleanup calls each service once per batch; the ids travel as JSON on stdin, which has no size limit (a Windows environment variable is capped at 32 KiB) and also reaches WSL node (by @zhukunpenglinyutong)

🐛 Fixes

  • Stop MCP server configs from silently vanishing (#1758): ~/.claude.json is shared with the Claude CLI, and three defects combined to make configured servers disappear “on their own” — a plain FileWriter truncated the file before writing, so a crash left a torn config that every later reader treated as empty; read-modify-write cycles were not serialized, so a concurrent writer's snapshot could revert a just-saved list; and syncMcpToClaudeSettings copied an empty mcpServers over a non-empty one in settings.json, spreading the loss to the second store. Plugin writes to ~/.claude.json and settings.json now go through a staged temp file plus ATOMIC_MOVE, keep a .ccgui-backup that is written atomically and born owner-only on POSIX (these files can hold ANTHROPIC_AUTH_TOKEN), and take an advisory .ccgui-lock; every mutation fingerprints the file with SHA-256, rejects the replace when it changed underneath and re-plans up to 3 times instead of overwriting the other writer. Reads never heal the live file (a failed read may be a newer CLI write in progress), a missing mcpServers key means “no servers” while the loss guard still blocks accidental empties, symlinked configs update their target and keep their POSIX mode, identical content is a no-op with no backup rotation, a corrupt live file is never promoted into the backup, an unreadable file is reported instead of rendered as an empty list, and deleting through the legacy ~/.codemoss/config.json path clears only that entry from settings.json (by @hebulin, @zhukunpenglinyutong)
  • Make the Node service timeout a real deadline (#1778, #1978): executeNodeScript drained stdout to EOF before checking its 30 s timeout, so a child that hung with the pipe open blocked the caller forever and the timeout was dead code for favorites, titles and input history; InputHistoryHandler also wrote stdin synchronously before the timer started, which blocked once the payload outgrew the pipe buffer of a child that never read it. The pattern is now bridge/NodeProcessRunner: stdout is drained and stdin written on named daemon threads, waitFor(timeout) is the only blocking step and also covers stdin, the child is killed and a TimeoutException thrown on expiry, and output is only used once the reader reached EOF — a stdout still open 2 s after exit fails the call instead of returning a truncated result. NodeJsServiceCaller, InputHistoryHandler and ClaudeSessionQueryService all use it, and the session query's 30 s now covers the whole run, including streaming the output (by @yibeiqingke, @zhukunpenglinyutong)
  • Put a real deadline on npm install and cache clean: npm install and npm cache clean read stdout to EOF before waiting, so their timeouts never fired while npm hung with the pipe open — and with the per-SDK install lock in place, one stalled install blocked every later install of that SDK until the IDE restarted. NpmInstallRunner streams output on a daemon thread, enforces the deadline with waitFor and kills the process tree when it passes, and lines never reach the caller's log after it returns; install attempts and cache clean both run through it, waiting for a running install is capped at 20 minutes before reporting that it is still busy, and a WSL install that times out is not retried because killing wsl.exe may leave npm running inside Linux (by @zhukunpenglinyutong)
  • Guide users when JCEF is missing instead of failing to open a chat (#1912, #1953): without the Web Browser (JCEF) module, JBCefBrowser and JBCefOSRHandlerFactory threw a linkage error while the chat window was being constructed, so the tool window broke with no explanation. The entry point now checks that both classes load through the plugin class loader without running their static initializers and shows a Swing panel with install/enable/update guidance before bridge startup, tab restoration or listener registration; Android Studio 2026.2+ on Windows/macOS keeps the plugin-specific text, while other IDEs get IDE-neutral module text because Boot Runtime advice cannot restore missing platform classes. Quick Fix and New Tab surface the same steps in a sticky balloon (Quick Fix checks before its prompt popup), and every locale now says “install, enable, or update” (by @mvanhorn, @zhukunpenglinyutong)
  • Stop JCEF browsers from being recreated while they are being disposed (#1971): tab activation, hierarchy events and remote work could each request the first browser, and a watchdog recreation could run while native resources were being torn down, producing duplicate preparation and use-after-dispose failures. Initial startup is now a single coalesced request (activation and hierarchy requests wait for the tab to be active, remote work forces it), browser creation re-checks ownership after native creation and disposes an instance that lost the race, the default-constructor fallback is only allowed after the failed instance released its native resources and is refused outright when an OSR handler factory is required, disposal still tears native resources down when an unrelated listener or service cleanup throws, and a failed cleanup shows the webview recovery panel instead of a blank tab (by @GGMGG)
  • Recover remote chat tabs instead of leaving them on “Checking SDK status…” (#1967): Remote JCEF can replace a hidden chat page without delivering onLoadEnd, while Java still reports frontendReady for the old document, so tab activation skipped recovery and the new page waited forever for sendToJava. Activation now runs the idempotent bootstrap for the current browser and page generation before scheduling retries (disposed, inactive and mismatched pages are still skipped, and ready pages start none), and a frontend_ready that arrives while Java already holds the flag can only come from such a replaced page, so it is treated as runtime recovery and the current provider, model and reasoning state are pushed before the transcript is replayed (by @Jefung)
  • Keep Codex streaming and replaying every item consistently: streaming could omit commentary, reasoning and edit cards between batches until the conversation was reloaded, and history replay collapsed supported parallel calls into generic exec cards with command labels that differed from live rendering. The transport now compares complete raw message content when choosing the suffix to send (structural signatures only schedule snapshots), and a buffered full snapshot is applied before its dependent tail update advances the sequence barrier. Replay associates Promise.all / allSettled results with their original array slots, keeps labeled arrays, primitives and plain text, restores mixed command and write_stdin batches with polling tied to the original process card, matches identical commands through confirmed process identity or a unique absolute working directory (including file URIs and Windows paths, while preserving literal POSIX backslashes), never assigns unindexed parallel receipts by arrival order, and keeps local Promise computations out of the visible timeline. Recorded summaries, approval reasons and parsed command actions are preserved, list_files and listFiles are both accepted, and generated English command summaries are gone (by @gadfly3173)
  • Reopen Codex approvals only when they are still pending: dialogs closed as soon as the page handed an answer to Java; when Java could not deliver it, the failure acknowledgement reached the page but nothing handled it, so Codex kept waiting on a request the user could no longer see and the turn looked stuck. Each answer is now tracked — a failure shows a toast and reopens the dialog once, unless Java marks it not retryable, the deadline passed, it was already retried, or the runtime closed the dialog. A request that was already answered or released reports INTERACTION_NOT_PENDING, so a later answer cannot resurrect the dialog and override the first choice, and a respondInteraction timeout is marked “delivery unconfirmed” with a warning not to answer again instead of reopening. Control-command timeouts now carry a readable error — a null message became JsonNull, which Gson drops, so timeouts read as success — and command approvals no longer show two identical “allow with this rule” buttons, because the advertised availableDecisions list is used as-is; rule buttons show the command prefix or host they would allow, with the full text on hover (by @zhukunpenglinyutong)
  • Keep a user's API_TIMEOUT_MS and stop leaking provider env values (#1307, #1729): API_TIMEOUT_MS was listed as plugin-managed, so every provider sync deleted a user-configured value, and users running slow local backends (Ollama with 80k+ token contexts) had no way to extend the request timeout. It is no longer managed. The other half of the leak is fixed too: presets that set it themselves, such as MiniMax's 50-minute timeout, carried it over to the next provider, and removing a value while editing a provider left it behind. The sync plan receives the provider recorded in codemossProviderId and removes the unmanaged env values that provider wrote — but only while settings.json still holds that exact value, so a value changed by hand stays (by @hebulin, @zhukunpenglinyutong)
  • Delete favorites and custom titles together with the session: HistoryDeleteService.cleanupSessionMetadata called removeFavorite, which the favorites whitelist did not allow, so the call threw and — because both steps shared one try/catch — the custom-title deletion was skipped as well; deleted sessions kept entries in favorites.json and session-titles.json. removeFavorite is whitelisted, the two steps run independently, and a false result (a failed save still exits 0) counts as a failure, so the log no longer reports a broken cleanup as done. Since every call rewrites the whole file and deletion can now overlap a rename or a favorite toggle from any chat window, NodeJsServiceCaller serializes calls per file with a JVM-wide lock (by @zhukunpenglinyutong)
  • Keep a bad turn cursor from reloading or duplicating history (#1976): getSessionPage parsed the optional beforeTurn cursor inline and accepted any integer-valued number, so a cursor beyond the history length returned the latest page with cursorReset=true and the client discarded its cached transcript for a value that was never usable. Parsing is now a pure parseOptionalTurnCursor(): absent, empty or non-numeric cursors fall back to the latest page, an explicit 0 still means “the page before the first turn”, and a numeric cursor beyond the history keeps cursorReset — that flag is what tells the orchestrator to replace the transcript instead of prepending a latest page and duplicating every visible message (by @hebulin)
  • Treat an empty provider id as “disabled” instead of a config change (#1969): ProviderManager treated an explicit empty currentId as invalid input and rewrote the provider config, so a deliberately disabled provider caused a config write on every load. An empty currentId is now a valid disabled state and no longer triggers a rewrite (by @zhouxiangsuper-create)

中文:

✨ 新功能

  • 在需要更新的会话里直接更新内置 Claude Code SDK(#1937):当模型要求更高版本的 Claude Code 时,API 会拒绝请求并返回 claude_code_version_too_old,而错误里“请更新 Claude Code”的提示没有用——插件运行的是自己 SDK 内置的那一份,更新插件或终端 CLI 都不会改动它。现在诊断卡片会识别该错误并提供「更新 SDK」按钮,复用已有的依赖更新流程原地执行并就地展示结果。安装成功后会推进共享的 SDK 版本号,IDE 内每个 Claude 守护进程都会在下次请求前重新加载,而正在回复的守护进程不会被中断(更新不再让回复以「Daemon stopped」结束);同一 SDK 的安装串行执行,所有 npm 尝试都超时的那次运行会如实报告失败,卡片会说明被替换掉的版本,若真正需要更新的是自定义 Claude CLI 覆盖项也会直接指出,卡片重新挂载后仍保留更新状态(by @EeeasyCode、@zhukunpenglinyutong)
  • 把编辑器上下文放在消息旁边而不是塞进消息里:过去编辑器状态会被直接粘贴进用户消息文本,占用该条消息的原生上下文预算并污染历史回放。现在每轮 Codex 请求改为冻结结构化的 additionalContext 片段(ide_context、open_tabs、workspace_context、referenced_files_<index>、terminal_context_<index>),每个片段各自拥有原生预算,请求文本保持原样。Bridge 会为每个子进程嗅探一次所选 CLI(app-server generate-json-schema --experimental)以确认 turn/start 是否接受 additionalContext,运行时被替换后会重新嗅探;旧版 CLI 仍使用官方桌面端文本信封,并相应平移 UTF-8 文本元素的字节范围,历史回放会剥离该信封,用户只会看到自己写的内容(by @gadfly3173)

🔧 优化

  • 把 Node 版本探测移出 JCEF UI 线程(#1776):版本缓存未命中时,发送消息会在 UI 线程上同步解析 Node 版本,导致消息还没派发 webview 就已卡住——预热过的 <node> --version 阻塞 58 ms,完整重新探测阻塞 80 ms,子进程卡死时阻塞 5 s。现在两条发送路径都会把探测放在已有后台任务的起始位置,错误提示、触发条件和 invokeLater 推送语义均未改变(by @yibeiqingke)
  • 为 SDK 版本查询设定上限并暴露失败原因(#1972):npm view 原本读完两个管道后才开始等待,registry 请求卡住时 30 s 超时永远不会生效,而且失败与空列表无法区分。现在查询会在执行截止时间的同时持续排空 stdout 与 stderr,到期后结束整个进程树并回传 npm 错误码;EPERM/EACCES 缓存失败会用插件自有缓存(WSL 路径已转换)重试一次,同时保留 registry、认证与代理设置;内置的推荐版本不再被当作可用的远程版本展示;「设置 > 依赖」会显示失败原因与重试按钮,而不是一个空下拉框(by @GGMGG、@zhukunpenglinyutong)
  • 批量清理已删除会话的元数据(#1979):过去删除会话会逐个会话启动两个 Node 进程,且各自持有 JVM 级的收藏或标题锁,删除 100 个会话意味着 200 次进程启动,其他窗口加载历史时还要排队等同一把锁。removeFavorites 与 deleteTitles 现在接受列表,一次读取、一次写入,清理逻辑每批各调用一次;id 通过 stdin 以 JSON 传递,没有大小上限(Windows 环境变量上限为 32 KiB),也能被 WSL 下的 node 接收(by @zhukunpenglinyutong)

🐛 修复

  • 修复 MCP 服务器配置静默消失(#1758):~/.claude.json 与 Claude CLI 共用,三个缺陷叠加导致已配置的服务器“自己消失”——普通 FileWriter 会先截断文件,崩溃后留下残缺配置,后续读取一律当作空文件;读-改-写没有串行化,并发写入者的快照可能把刚保存的列表回滚;syncMcpToClaudeSettings 会把空的 mcpServers 覆盖到 settings.json 的非空列表上,把数据丢失扩散到第二份存储。现在插件对 ~/.claude.json 与 settings.json 的写入都走临时文件加 ATOMIC_MOVE,同时维护一份原子写入的 .ccgui-backup(在 POSIX 上创建即为仅属主可读,因为文件可能含有 ANTHROPIC_AUTH_TOKEN),并加 .ccgui-lock 建议锁;每次修改都会用 SHA-256 记录文件指纹,读取后被其他写入者改动就拒绝替换并最多重新规划 3 轮,而不是覆盖对方的写入。读取不再“自愈”写回活动文件(一次失败的读取可能只是 CLI 正在写入更新的内容),缺失 mcpServers 键即表示“没有服务器”,同时丢失防护仍会阻止意外清空;符号链接配置只更新其目标并保留 POSIX 权限,内容相同视为空操作且不轮转备份,损坏的活动文件永远不会被提升为备份,无法读取的文件会报错而不是渲染成空列表;通过旧版 ~/.codemoss/config.json 路径删除时只清除 settings.json 中对应条目(by @hebulin、@zhukunpenglinyutong)
  • 让 Node 服务超时真正生效(#1778、#1978):executeNodeScript 先读 stdout 到 EOF 再检查 30 s 超时,子进程卡住并保持管道打开时会永久阻塞,收藏、标题与输入历史的超时形同虚设;InputHistoryHandler 还会在计时开始前同步写 stdin,载荷超过管道缓冲区且子进程不读取时同样会永久阻塞。现在统一为 bridge/NodeProcessRunner:stdout 由具名守护线程排空、stdin 由具名守护线程写入,waitFor(timeout) 是唯一阻塞步骤且同时覆盖 stdin,超时后终止子进程并抛出 TimeoutException,只有在读取线程到达 EOF 后才使用输出——退出 2 s 后 stdout 仍未关闭则直接失败,而不是返回可能被截断的结果。NodeJsServiceCaller、InputHistoryHandler 与 ClaudeSessionQueryService 都改用它,会话查询的 30 s 现在覆盖整个执行过程(包括流式输出)(by @yibeiqingke、@zhukunpenglinyutong)
  • 为 npm 安装与缓存清理设定真实截止时间:npm install 与 npm cache clean 原本先读 stdout 到 EOF 再等待,npm 卡住并保持管道打开时超时永不触发——配合按 SDK 的安装锁,一次卡死的安装会阻塞该 SDK 之后的所有安装,直到 IDE 重启。NpmInstallRunner 用守护线程流式读取输出,用 waitFor 强制执行截止时间并在超时后结束整个进程树,返回后不会再向调用方日志输出任何行;安装尝试与缓存清理都走这条路径,等待正在进行的安装最多 20 分钟,之后报告仍在忙;WSL 安装超时后不再重试,因为杀掉 wsl.exe 可能让 npm 继续在 Linux 内运行(by @zhukunpenglinyutong)
  • JCEF 缺失时给出指引,而不是让会话打不开(#1912、#1953):缺少 Web Browser (JCEF) 模块时,JBCefBrowser 与 JBCefOSRHandlerFactory 会在构造聊天窗口阶段抛出链接错误,工具窗口直接坏掉且没有任何说明。现在入口会在启动 bridge、恢复标签页或注册监听器之前,检查这两个类能否通过插件类加载器加载(不触发静态初始化),失败时显示带安装/启用/更新指引的 Swing 面板;Windows/macOS 上的 Android Studio 2026.2+ 保留插件专用文案,其他 IDE 使用与 IDE 无关的模块文案,因为 Boot Runtime 建议无法恢复缺失的平台类。Quick Fix 与新建标签页会用常驻气泡展示同样的步骤(Quick Fix 在弹出输入框前先检查),所有语言文案统一为“安装、启用或更新”(by @mvanhorn、@zhukunpenglinyutong)
  • 避免在销毁 JCEF 浏览器的同时重建它(#1971):标签页激活、层级事件与远程任务都可能请求创建首个浏览器,看门狗重建还可能在原生资源正在释放时执行,导致重复准备与释放后使用。现在初次启动合并为一次请求(激活与层级事件会等标签页处于活动状态,远程任务则强制启动),浏览器创建后会在原生创建返回时重新校验归属并释放竞争失败的那个实例;默认构造函数兜底只允许在失败实例释放原生资源之后使用,且必须有 OSR 处理器工厂时直接拒绝;即使无关的监听器或服务清理抛异常,释放流程仍会完成原生资源清理;清理失败时显示 webview 恢复面板,而不是空白标签页(by @GGMGG)
  • 远程聊天标签页不再卡在「正在检查 SDK 状态…」(#1967):远程 JCEF 可能在不投递 onLoadEnd 的情况下替换隐藏的聊天页面,而 Java 仍为旧文档保留 frontendReady,于是标签页激活时跳过恢复,新页面永远等不到 sendToJava。现在激活会先对当前浏览器与页面代次执行幂等引导,再安排重试(已释放、非活动与代次不匹配的页面仍会跳过,已就绪的页面不会重试);若 Java 仍持有就绪标记时又收到 frontend_ready,那只能来自被替换的页面,会被当作运行时恢复处理,先推送当前的供应商、模型与推理强度状态,再回放会话记录(by @Jefung)
  • Codex 流式输出与历史回放保持一致:流式过程中可能丢失批次之间的评论、推理与编辑卡片,必须重新加载会话才能看到;历史回放还会把支持的并行调用压缩成通用 exec 卡片,命令标签也与实时渲染不一致。现在传输层选择要发送的增量时会比较完整的原始消息内容(结构签名只用于安排快照),缓冲的完整快照会在其依赖的尾部更新推进序号屏障之前应用。回放会把 Promise.all / allSettled 的结果对应回原始数组槽位,保留带标签的数组、原始值与纯文本,恢复命令与 write_stdin 混合批次并让轮询绑定到原进程卡片;相同命令通过已确认的进程身份或唯一的绝对工作目录匹配(包括 file URI 与 Windows 路径,同时保留 POSIX 字面反斜杠);无索引的并行回执绝不会按到达顺序分配;本地 Promise 计算不再出现在可见时间线中。记录下来的摘要、审批原因与解析后的命令动作都会保留,list_files 与 listFiles 两种写法都接受,自动生成的英文命令摘要已移除(by @gadfly3173)
  • 只在 Codex 仍在等待时重新打开审批框:页面把答案交给 Java 后对话框立即关闭;若 Java 无法投递,失败回执会到达页面却没有人处理,Codex 便一直等待用户已经看不到的请求,这一轮看起来就卡住了。现在会跟踪页面发出的每个答案——失败时弹出提示并重新打开一次对话框,除非 Java 标记为不可重试、已过截止时间、已经重试过,或运行时已关闭该对话框。已作答或已释放的请求会返回 INTERACTION_NOT_PENDING,之后的答案无法再复活对话框并覆盖第一次选择;respondInteraction 超时会被标记为「投递未确认」,提示用户不要再次作答,而不是重开对话框。控制命令超时现在带有可读错误——null 消息会变成 JsonNull 并被 Gson 丢弃,导致页面把超时读成成功;命令审批也不再出现两个一模一样的「允许并使用此规则」按钮,因为服务端公布的 availableDecisions 列表已包含该修正,现在直接按原样使用;规则按钮会显示它将要允许的命令前缀或主机,悬停可看完整内容(by @zhukunpenglinyutong)
  • 保留用户配置的 API_TIMEOUT_MS,不再泄漏供应商环境变量(#1307、#1729):API_TIMEOUT_MS 曾被列为插件托管键,因此每次供应商同步都会删掉用户配置的值,使用较慢本地后端(80k+ token 上下文的 Ollama)的用户无法延长请求超时。现在它不再由插件托管。另一半泄漏也一并修复:自身设置该值的预设(例如 MiniMax 的 50 分钟超时)会把它带到下一个供应商,编辑供应商时删除某个值也会残留。同步计划现在接收 codemossProviderId 中记录的供应商,并清除该供应商写入的非托管环境变量——但仅当 settings.json 中仍是该确切值时才清除,用户手动改过的值会保留(by @hebulin、@zhukunpenglinyutong)
  • 删除会话时一并清理收藏与自定义标题:HistoryDeleteService.cleanupSessionMetadata 调用了 removeFavorite,但收藏白名单不允许该函数,调用直接抛异常,而两步共用一个 try/catch,导致自定义标题也一并被跳过;被删除的会话在 favorites.json 与 session-titles.json 中留下残留。现在 removeFavorite 已加入白名单,收藏移除与标题删除作为两个独立步骤执行,服务返回 false(保存失败仍以 0 退出)也会被视为失败,日志不再把失败的清理报告为完成。由于每次调用都会重写整个文件,且删除现在可能与任意聊天窗口的重命名或收藏切换重叠,NodeJsServiceCaller 会用 JVM 级锁按文件串行化调用(by @zhukunpenglinyutong)
  • 避免错误的翻页游标导致历史重载或重复(#1976):getSessionPage 曾在原地解析可选的 beforeTurn 游标,并接受任意整数值,超出历史长度的游标会返回最新一页且 cursorReset=true,客户端于是为一个从未可用的值丢弃缓存的历史。现在解析逻辑抽成纯函数 parseOptionalTurnCursor():缺失、空值或非数字游标回退到最新一页,显式的 0 仍表示“第一轮之前的那一页”,超出历史长度的数字游标则保留 cursorReset——正是该标记让编排器替换会话记录,而不是把最新一页前置导致每条可见消息重复(by @hebulin)
  • 空供应商 id 视为「已禁用」而不是配置变更(#1969):ProviderManager 曾把显式为空的 currentId 当作非法输入并重写供应商配置,于是有意禁用的供应商每次加载都会触发一次写入。现在空 currentId 是合法的禁用状态,不再触发重写(by @zhouxiangsuper-create)

What's Changed

  • docs(changelog): add v0.6.2 release notes by @zhukunpenglinyutong in #1964
  • Feature/claudecode provider noop config write by @zhouxiangsuper-create in #1969
  • fix(jcef): fence browser startup, recreation and resource disposal by @GGMGG in #1971
  • fix(settings): stop stripping user-configured API_TIMEOUT_MS on provider sync by @hebulin in #1729
  • fix(webview): restore lost bridges when reactivating remote chat tabs by @Jefung in #1967
  • fix(dependencies): bound SDK version queries and expose lookup failures by @GGMGG in #1972
  • refactor(bridge): extract turn-cursor parsing into a tested helper by @hebulin in #1976
  • fix(claudecodegui): show JCEF installation guidance before chat window construction by @mvanhorn in #1953
  • feat(claude): offer an in-place SDK update when Claude Code is too old for the model by @EeeasyCode in #1937
  • perf(session): move node version probe off the JCEF UI thread by @yibeiqingke in #1776
  • fix(history): make the node-service timeout actually reachable by @yibeiqingke in #1778
  • fix(mcp): stop MCP server configs from silently vanishing by @hebulin in #1758
  • fix: make the Node child timeout a real deadline for input history and session queries by @zhukunpenglinyutong in #1978
  • fix: clean up favorite and custom title when a session is deleted by @zhukunpenglinyutong in #1979
  • Feature/v0.6.3 by @zhukunpenglinyutong in #1975

New Contributors

Full Changelog: v0.6.2...0.6.3

Don't miss a new jetbrains-cc-gui release

NewReleases is sending notifications on new releases.