Skip to content

Preview - #1484

Merged
1lck merged 67 commits into
mainfrom
preview
Oct 25, 2026
Merged

Preview#1484
1lck merged 67 commits into
mainfrom
preview

Conversation

@1lck

@1lck 1lck commented Oct 25, 2026

Copy link
Copy Markdown
Owner

No description provided.

xiaoyumuxi and others added 30 commits October 22, 2026 09:12
* feat(macos): 按设计稿改造“管理插件仓库”弹窗

插件页齿轮菜单里的“管理插件仓库…”弹窗改成设计稿的样式,添加、刷新、
停用和移除的行为不变。

- 仓库列表放进圆角卡片,每行是名称、等宽地址和状态行,右侧依次是启用开关、
  “刷新”和红色“移除”;输入框改用设置页共享的文本框样式,示例地址作为
  逐字提示,不再被 markdown 渲染成蓝色链接。
- “Lithe 官方”行只能停用、不能移除,用灰色“默认”代替“移除”。
- 地址一行显示用户认得出的内容:Lithe Store 显示 GitHub 仓库地址,官方源显示
  Plugins/marketplace/index.json,实际抓取的索引地址放进悬停提示。
- 刷新时间改成相对时间:一分钟内“刚刚”,一周内“5 分钟前”,更早显示日期;
  弹窗打开期间每 15 秒重新计算。时钟被调回时也显示“刚刚”。
- 停用的源在状态行标注“已禁用”,“全部刷新”在没有启用的源时置灰,完成按钮
  使用主色强调。
- 新增 PluginRepositoryPresentationTests 覆盖相对时间的边界和地址展示规则;
  功能矩阵的插件市场验收描述同步补充弹窗的新表现。

* chore(macos): 移除插件仓库弹窗不再使用的占位文案 key

* feat(macos): 插件仓库弹窗行内加官方/社区标签,复用相对时间格式化器
* perf(macos): 设置窗口与工作台变化解耦,拖动交给窗口服务器

- 设置窗口只订阅 AppModel.settingsChanges,功能模块的高频转发不再重建设置页
- 标题栏拖动时临时解除子窗口关系,松手后挂回项目窗口,拖动跟手
- 设置窗口外观仅在配置变化时重新应用;插件列表单次排序过滤、悬停状态下沉到行
- 新增 AppModelSettingsChangesTests,更新性能边界 Agent Note

* fix(macos): 运行配置页在执行模块休眠后改用新实例,补充标题栏拖动事件回归

- 新增 ModuleFeatureSelection:激活任务以当前能力身份为 key,休眠后丢弃已释放的 RunFeatureModel 并重新激活
- 激活中显示加载状态;被取消的激活任务不再覆盖选择
- SettingsWindowChrome.handleTitlebarMouseEvent 抽出,用原生鼠标事件测试脱离/挂回/关闭后重开
- 更新性能边界 Agent Note
* fix(macos): 隐藏路径的普通名称同时隐藏同名文件夹,并让 .lithe 隐藏后仍被监听

问题:在设置 → 隐藏路径的“文件模式”里输入 `.lithe`,项目树里的 `.lithe`
文件夹仍然显示,里面的内容也照常被加载。原因是文件模式只匹配文件。

- 规则:不含 `*`、`?`、`/` 的普通名称(如 `.lithe`)同时隐藏任意层级的同名
  文件和文件夹,不区分大小写;带通配符的写法仍只匹配文件,末尾 `/` 仍是
  从项目根起的文件夹规则(shared/fixtures/search/exclusions.json 固定)。
- 加载:被隐藏的文件夹在列目录和快照时直接剪枝,不再读取其内容;搜索索引
  与本地历史按同一规则对齐,Swift 侧的 FileVisibilityRules 同步镜像。
- 监听:工作区根下的 `.lithe` 是唯一的“显示”和“监听”分离的特例。默认它仍
  按普通逻辑显示;无论用户用哪种写法隐藏它,文件事件都照常送达,修改其中的
  JSON 配置仍会重载项目服务。内置噪声(如 .lithe/run/local.json)仍丢弃,
  嵌套的 .lithe 不享受该例外。
- 界面:隐藏路径的“目录”和“文件模式”改为同一张卡片内左右并排,应用按钮
  放在右下;说明文字和简体中文翻译按新规则更新。
- 文档:更新 rust-core-api 契约、Agent 笔记和功能矩阵;Windows 沿用既有
  gitignore 语义,不在本次范围。
- 测试:新增 Rust 文件树/本地历史测试、共享 fixture 用例,以及 Swift 的
  可见性、监听分类和工作区模型测试。

* fix(macos): 隐藏文件夹改为显式模式匹配,`.lithe/*` 隐藏整个文件夹

上一版让文件模式里的普通名称同时隐藏同名文件夹,需要猜“这个名字指文件还是文件夹”。
改为全部走显式模式匹配,规则只由模式本身决定。

- 以 `/`、`/*` 或 `/**` 结尾的条目都是从项目根起的文件夹规则:`.lithe/`、
  `.lithe/*`、`.lithe/**` 效果相同,文件夹连同内容一起隐藏并在列目录时剪枝,
  不会留下空文件夹;`**/.lithe/*` 可覆盖嵌套副本。
- 普通名称(如 `.lithe`)和带通配符的文件 glob 恢复为只匹配文件,Local History
  的匹配恢复原样。
- Rust Core 与 Swift FileVisibilityRules 同步;共享 fixture 改为 `generated/*`、
  `docs/**`、`notes` 用例,固定文件夹规则与文件规则的边界。
- `.lithe` 隐藏后仍被监听的特例保持不变,测试改为用 `.lithe/*` 等写法覆盖。
- 设置页 ⓘ 说明和简体中文翻译改为介绍 `/`、`/*` 写法;契约、Agent 笔记和功能
  矩阵同步更新。

* feat(macos): 隐藏路径合并为一个模式列表,`**/` 可匹配任意层级

- 设置页把“目录”和“文件模式”两个输入框合并为一个模式列表,应用按钮在右下;
  内置规则以只读胶囊回显(悬停查看全部),始终生效且不可移除
- ⓘ 说明写明语法是不区分大小写的通配符(正则的简化写法),并给出
  `**/dist/`、`.lithe/*`、`*.log`、`docs/*.md` 四个示例
- 匹配器中开头的 `**/` 代表零层或多层目录,`**/tmp/` 同时覆盖根目录和嵌套的
  `tmp`;Rust 与 Swift 同步实现,Search Everywhere 不再自行补根目录写法
- 升级时合并旧的两个列表:自定义目录名迁移为 `**/名称/`,文件模式原样保留,
  内置项不复制;旧存储键保留,新键保存后不再读取
- 共享 fixture 增加 `**/tmp/`、`**/secret.txt` 用例,Rust 搜索索引测试改为
  直接读取 fixture 中的规则,避免两边规则列表漂移
- 同步更新 Core 契约文档、Agent Note 和功能矩阵

* fix(core): Local History 复用统一的隐藏路径规则

Local History 原来用自己的简易匹配器(目录按名称相等、文件按完整文件名),
设置里的 `**/generated/`、`.lithe/*`、`*.log` 等模式对它不生效:文件树和
搜索已经隐藏的路径,保存时仍会写入快照并出现在历史列表里;旧版自定义目录名
迁移成 `**/name/` 之后,也不再被 Local History 识别。

- history.record / history.entries 改用文件树共用的 VisibilityRules,
  删除 history.rs 里的私有匹配器,并补充对应的核心测试和契约说明
- Windows 调用 Local History 时不传隐藏列表,现在也会跳过与文件树一致的
  内置目录(build、dist、coverage 等)
- VisibilityRules.is_hidden 与 Swift FileVisibilityRules.isHidden 只拼接
  一次祖先路径前缀,供所有文件夹规则共用,不再按规则重复拼接
- 迁移函数 hiddenPathPatterns(migratingFrom:) 改名为
  migratedHiddenPathPatterns(from:),避免和同名属性混淆
* test(plugins): cover independent Cargo build plugin compatibility

* docs(plugins): move Cargo compatibility ownership to plugin CI
* fix(macos): HTML 预览改为内嵌浏览器,支持导航、缩放、滚动条与开发者工具

旧预览用 loadHTMLString 加载文本并取消所有导航,也没有 WKUIDelegate,
页面只能看不能用。改为内嵌的单标签浏览器:

- 页面通过自定义协议 lithe-html://preview/<路径> 提供(同源、安全上下文),
  模块脚本、fetch、XHR、锚点和以斜杠开头的路径都能工作;当前文档来自编辑器
  缓冲区,其余文件只读。
- 拒绝隐藏文件和密钥扩展名、非预览来源的子资源请求,导航策略永不加载 file:。
- 导航规则为可单测的纯函数表:链接、锚点、target=_blank/window.open 在预览内
  跟随,mailto/tel/sms 仅在用户点击时交给系统,顶层 data:/blob: 取消。
- alert/confirm/prompt、文件选择、下载分别用 NSAlert/NSOpenPanel/NSSavePanel 呈现。
- 工具栏:后退、前进、刷新/停止、地址栏、页面缩放(−/百分比/+,⌘+ ⌘− ⌘0)、
  在系统浏览器中打开、开发者工具(私有 _WKInspector,带可用性检查)。
- 内容溢出时常驻显示纵向和横向滚动条,缩放时仍保持约 14pt,页面自带样式优先。
- 编辑内容变化后防抖刷新并保留滚动位置;加载失败显示错误横幅。
- 补充中英文本地化、Agent Note、跨平台功能矩阵和单元测试。

* fix(macos): 修复 HTML 预览评审发现的问题

- 另存为内部资源时,若目标就是源文件本身则直接保留,避免先删后拷导致原文件丢失;
  预览中的当前文档另存为时写入编辑器里的文本
- 切换到另一个 HTML 标签页时,预览立刻显示该文档的内容,不再停留在上一份文档
- 点击浏览器无法展示的链接文件(zip 等)时,弹出保存面板而不是什么都不发生
- 地址栏输入目录时补上结尾斜杠,目录 index 里的相对链接和资源不再解析到上一级
- 文档页仍在加载时收到更新,改用 load 而不是 reload,避免重载上一份文档
- WebContent 进程被终止后自动重新加载(连续失败最多恢复 2 次),不再留下空白预览
- 资源读取队列改为并发队列,大文件不再挡住脚本和样式
- 滚动条脚本的字符串字面量改用 JSONEncoder 生成
- 补充文档切换、新窗口链接、不可展示文件保存、download 属性、目录地址、同文件保存的测试,
  并更新 Agent Note

* fix(macos): HTML 预览补齐 iframe 滚动条缩放、目录链接重定向与 scheme 任务共用

- 页面缩放时,页面里 iframe 的滚动条也保持 14pt:每个子 frame 的脚本启动时通过
  litheScrollbarFrame 消息上报自己(带标识文档的 token),控制器保存 WKFrameInfo,
  缩放后逐个执行更新脚本;frame 消失、换了文档或主框架提交新文档时清理,上限 128 个
- 不带结尾斜杠的目录链接(<a href="docs">、location 跳转、iframe src)由导航层
  取消并改为加载带斜杠的地址,主框架直接加载,iframe 用 location.replace,
  目录首页里的相对脚本、图片和链接不再解析到上一级;查询串和片段保留
- HTML 预览与 Markdown 预览的 scheme 处理器共用 LocalFileSchemeTasks(任务登记、
  claim、stop)和 LocalFileContainment(按路径分量判断根目录包含);Markdown 处理器
  同时改为在主线程投递应答,避免 stop 插在 claim 与投递之间
- 抽出 HTMLPreviewScript.literal,滚动条脚本和 frame 重定向共用 JS 字符串字面量
- 新增 iframe 缩放滚动条、链接/iframe 目录重定向、folderRedirect、任务 claim 与
  路径包含的测试,并更新 Agent Note
* fix(git): 大型未跟踪目录按目录汇总,变更列表只构建可见行 (#1385)

根因有两层:
- Core 的 git.status 使用 --untracked-files=all,一个未忽略的 target/
  会变成 5,000+ 条变更,每次刷新都要编解码、比较、分组和着色。
- macOS 多仓库变更列表把每个仓库的全部行包在一个 VStack 里,外层
  LazyVStack 只能按仓库懒加载,仓库可见时其下所有行都会被创建。

Core:
- git.status 新增 summarizeUntrackedDirectories:使用 -unormal,超过
  100 个文件且不含嵌套仓库的整目录报告为一条带 untrackedFileCount 的
  汇总;含嵌套仓库(如 .worktrees/)的目录递归拆分,避免暂存产生 gitlink。
- 新增 git.untrackedDirectory 按层列出目录内容。
- git.diff 的未跟踪目录路径展开为逐文件 diff,保证 Shelve 不会生成空补丁
  后清理目录;discardAll 识别未跟踪目录路径。
- 不传参数时行为不变(Windows 仍为逐文件)。

macOS:
- 变更面板使用汇总快照;目录节点可展开,展开内容在每次刷新时重新列出
  并紧跟在汇总后。
- 项目树、编辑器行标记、ChangeList 归属对汇总目录下的文件保持逐文件
  语义;计数按文件统计且不重复计算。
- 变更列表拍平成行,每个标题和变更都是 LazyVStack 的直接子项。

其他:新增 Agent Note、功能矩阵记录、契约说明、本地化文案;.gitignore
补充 rust/*/target/ 与 /.worktrees/。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(git): 汇总目录的 ChangeList 提交范围与批量写操作 (#1385)

自审发现的两处问题:
- ChangeList 只记录汇总目录的 `dir/` 键,而 Core 的 PathScope 按字面路径
  比较。暂存后的文件在界面上属于该 ChangeList,提交时却会被拒绝;在默认
  列表中提交则会绕过隔离检查。commitScope 现在会把继承目录归属的文件
  逐个列出。
- 展开状态下,Rollback 和 Shelve 会同时处理汇总及其子项:补丁里同一文件
  出现两次,恢复搁置失败;汇总被清理后子项的 restore 报错并中断。现在先
  去掉被同批汇总覆盖的子项。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(windows): summarize large untracked directories in the Commit view

Windows now opts into Core's untracked directory summaries (#1385):

- Store status reads pass summarizeUntrackedDirectories and splice the
  listed contents of expanded summaries in after them, so
  repositoryStatuses stays the single published status. One-off readers
  (Shelf, diff review, GitHub) keep the file-level projection.
- The status panel shows a summary as one directory row with its file
  count; the chevron lists one level at a time, and in folder view the
  folder built from an expanded summary stands for it.
- Counts follow files, the project tree, gutter and line history treat
  files below a summary as untracked, ChangeList assignments of a summary
  are inherited and listed by path in the commit scope, and deletion and
  diff skip contents a summary already covers.
- Feature matrix marks Windows implemented; the Agent Note records the
  Windows design.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(git): never clean what Shelve could not export; respect toggles during refresh

Addresses the PR review of #1385:

- Core: an untracked directory diff fails instead of skipping a file whose
  name the path guard rejects (e.g. `bad:name.txt`). Shelve cleans the whole
  directory after saving, so a skipped file was deleted without a copy.
- macOS Shelve: workingDiffPatch/stagedDiffPatch return nil when Git could
  not export a change, and captureAndCleanShelf aborts before saving or
  cleaning anything. A failed read used to be treated as an empty patch.
- macOS and Windows: when the user collapses or expands a summary while a
  refresh awaits a listing, the result is rebuilt from the current
  expansions (reusing listings already read) instead of publishing the
  stale set; only expansions requested at the start can be forgotten.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(git): stop implicit upstream tracking from rewriting remote main (#1272)

Creating a branch from a remote reference inherited that reference as its upstream through Git's default branch.autoSetupMerge. A feature branch started at origin/main therefore tracked refs/heads/main, and the next push sent the explicit refs/heads/<name>:refs/heads/main refspec over the remote main branch.

- createBranch now passes --no-track so the result no longer depends on user Git preferences; checking out a remote branch keeps its tracking semantics.
- pushPreview reports targetKind (publish/tracking/divergent) and createsRemoteBranch, so callers can show the full direction.
- A divergent upstream is no longer the implicit destination; push requires an explicit pushTarget choice (publish to the same-named branch, or keep the upstream).
- validatePushExpectation also verifies targetKind, rejecting a destination that changed after the preview.
- Shared push-preview fixture and Core unit test updated for the new fields.

* fix(git): keep reviewed pushes working without targetKind (#1272)

The new targetKind field was compared strictly against expectedPush. A caller that omits the field deserializes it as None, which never equals Some(...), so every reviewed push from a client that predates target kinds was rejected as a stale preview.

- Compare targetKind only when the caller supplies it, so omission keeps the previous behaviour while an explicit mismatch is still rejected.
- Add both directions as tests: omitting targetKind pushes normally, a wrong one is still refused as stale.
- Cover the worktree tracking semantics the issue asks about: a remote start tracks that branch, an explicit commit start tracks nothing.
- Document targetKind, createsRemoteBranch, pushTarget and the divergent confirmation rule in the shared Rust Core contract.

* feat(git): show and confirm the push destination on Windows (#1272)

The push dialog now surfaces where a push will actually go and asks the user to choose when the branch tracks a differently named remote branch.

- Push preview types carry targetKind and createsRemoteBranch, and the API forwards an optional pushTarget.
- The dialog header shows 'local -> remote/branch' and marks a not-yet-existing remote branch.
- A divergent upstream renders an inline choice instead of pushing silently: publish to the same-named branch, or keep the existing upstream. The push button stays disabled until one is picked, and a refreshed preview clears the earlier choice.
- Same-named and first-publish pushes keep their current one-click behaviour.
- Localized the new strings for English and Chinese.

* fix(git): settle the commit-and-push destination before committing (#1272)

Commit-and-push runs its push step from Core without a reviewed preview, so on a branch tracking a differently named remote branch it committed first and only then failed the push.

- Workspace commit plans carry an optional pushTarget, and the push step forwards it, so a confirmed destination survives the commit/push split.
- The commit panel resolves the destination before writing the commit and asks when the branch is divergent; cancelling aborts without committing.
- A preview failure does not block committing, because the push step still reports its own error.
- New prompt dialog names both destinations explicitly, with a test per case.

* feat(macos): accept a confirmed push destination in the Git bridge (#1272)

macOS pushes without a preview layer, so a branch tracking a differently named upstream now fails with an actionable error instead of updating that branch. This lets the bridge carry an explicit destination once the macOS surface offers the choice.

- GitWriteRequest and gitWriteResult accept an optional pushTarget that is omitted for routine pushes.
- The GitOperations protocol and the Git service surface the same optional parameter; both test doubles were updated to match.
- No UI or behaviour change otherwise: existing callers keep their current signature and semantics.

* docs(matrix): record the issue #1272 push destination evidence

Adds the push preview, push dialog, target prompt and Core push regression tests to the git-branches-remotes evidence, and notes what is verified (Windows automation) versus what is not (macOS GUI).

* docs(notes): record the push destination and upstream tracking decision (#1272)

Explains why branch creation stops inheriting an upstream, how a divergent destination must be confirmed, and why adding an optional review field must stay backward compatible. Records the rejected alternatives and what is verified per platform.

* style: apply rustfmt and fix test typing (#1272)

* fix(git): resolve a confirmed upstream destination with the shared splitter (#1272)

Confirming 'continue pushing to the existing upstream' parsed the upstream short name with rsplit_once('/') and took the last segment as the branch name. An upstream short name is remote/branch and either side may itself contain slashes, so on a branch tracking e.g. team/origin/team/release the push went to a newly created team/origin/release instead of the branch the user confirmed.

- Use the existing mutations::remote_branch_components, which lists configured remotes and matches the longest one, matching how resolve_push_target already splits a remote reference.
- Route both failures through one invalid_push_destination helper so a confirmed-but-unresolvable destination reports a stable, actionable error.
- Add regressions on both the reviewed push path and the workspace commit-and-push path: remote name and upstream branch name both contain slashes, and assert the commit lands on the confirmed branch while no mis-resolved branch is created.

* fix(macos): forward optional push target in Git write bridge

* fix(git): 异名上游推送由 Core 统一提问并绑定到用户看到的目标 (#1272)

在 PR #1331 的基础上修复评审发现的问题:

- 预览与推送共用 resolve_push_target:git.pushPreview 与 push 都接受
  pushTarget,已审阅的推送、--force-with-lease 的 OID 和最终 refspec 都来自
  同一个有效目标,确认 upstream 后不会再更新预览未展示的分支
- git.workspaceCommitPrepare 对每个待推送仓库提出 pushTargetQuestions(空时不
  序列化),回答按仓库 ID 保存在 plan.pushTargets,重试时由 Core 恢复并重新
  校验;某仓库的异名目标没有有效回答时,在写入该仓库提交之前拒绝,避免留下
  推不出去的提交
- Windows:“提交并推送”不再在客户端先取预览(预览没有结果时会静默什么都不做),
  改为交给工作流,由 Core 返回问题,面板用一个对话框一次回答所有仓库;推送
  弹窗按所选目标重新取预览并在目的地变化时撤销选择
- macOS 仅透传可选 pushTarget;界面选择留给后续变更,异名分支会在对应仓库
  提交之前得到 Core 的可操作错误
- 同步更新 Rust Core API 契约、Agent 笔记和平台功能矩阵,并补充
  git_push、workspace commit、Windows 工作流与面板的回归测试

* feat(macos): 推送前先弹出 IDEA 式推送窗口,显示目的分支和提交,确认后才推送 (#1272)

- 分支“推送”改为打开推送弹窗:向 Core 取 git.pushPreview,顶部显示“本地分支 → 远端/分支”,左侧列出将推送的提交,右侧显示所选提交的改动文件;点击“推送”后才写远端,并把这份预览的 expectedPush 与选择一并发回,仓库或远端变化时由 Core 按过期拒绝
- 分支跟踪名称不同的远端分支(如从 origin/main 新建后设置 upstream)时,“推送”保持禁用,直到在“发布到同名分支”和“推送到 upstream”之间选择;选择绑定到当时看到的目的地,目的地变化后作废
- 没有新提交的“发布分支”仍可推送;没有内容可推时不可推送
- “提交并推送”始终先出审阅单,列出每个仓库的目的地;异名仓库就地选择,未选择时“继续”不可用;pushTargets 随每次重建审阅单发回 Core,pushTargetQuestions 与 pushTargets 在原生层往返保留
- 新增中英文文案,补充 Agent Note 与平台功能矩阵中的 macOS 说明
- 新增推送弹窗状态、服务层、真实 Core 桥接的测试

---------

Co-authored-by: milestone <345198561@qq.com>
Co-authored-by: lick <2188718831@qq.com>
Co-authored-by: Xiaoyumuxi <23722032@bjtu.edu.cn>
* docs: sync Windows Agent feature matrix gaps

* feat(windows): complete Agent parity capabilities

* fix(windows): address Agent parity review feedback

* fix(windows): guard Agent revert and linked provider refresh

* fix(ci): budget plugin cold compilation separately
* fix(macos): 项目树同级排序对齐 IDEA 自然排序,版本号按数值从低到高

项目树有三处各自排序(Rust Core visible_children、macOS 兜底扫描、
FileNodePathLookup 插入位置),都只做小写字典序比较,导致
v0.1.12.md 排在 v0.1.4.md 之前。

- Rust Core 新增 file_name_order.rs,移植 IDEA FileNameComparator
  (NaturalComparator ignoreCase + likeFileNames),visible_children
  改用 sort_by_cached_key,目录优先规则不变
- Swift 新增 NaturalNameOrder(LitheCoreContracts),兜底扫描与树内
  新增文件的插入位置改用它;GitGraphHeadOrdering.naturalCompare 委托
  给它,分支名排序行为不变
- 新增共享 fixture file-name-order-v1.json,Rust 与 Swift 测试共用
- 补充 Rust/Swift 测试、Agent Note、功能矩阵与 NOTICE

* fix(core): 项目树自然排序只作用于目录列表,快照和搜索索引保持原有遍历顺序

visible_children 增加 ChildOrder 参数。workspace.listDirectories 使用 Tree(IDEA 自然排序),
快照 files / root 树和搜索索引使用 Traversal(目录在前、按小写名字排序,与改动前一致)。

Windows 快速打开只取快照 files 里过滤后的前 100 项,显示顺序的改动不应悄悄改变它。
新增回归测试固定快照 files 在含与不含 includeTree 时的顺序,并在 Agent 笔记、
Core API 契约和功能矩阵里写明两种顺序的边界。
* feat(macos): HTML 预览新增页内查找、打印与导出 PDF、右键菜单调整和摄像头麦克风确认

接 #1412 的内嵌浏览器,补上对标 VS Code Simple Browser 的交互功能。

- 页内查找:⌘F 打开查找条,⌘G / ⇧⌘G、Return / ⇧Return 和箭头按钮前进后退并回绕,
  基于 WKWebView.find;输入变化时先折叠选区,多输入一个字母不会跳过当前匹配;
  快捷键只在页面有焦点时响应,不抢编辑器的按键。
- 右键菜单:保留 WebKit 的拷贝链接和检查元素,删掉“在新窗口打开”,
  页面空白处的菜单加入 Print… 与 Export as PDF…。
- 打印与导出 PDF:⌘P 以窗口 sheet 打开系统打印面板;导出为整页的单页 PDF,
  文件名取页面标题。
- 摄像头和麦克风:页面调用 getUserMedia 时弹出写明页面名称的确认框,
  默认按钮是 Don’t Allow,每次都重新询问、什么也不记;地址栏右侧新增“设备使用中”
  指示器,可暂停或停止,状态来自 cameraCaptureState / microphoneCaptureState 的 KVO;
  屏幕共享不提供。缺少 Info.plist 用途说明时请求直接拒绝。
- WebAssembly:新增真实 WKWebView 测试,证明 fetch 与 instantiateStreaming
  能在 lithe-html://preview 下加载 .wasm。
- 本地化 20 个新键(en / zh-Hans),功能矩阵与 Agent Note 同步更新。

未改 Info.plist 和 entitlements:摄像头 / 麦克风功能在当前构建里休眠,
等维护者确认后再补用途说明。

* feat(macos): 摄像头和麦克风统一为默认拒绝、逐次确认,覆盖插件页和 Lithe 自己的页面

- 新增 WebMediaCapture.decide 作为唯一的授权点:只有使用者明确点 Allow 才授权,缺用途说明、没有窗口、没有点名设备一律拒绝,Lithe 不记任何旧答案
- 插件页每次请求弹窗,问题写明插件名和插件 ID;只响应插件自己的主框架,页面不在窗口里直接拒绝,回答时再检查一次;隐藏窗口时,以及设备在页面离开窗口之后才启动时,都立即停止采集
- Markdown 预览、Monaco 编辑器和 diff、发行说明把 WebMediaCaptureDenier 设为 uiDelegate,一律拒绝;源码扫描测试保证每个 WKWebView 都有人回答请求,且 .grant 只出现在 WebMediaCapture.swift
- 补测试:门的决策、问题文字、拒绝委托、源码扫描,以及 HTML 预览和插件页在 WebKit 模拟设备下的端到端用例
- 同步 Agent Note、功能矩阵和本地化(新增 4 个键);Info.plist 和 entitlements 没有改,摄像头和麦克风在当前构建里仍然休眠

* docs(macos): 记录摄像头 / 麦克风保持休眠的决定和子进程授权继承评估

HTML 预览 Note 把“子进程可能继承 Lithe 的摄像头授权(没有实测)”改成 macOS 27.2 上的实测结论:责任进程沿子孙链继承;脱钩责任进程(disclaim)会切断全部系统授权,对 IDE 子进程是回归;只禁设备要用沙盒 deny,但它能否真的拦住采集还没有在真实设备上验证。同时记录 2026-10-22 的决定:继续保持休眠,不改 Info.plist,用途说明必须和子进程隔离在同一个 PR 里上线。

新增提议 Note“子进程摄像头 / 麦克风隔离”:启动入口盘点、沙盒策略、真机验证步骤、备选方案、验收标准和风险。仅文档改动,没有代码改动。

* fix(macos): HTML 预览页面有焦点时,应用键位放行页面的查找、缩放和打印快捷键

应用级键盘监听器(MacShortcutDetector)先于 AppKit 把按键交给任何视图,
默认键位又把 ⌘F / ⌘G / ⇧⌘G 绑给编辑器的查找命令。监听器匹配到就吞掉事件,
预览页面的 performKeyEquivalent 永远轮不到:在预览里按 ⌘F 会去驱动编辑器的查找,
页面自己的查找条打不开(PR 评审 P1)。之前的测试直接调用 performKeyEquivalent,
绕过了监听器,所以没有发现。

- 新增 HTMLPreviewPageShortcut,把缩放、查找、打印三张纯规则表合并成一个识别器;
  页面的 performKeyEquivalent 和监听器的放行规则读同一个识别器,两边不会漂移
- 新增 MacShortcutInputPolicy.shouldDeferToPreviewPage:页面(或其内部视图)是第一响应者、
  并且按键是页面认领的那几个时,监听器放行事件;页面不认领的按键(如 ⇧⌘F、⌘S)
  和页面外的按键照旧走应用键位,用户自定义键位同样成立。先判断按键再向上找视图,
  普通输入不用为每次按键遍历视图层级
- 新增 HTMLPreviewPageShortcutTests:4 项纯策略测试,加 1 项经 NSApplication.sendEvent
  驱动真实监听器的回归测试(页面有焦点时键位拿不走页面的按键,焦点移到页面外后
  同样的按键归键位);临时禁用监听器的放行后该回归测试失败
- Agent Note 记录按键处理顺序(监听器、key window 的视图层级、主菜单)、
  在真实 key window 里的实测结论和测试设计;功能矩阵补上新增的实现和测试文件
* docs(vcs): 提出统一 VCS 模型与 Provider 接入方案(#827)

- 新增提议 Note:Rust Core 定义与具体 VCS 无关的统一模型和 vcs.* 命令,
  Git 作为内置 Provider 只加转换层,SVN 等以插件 Provider 进程接入,
  界面按能力而不是 VCS 名字出现入口;分 P0–P5 落地。
- 新增 VCS Provider 契约草案(未实现):模型、能力、根识别、插件清单、
  litheVcs 协商、lithe/vcs/* 方法与错误码。
- 新增 fixtures:Git/SVN 能力描述、根识别、状态快照与插件回复校验用例。
- 公共扩展契约提案补充 VCS 领域扩展点的链接。

* docs(vcs): 在功能矩阵登记统一 VCS 与 SVN 能力(#827,双端未实现)
## 背景

- 已运行的 TUI(如 oh-my-pi)只在启动时查询一次 OSC 11;SwiftTerm 不支持 kitty 的背景变更推送(DEC mode 2031 / DSR 997),Lithe 切换明暗或开关壁纸后这些程序保持旧配色,直到手动重查或重启。
- 终端视图加入窗口前 effectiveAppearance 跟随系统外观,先于挂载启动的进程查询 OSC 11 会拿到系统外观的背景而非应用主题。

## 改动

- 背景实际变化时向终端应用推送 OSC 11 报告 + kitty 变更通知 DSR 997,跟踪背景的程序自动重查,其余程序忽略该序列
- 视图未挂载时按应用主题偏好解析明暗,消除初始应答取系统外观的窗口
- 报告格式与 SwiftTerm getTerminalColor 的 UInt16(component * 65535) 转换一致,新增单测锁定字节序列与壁纸透明黑回报

## 验证

- MacTerminalBackgroundReportingTests 3 用例通过;Terminal input focus / Terminal canvas compositing 套件 15 用例通过
- 平台能力矩阵门禁通过

Co-authored-by: Xiaoyumuxi <23722032@bjtu.edu.cn>
* fix(windows): Diff 块内拆分新增行并按 IDEA 标绿

Git 会把 order 整体重排的 JSONL 等文件报告成一个大修改块,并排预览
直接按 Git 块着色时,纯新增行会和修改行同为蓝色,与 PyCharm 不一致。

显示层现在参考 Community fb72b4df43ab 的
ComparisonManagerImpl.createInnerWordFragments -> ByWord.compareAndSplit
-> LineFragmentSplitter 语义,在 Git 修改块内部按词元相似度做有界行配对:
单侧存在的行恢复新增绿/删除灰,相似配对保持修改蓝,完全相同的配对行
按上下文不绘制,无共享词元的相邻子块仍合并为一个修改块。进度受配对格数、
词元工作量和块大小预算约束,超限回退为整个 Git 块。

拆分仅服务行底色、词级范围、连接带和概览标记;Git 脚本、差异计数、
块包含、回退与导航不变,单个 Git 块的控件仍只绘制一次并锚定首个子块。

新增回归覆盖整文件 order 重排拆分、无共享词元合并、超预算回退、
显示子块装饰以及块控件不重复;用真实 17_menus.jsonl 的 115/113 行
单块验证新文件第 2、3 行被拆为新增子块。同步更新决策笔记与功能矩阵。

* fix(windows): Diff 文件导航跟随面板与提交文件树顺序

左侧提交面板按仓库->changelist->文件夹树或状态分组渲染,Git Log 的
提交文件树按目录优先和 IDEA 自然排序渲染;但 Diff 的文件箭头直接使用
GitStatus.files 的路径序(Core 按 path 字节排序,未跟踪文件混排在已
跟踪文件之间),因此箭头会跳到列表末尾的未跟踪文件,而不是下一行。

- 新增 orderGitStatusFilesForDisplay:与面板共用仓库、changelist 和
  added->modified->deleted->renamed->untracked 分组顺序(文件夹视图
  使用目录优先自然排序),跳过未跟踪目录汇总行;git-view 用它生成
  workingTreeFileOrder,批量 Diff 的条目也按同一顺序加载。
- 新增 gitFileTreeOrder / orderGitDiffsForTree:Git Log 单文件预览、
  完整提交 Diff、范围 Diff 与离散多选 Diff 按提交文件树顺序排列;
  fileKeys/fileLabels/fileRevisions 跟随同一置换,重复路径稳定相邻。
- getFirstCommitFilePath 复用同一树序遍历。

回归覆盖混合状态与未跟踪汇总结算顺序、文件夹树顺序、changelist 分组、
重复路径的稳定顺序、面板顺序覆盖状态路径序,以及选择预览的并行数组
置换。类型检查、Jest 范围测试、前端构建、Windows 边界、功能矩阵与
Agent Notes 校验通过;真实 WebView2 视觉验收未在本机执行。

* fix(windows): Git Log 预览切换文件后刷新标签标题

Git Log 单文件预览固定复用 diff://commit-file-preview 标签,文件箭头只
更新缓冲区内容与选中比较;标签栏的 chrome 相等判断只覆盖了 Commit 面板
的 commitPreview 文件名,Git Log 的 commitFilePreview 两边都返回 null,
所以正文已切到新文件而标签标题仍停留在旧文件名。

新增 getDiffTabFileName:同时覆盖 Commit 面板预览与 Git Log 提交文件
预览,按当前选中比较返回标题文件名;标签栏改用它作为复用 Diff 标签的
比较键。补充标签栏回归,验证同一预览切换选中文件时重新渲染,同一文件
保持稳定。
* style(macos): unify text action buttons with Welcome geometry

* fix(macos): address action button layout review findings

* fix(macos): reserve commit pane height for stacked actions

* fix(macos): restore action cursors and adapt plugin buttons to narrow panes

* test(macos): avoid repeated regex bridging in menu coverage scan
* fix(windows): 关闭窗口或退出时停止已启动的运行服务 (#1137)

窗口销毁时结束该窗口拥有的 Run 进程树,应用退出时结束全部剩余 Run 进程
并等待未完成的窗口清理;复用手动 Stop 的 taskkill /T 终止路径,重复触发
幂等,不影响其他窗口。

关闭窗口前如仍有运行中的服务,弹窗列出服务名称,可选择停止并关闭或取消。

* test(windows): 用子进程输出同步替代睡眠轮询 (#1137)

* fix: 关闭项目、退出和更新前确认并结束运行服务,Windows 用 Job Object 管理进程树 (#1137)

- Rust Core processLifecycle.resolve 新增 closeWorkspace 场景、confirmStop 动作和
  runServicesOnExit(ask/terminate)设置,两端共用同一条确认规则
- lithe-git-host 新增 ProcessTree:Windows 挂起创建后放入 Job Object,Unix 用进程组
- Windows 运行会话、调试适配器和语言服务器改用 ProcessTree,停止与崩溃按整组结束,
  不再依赖 taskkill 的 PID 链
- Windows 菜单退出改走各窗口关闭守卫;更新安装前确认并停止运行服务,再结束其余受管进程
- Windows 关闭窗口时从原生会话表列出本窗口的运行服务(含 Maven 目标和已关闭项目留下的会话)
- macOS 关闭项目或窗口、退出时用 NSAlert 询问运行服务;设置页新增“运行服务”选项
- 更新 Agent Note、Rust Core 契约、fixture 和跨平台功能矩阵

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(windows): 停止运行服务后上报退出,并把新增前端测试接入 CI (#1137)

- run_stop_owned_processes 为每个确认已结束的会话向所属窗口发送 run-exit;
  更新安装失败、窗口仍在时,运行面板不会停留在“运行中”
- ci-windows 新增运行服务确认与设置规范化测试步骤

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: wh <kevin1811@qq.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(macos): 恢复隐藏标题栏窗口的原生全屏能力

问题:当前 macOS 工具链下,SwiftUI 为 .hiddenTitleBar 窗口默认标记
collectionBehavior.fullScreenNone,绿色交通灯按钮因此退化为普通最大化
(action 被固化为 _setNeedsZoom:),toggleFullScreen(_:) 也被静默拒绝,
主窗口无法进入独立全屏 Space。源码构建版本与 v0.6.3 发布版本均复现。

修复:RootView 挂载 WindowFullScreenCapabilityGuard,通过
NSWindow.didUpdateNotification 持续剥离 SwiftUI 反复重设的
fullScreenNone 并补上 fullScreenPrimary;同时把绿色按钮重接到
zoomButtonClicked(_:)(先剥离再 toggleFullScreen),消除标志位竞争。
欢迎页、项目工作台与独立文件窗口共用 RootView,一并覆盖。

- 新增 WindowFullScreenCapabilityGuardTests 覆盖剥离、按钮重接与
  SwiftUI 重设后的再次剥离(同步触发,无轮询)
- 更新 window-controls 平台能力矩阵:明确绿色按钮应进入原生全屏 Space
- 新增 Agent Note 记录根因、备选方案与验证方式

* fix(macos): 全屏态下移除工作台顶栏的窗口按钮预留空位

进入原生全屏后 macOS 会隐藏红绿灯按钮,但顶栏仍按普通窗口预留
WorkbenchTopBarMetrics.leadingInset(83pt),左上角出现一段空白。

新增 WindowFullScreenStateReader:复用 NSWindow.didUpdateNotification
机制把窗口全屏状态同步到 SwiftUI @State(无轮询),顶栏在全屏态将
leading padding 降为 0,退出全屏自动恢复预留,行为对齐 IDEA。

新增 WindowFullScreenStateReaderTests 覆盖进入/退出全屏的状态同步
(同步触发,无实时等待);同步更新 window-controls 能力矩阵验证动作
与全屏 Agent Note。

* fix(macos): 全屏期间的布局切换延迟换框,并修复全屏测试的 CI 崩溃

问题一:欢迎页全屏后打开项目,工作台只显示为居中的 1440×900,四周黑屏。
原因:布局切换的换框 setFrame 落在原生全屏窗口上。现在全屏期间跳过换框
(内容继续填满屏幕),退出全屏时补一次换框落到当前布局的正常尺寸;布局
未变的正常退出保持"恢复进入全屏前尺寸"的行为不变。已实测确认修复。

问题二:全屏相关测试直接写 styleMask 的 .fullScreen 位,AppKit 在真实
全屏过渡之外抛 NSGenericException,CI 的 macOS 测试进程整体崩溃。为
WindowFullScreenStateReader 与 LitheWindowCoordinator 增加可注入的全屏
判定接缝(默认行为不变),测试改用注入桩值驱动状态,不再触碰受保护
标志位。

新增 WindowLayoutFullScreenTransitionTests 覆盖全屏期间换框延迟与未变
布局退出不换框;既有 reader 测试改为注入式驱动。

* test(macos): 全屏过渡测试的期望宽度按屏幕可视区域钳制

CI 的虚拟显示器只有 1024pt 宽,applyFrame 的屏幕钳制会把
1440pt 的目标宽度缩到 1000pt,导致
layoutTransitionWhileFullScreenDefersFrameSwapUntilExit 断言
window.frame.width == workspaceContentSize.width 失败。改为用
LitheWindowLayout.frame(_:fitting:) 按 applyFrame 相同的规则
计算期望宽度,无可见屏幕时不钳制,保证测试在不同显示尺寸下
结果一致。

---------

Co-authored-by: Xiaoyumuxi <23722032@bjtu.edu.cn>
## 背景

- Windows 端已随 `TERM_PROGRAM` 一并导出 `TERM_PROGRAM_VERSION`(`windows/tauri/crates/terminal/src/connection.rs:268`),macOS 端缺失,同一产品两平台环境不一致。
- 工具按版本门控终端能力是既有惯例(如 oh-my-pi 以该变量区分 tmux 版本行为);Lithe 引入新的外部可观察能力(如背景变更推送)后,也需要一个版本位供 TUI 安全启用。

## 改动

- `TerminalTransport` 协议新增 `termProgramVersion: String?`(无法取得时为 nil),extension 默认 nil
- `TerminalSession` 以可选值直赋导出 `TERM_PROGRAM_VERSION`,版本未知时同时清除从外层终端继承的同名值
- macOS 取应用打包版本(`CFBundleShortVersionString`),与 Windows 报告的打包版本一致
- `TerminalModuleTests` 新增 3 个用例(导出、无法取得不写入、清除继承值);更新 `terminal-shell.json` 能力矩阵

## 验证

- `TerminalModuleTests` 全绿(含 3 个新增)
- 平台能力矩阵门禁通过
* feat(plugins): support configured build executable paths

* fix(macos): keep plugin path chooser visible in narrow settings

* fix(macos): keep plugin details inside resized split panes

* refactor(plugins): unify executable candidates and injected resolution

* fix(macos): preserve executable selections across runtime failures

Block Provider discovery after prerequisite runtime failure when tool or runtime settings are explicit. Probe each runtime with the same candidate environment used for execution. Add real Core/resolver/service regressions and native layout comparisons.

---------

Co-authored-by: Xiaoyumuxi <23722032@bjtu.edu.cn>
…1442)

* refactor(plugins): 契约发布到 lithe-plugin-docs,fixture 按能力改名,SDK 移出主仓库

- 契约 fixture 按演示的能力改名(文件名和 dev.lithe.fixture.* ID),同步更新
  标准答案、Rust Core 测试、macOS 测试与展示副本、功能矩阵和 Agent Notes。
- 两份 schema 的 $id 改为 lithe-plugin-docs 的 raw 地址;verify-shared-contracts.sh
  要求 $id 完全相等,并拒绝离开契约目录的 README 相对链接。
- 契约 README 的目录外链接改为绝对地址,说明 lithe-plugin-docs 保存完整副本,
  官方 SDK 一节指向 lithe-plugin-docs。
- 删除 sdk/、SDK 端到端测试和 Java SDK 发版工作流;Rust Core 的 CI 脚本、
  ci-macos.yml、CI 分类和 .gitignore 去掉 SDK 相关内容。
- AGENTS.md 新增两仓库同步规则,新增 Agent Note 记录决策,并更新 SDK 相关
  Note、develop-lithe 布局表、Plugins README 和 docs/ci-builds.md。

* docs(plugins): SDK 与契约的每周检查跟踪 preview 而不是默认分支 main
* feat(agent): add native global and project skill management

* fix(macos): make skill toggles respond immediately

* feat(agent): 新增原生全局指令并稳定技能开关反馈

在 AI 设置中保留独立的指令与技能入口,直接编辑 Codex/Claude 用户指令文件,提供草稿、冲突校验和原子保存。为技能成功提示保留布局空间,覆盖连续启停、深浅主题和窄宽页面的原生几何回归。

* fix(agent): 技能保存仅锁定当前行,避免其他开关变灰

将待确认选择按点击顺序串行保存,其他技能保留原生启用外观和交互能力。覆盖同一 Agent 连续写入、单行失败回滚、队列继续、重复点击去重、项目切换及离页清理;同步 Agent Note 与平台矩阵。

* feat(agent): add shared instruction cards and native synchronization

* feat(mcp): add bundled publisher icons and common featured servers

* feat(mcp): 增加工具检测与原生工具开关

* fix(agent): preserve cancellation and native MCP tool filters

* fix(skills): publish Windows skill packages without replacement

* fix(ci): bound multi-repository tests and join search fixture teardown

* test(windows): await owned process exit signals and clean fixtures

* fix(agent): close cancellation and MCP policy lifecycle gaps

* test(ci): bound Windows frontend path roundtrip startup

* fix(ci): match raw path test names for scoped deadlines

* test(ci): scope checkout and clone integration timing allowance

* fix(ci): allow Agent Host cold compilation within Rust suite budget
* fix(macos): 刷新已打开终端的主题色

* feat(macos): 终端环境导出 COLORFGBG

- `COLORFGBG` 是 Terminal.app、iTerm2、tmux 等终端的行业惯例环境变量;omp 等 TUI 在进程启动时同步读取其 bg 字段(<8 深、>=8 浅)选择配色,先于任何 OSC 往返,可消除首帧按回退深色渲染的闪变。
- Lithe 终端此前未导出该变量;且终端视图加入窗口前 effectiveAppearance 跟随系统外观,直接读它会与 Lithe 主题不一致。

- `TerminalTransport` 协议新增 `reportsLightBackground: Bool?`(宿主是否渲染浅色背景,无法判定时为 nil),extension 默认 nil
- `TerminalSession` 以可选值直赋导出 `COLORFGBG`(浅色 `0;15`、深色 `15;0`;fg;bg 惯例,判读位是 bg 字段),宿主无法判定时同时清除从外层终端继承的同名值
- macOS 实现按应用主题偏好解析:视图未挂载窗口时用主题 pin 的明暗,挂载后用窗口外观
- `TerminalModuleTests` 新增 4 个用例(浅色、深色、无法判定不写入、清除继承值);更新 `terminal-shell.json` 能力矩阵

- `TerminalModuleTests` 全绿(含 4 个新增)
- 平台能力矩阵门禁通过
- 真机浅色/深色首帧配色正确,无闪变;`echo $COLORFGBG` 输出 `0;15` / `15;0`

* fix(macos): 背景通知仅推送给订阅 kitty DEC mode 2031 的程序

- 背景变化通知由无条件推送改为按订阅发送: 解析进程输出中的 CSI ? 2031 h/l (含组合 DEC mode 与跨块分片), 未订阅的 shell 不再收到响应字节
- DSR 997 按背景亮度如实报告: 997;1n 暗色、997;2n 亮色
- 新进程启动与终端 RIS 重置清除订阅状态
- 单测 15 用例: 通知编码门控与明暗状态 + 订阅解析全路径
* feat(vcs): Core 实现插件 VCS Provider 底层(#827 P1)

- 插件清单 API 3 新增 vcsProviders 能力、process.vcs 权限和 onVcsRoot 激活事件,git 为保留 ID;安装审查以 vcsTool 列出 VCS 命令行
- 新增 vcs.detectRoots(静态标记识别根、歧义目录与用户映射、祖先工作副本)、vcs.ownerOf(最深根归属)、vcs.decodeReply(Provider 回复校验与归一化)
- LSP 会话:只向插件会话提供 litheVcs 协商,成功后发出 vcsProvider 事件;lsp.vcsRequest 按操作生成 lithe/vcs/* 请求并检查已协商能力;Provider 错误码只保留契约白名单
- lithe/vcs/execution 转为会话日志事件,lithe/vcs/authenticate 暂按未知请求回绝
- 契约、插件 README/schema、rust-core-api、fixtures、功能矩阵与提议 Note 同步
- 修复 unregistering_a_running_function_revokes_the_call 的竞态:改为有界等待 $/cancelRequest 写出

* feat(sdk): Node SDK 支持 litheVcs 并用示例 Provider 端到端验证(#827 P1)

- backend.vcs(id, handlers, traits) 按声明的处理函数协商 VCS 能力,必需 status/baseContent/checkin/rollback,git 保留,litheVcs 不能手写进 capabilities
- 只在宿主提供 litheVcs 1 时分发 lithe/vcs/* 请求;回复必须是对象,无返回值视为 {}
- VCS 处理函数的 context.run 自动发出 lithe/vcs/execution(命令行、退出码、耗时、截断到 16 KiB 的 stderr),可用 report: false 关闭
- 导出 VCS_ERRORS 与 isVcsId,补充类型声明、README 和单元测试
- 新增 sdk/node/examples/sample-vcs 玩具 VCS,Rust 端到端测试经真实 Core 会话跑通协商、全部 11 种操作、错误码和执行报告
- 契约写明 lithe/vcs/execution 的参数;Note 与功能矩阵更新 P1 完成状态

* fix(vcs): 按评审修正祖先根判断与示例移动回滚(#827 P1)

- 只有全部由 .. 段组成的根 ID 才是工作区外的祖先根;工作区内名为 ..repo 的目录按普通路径计算深度和包含关系,补充单元测试
- 示例 Provider 回滚移动目标时把文件移回原路径、恢复基线内容并清除移动记录;端到端测试覆盖移动后回滚
- 插件能力版本笔记补充 vcsProviders、其对 serverProcess 的依赖、两端宿主尚未声明的状态,以及 litheVcs 协商
* feat(vcs): Core 实现插件 VCS Provider 底层(#827 P1)

- 插件清单 API 3 新增 vcsProviders 能力、process.vcs 权限和 onVcsRoot 激活事件,git 为保留 ID;安装审查以 vcsTool 列出 VCS 命令行
- 新增 vcs.detectRoots(静态标记识别根、歧义目录与用户映射、祖先工作副本)、vcs.ownerOf(最深根归属)、vcs.decodeReply(Provider 回复校验与归一化)
- LSP 会话:只向插件会话提供 litheVcs 协商,成功后发出 vcsProvider 事件;lsp.vcsRequest 按操作生成 lithe/vcs/* 请求并检查已协商能力;Provider 错误码只保留契约白名单
- lithe/vcs/execution 转为会话日志事件,lithe/vcs/authenticate 暂按未知请求回绝
- 契约、插件 README/schema、rust-core-api、fixtures、功能矩阵与提议 Note 同步
- 修复 unregistering_a_running_function_revokes_the_call 的竞态:改为有界等待 $/cancelRequest 写出

* feat(sdk): Node SDK 支持 litheVcs 并用示例 Provider 端到端验证(#827 P1)

- backend.vcs(id, handlers, traits) 按声明的处理函数协商 VCS 能力,必需 status/baseContent/checkin/rollback,git 保留,litheVcs 不能手写进 capabilities
- 只在宿主提供 litheVcs 1 时分发 lithe/vcs/* 请求;回复必须是对象,无返回值视为 {}
- VCS 处理函数的 context.run 自动发出 lithe/vcs/execution(命令行、退出码、耗时、截断到 16 KiB 的 stderr),可用 report: false 关闭
- 导出 VCS_ERRORS 与 isVcsId,补充类型声明、README 和单元测试
- 新增 sdk/node/examples/sample-vcs 玩具 VCS,Rust 端到端测试经真实 Core 会话跑通协商、全部 11 种操作、错误码和执行报告
- 契约写明 lithe/vcs/execution 的参数;Note 与功能矩阵更新 P1 完成状态

* fix(vcs): 按评审修正祖先根判断与示例移动回滚(#827 P1)

- 只有全部由 .. 段组成的根 ID 才是工作区外的祖先根;工作区内名为 ..repo 的目录按普通路径计算深度和包含关系,补充单元测试
- 示例 Provider 回滚移动目标时把文件移回原路径、恢复基线内容并清除移动记录;端到端测试覆盖移动后回滚
- 插件能力版本笔记补充 vcsProviders、其对 serverProcess 的依赖、两端宿主尚未声明的状态,以及 litheVcs 协商

* feat(vcs): macOS 宿主接入插件 VCS Provider(#827 P3)

SVN 插件改为独立仓库 Lithe-IDEA/lithe-plugin-svn 的社区插件
(io.github.lithe-idea.svn-support),主仓库只保留与具体 VCS 无关的部分;
原 #1432 里宿主识别 vcsProviders 的通用改动并入本提交。

- 宿主识别:声明式清单解码 vcsProviders,声明了 VCS Provider 的插件生成一个
  <pluginID>.vcs-providers 扩展模块,只承载启用状态,默认关闭;
  PluginManifest.hostCapabilities 声明 vcsProviders: [1]。
- 安装审核:显示 Provider 的启动命令、客户端命令和是否连接仓库服务器。
- Provider 会话、Core 调用(vcs.detectRoots / ownerOf / decodeReply、
  lsp.vcsRequest)、VcsProvidersFeatureModel、左侧 VCS 工具窗口、历史与差异、
  项目树状态着色和移动跟踪。
- 测试改用契约里的 svn-provider 清单 fixture 和 SDK 的 sample-vcs 样例,
  不再依赖 SVN 插件源码。
- 契约的 Subversion provider notes 改为指向插件仓库;Note、功能矩阵和
  Plugins/mac/README.md 同步说明社区插件。

* fix(vcs): 按自审修正 VCS Provider 宿主(#827 P3)

- 包住工作区的工作副本(如 ../.svn)单独监听其声明的元数据目录,
  终端里的提交或更新也会触发刷新。
- 移动前按 Core 的归属规则确认两端都属于同一根,嵌套的 Git 仓库或
  未选择 VCS 的歧义目录不会被当成 svn move。
- 窗口关闭时调用 shutdown():停掉所有 Provider,之后迟到的工作区
  扫描也不会再把 Provider 拉起来。
- 工具窗口与命令沿用宿主版本控制图标;首次读取时显示“正在读取更改…”;
  变更行补充选择、打开/查看差异、纳入提交的辅助功能操作。
- 同步 Agent Note、能力版本 Note 与跨平台功能矩阵。

* fix(vcs): 隐藏 .svn 并按根监听元数据,补齐工具缺失与比较判断(#827 P3)

- 项目树、搜索、索引与工作区监听像 .git 一样隐藏 .svn(Swift 与 Rust Core 的内置隐藏列表同步),避免 .svn/pristine 进入索引
- 每个插件根单独监听自己的元数据目录(含包住工作区的 ../.svn);工作区里新出现的条目在后台检查标记,新检出的工作副本会重新识别
- 找不到 VCS 客户端时按契约报 vcs.tool.unavailable,工具窗口先显示安装提示
- 是否有基线统一由 VcsRootState.comparesWithBase 判断,工具窗口双击、辅助功能动作和项目树右键共用
- 等待 Core 判断移动归属期间开始了别的操作时,直接退回磁盘移动
- 同步 Agent Note、功能矩阵与 VcsProviderHostTests
swift-tests 的冷编译在运行 39943871840 中超过 20 分钟上限,与插件通道 39741361768 同类;编译步骤放宽到 40 分钟(job 80 分钟),测试执行预算不变。构建失败时不再叠加合并报告失败,避免同一失败被重复计数。
* feat(windows): dock terminal panel at bottom or right (#1436)

* fix(windows): drag terminal activity entry to either side

* fix(terminal): leave project search shortcut to workbench

* fix(terminal): focus docked sessions after the pane becomes visible
* fix(windows): Ctrl+Z 优先恢复键盘移动后的光标 (#1438)

* ci(windows): run cursor undo regression in frontend lane

* fix(editor): coordinate explicit cursor undo with generic redo
GitHub GraphQL repository.issueTemplates 只返回 Markdown 模板,gh 无法选择
YAML Issue Forms(cli/cli#5865)。Issue 门禁本就接受包含全部必填字段的正文,
因此 submit-lithe-issue 改为:原生模板不可用时用 gh issue create --body-file
提交逐字段生成的表单正文,仍禁止空白正文、API 直建和手工添加 issue-form 标签。
…ey 两种模式 (#1453)

* feat(macos): 优化编辑区 Agent 对话的大历史加载与 Claude Desktop 式布局

- 大历史回放性能:loadSession 回放期间消息写入不对外发布的缓冲区,
  sessionLoaded 时一次性提交,消除 @published 字典逐事件整体复制带来的
  平方级开销;1,200 轮(约 1 万事件)接收从 27s 降到 0.45s。
- 对话窗口化:首屏只构建最近 48 项,点「显示更早的 N 项」或导航栏跳到
  旧回合再展开,首次排版从 31s 降到 0.3s,总加载 <1s。
- 历史列表:按收藏/今天/昨天/过去 7 天/过去 30 天/更早/时间未知分组,
  行改为 Agent 磁贴 + 标题 + 消息数 + 会话 ID + 相对时间 + 「…」菜单;
  排序筛选改为一次快照。选择、多选、归档、已移除、导出等能力保留。
- 编辑区会话 UI 向 Claude Desktop 靠拢:用户消息中性灰气泡、16pt 圆角
  卡片输入框(仅添加/发送)、审批模式与模型下移到卡片下方状态行;
  详情栏改为上下文/更改/会话统计三个可折叠分区,并新增「更改」。
- 标题栏新增详情栏开关按钮,原菜单项保留。工具窗口侧栏样式不变。
- 新增 AgentLargeHistoryLoadTests;同步 Agent Note、功能矩阵、zh-Hans 本地化。

* perf(macos): 历史列表滚动不再掉帧;居中对话改为 Claude Desktop 式卡片详情栏

- 历史列表:排序结果、行数据、列表版本号三层记忆;流式输出期间刷新从
  p50 14ms(25% 掉帧)降到 1.7ms(0 掉帧),纯滚动 p95 从 8.6ms 降到 1.4ms
- 时间戳解析、本地化 .lproj 查找、DateFormatter 加缓存;canExport 改为打开
  菜单时按行计算(原先每行 O(n),整表 O(n²));managementSessions 只排序一次;
  消息数与临时标题不再复制整个对话
- 历史行:标题 + 消息数 + 时间 + 「•••」,1 小时内显示「N 分钟前」、之后显示
  具体时间;菜单为置顶/重命名/分叉/归档/复制 Session ID/导出/删除;固定行高、
  菜单只在悬停或当前行挂载
- 居中输入卡片内放 Agent、权限模式、模型、添加、发送;权限模式名称本地化
- 右侧详情栏 AgentEditorDetailsColumn:圆角卡片 + ▾ 折叠,上下文图例与更改列表
  按参考图排版;工具窗口输入框的会话详情弹窗恢复原样式

* feat(macos): 编辑区文件审查统一到「更改」卡片,活动卡只保留任务与子 Agent

- 「更改」卡片内可全部保留/全部回滚、逐个文件看 diff/回滚(悬停显示),
  回滚前确认;活动卡在编辑区不再重复显示文件修改行
- 批量菜单与筛选图标统一为「置顶」术语
- 清理不再使用的参数与常量,历史缓存清理已关闭对话的计数

* feat(agent): Claude 支持官方订阅与 API Key 两种模式;居中输入框改为状态圆环,权限模式汉化

- Claude 订阅(claudeSubscription):直接使用本机 Claude Code 已登录的
  claude.ai 账号。Host 新增 claude_subscription.rs:不注入 API Key/路由,
  移除继承的 ANTHROPIC_* 覆盖变量,初始化后读取适配器的登录状态,未登录时
  提示在终端用 /login 登录;Lithe 不读取、复制或刷新任何凭据
- 订阅只属于各自适配器(Codex 订阅不能给 Claude,反之亦然);供应商管理
  新增「Claude 官方订阅(本机账号)」开关,预检文案区分 API Key 与两种订阅
- 居中模式输入卡片去掉「+」与「发送」,右侧改为额度与上下文圆环,回复中
  才显示停止按钮;详情栏移除重复的额度卡片
- 权限模式按上游 ID 显示中文(Codex:请求批准/替我审批/完全访问;Claude:
  手动/接受编辑/计划/自动/跳过权限确认),菜单标题「模式」;修正 Claude
  「手动」的 ID 为 default
- 同步 Agent Note、新增功能矩阵 agent-claude-subscription、Rust 与 Swift 测试

* fix(agent): 评审修复——窄窗口保留活动入口、Claude 订阅额度圆环、权限模式翻译不误伤其他 Agent

- 居中模式详情栏关闭或宽度不足时,输入框上方恢复活动摘要(任务、子 Agent、
  文件审查与回滚),避免这些入口消失
- 上下文圆环始终显示(未上报时为空圈);Claude 订阅接入额度圆环:解析适配器
  转发的 rate_limit_event(_claude/rateLimit),按 five_hour/seven_day 等窗口
  累积,快照在窗口重置前有效,悬停显示「截至某时刻,仅在回复时更新」,不调用
  任何接口
- 权限模式只在「上游 ID + 英文原名」都匹配时翻译,其他 Agent 的同名 ID 保持原名;
  改写原先断言保留英文名的测试,Agent Note 记录决策变更
- 编辑区居中布局测试改用 Agent 切换按钮测量输入框左缘(附件按钮已移除)
1lck and others added 26 commits October 24, 2026 05:21
记录数据库模块的双端评估(规则三份不一致、Windows 从未接上后端)
和插件化方案:组织仓库独立插件、网页界面、Rust 后端、官方签名,
主仓库只提供插件后端、宿主凭据、MCP 声明等通用能力。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Windows 的数据库后端从未接入(backend-capabilities 中 database 为 false,
前端调用的数据库命令没有原生实现),但 .db/.sqlite/.duckdb 文件仍被送进
数据库查看器,功能矩阵也标为 implemented。

- getDatabaseTypeFromPath 遵循同一能力开关,后端不可用时这类文件走普通
  二进制/文本路由,打开与会话恢复共用此判断
- 功能矩阵中 Windows 的四项数据库能力改为 missing / not-applicable
- README 注明数据库工作台目前仅支持 macOS

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- sidecar 的危险 SQL 判定从字符串前缀/" WHERE " 匹配改为词法分析:去掉注释、
  字符串、引号标识符和 $$ 块;按语句逐条检查;WHERE 必须直接限定该
  UPDATE/DELETE(子查询里的 WHERE 不算);识别 WITH ... DELETE 与数据修改型
  CTE;DROP/TRUNCATE(含 ALTER ... DROP)需要确认;排除 FOR UPDATE、
  ON DELETE CASCADE、GRANT、MySQL TRUNCATE() 等非写入用法;MySQL/MariaDB
  与 PostgreSQL E'' 字符串按反斜杠转义处理,SQL Server 识别 [标识符]。
- 修复根因:执行前格式化会把 WHERE 换到新行,旧判定只认 " WHERE ",导致
  生产保护连接上所有带 WHERE 的 UPDATE/DELETE 都被拒绝。
- sidecar 新增不连库的 checkWriteProtection 方法;macOS 在生产保护连接执行写入
  前先问后端,需要确认时弹出原有确认框,避免批量执行到一半被拒。
- 补充 Rust 金样例测试与 Swift 预检测试。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 新增 level 3 能力 `backend` 1:插件自有的长驻进程,复用 serverProcess
  启动字段与安装审查(packagedBackend 等),需 `backend.launch` 权限和
  web 工具窗,不绑定 workspace(拒绝 ${workspaceStateDir})
- 新增权限 `credentials.store`,无 backend 时声明即无效
- launch plan 支持 `backend: true` 选择器,返回 `backend.hostServices`;
  `workspaceStateDirectory` 改为可选,仅在进程用到时必填
- 插件函数协议 v2:`lithe/host/credentials/{get,set,delete}`,Core 校验
  版本、授权与参数(key 字母表/长度、secret ≤16 KiB、拒绝未知字段),
  通过 `hostRequest` 事件交给宿主,宿主用新命令 `lsp.hostResponse` 应答;
  每会话最多 16 个未应答请求
- `lsp.startServer.hostServices` 传入授予的服务
- 契约 README、rust-core-api、schema、fixture 与黄金用例同步更新

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 修正“Agent 到 app 里查找 lithe-db-mcp”的描述:它只被打包,从未被启动
- 记录后端每插件一个进程、宿主全局、授权由安装审查覆盖等取舍
- 凭据生命周期:停用/更新保留,卸载删除
- 按平台可执行文件不改契约;Agent 工具后续经现有 lithe MCP 暴露
- 待确认清空

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(agent): Claude 与 Codex 官方订阅支持多账号与手动切换 (#1457)

每个额外账号是官方 CLI 的独立配置目录(CLAUDE_CONFIG_DIR / CODEX_HOME),
Lithe 只保存名称和路径,不读取、复制或刷新任何凭据。

- Host:AgentLaunch 新增 claudeConfigDir / codexHome,只对各自的订阅模式生效且必须是绝对路径;
  Codex 的额度查询和已归档历史使用同一账号目录;Claude 已登录账号的邮箱和套餐通过 account 事件发给前端
- 设置页:Agent 管理里新增「订阅账号」卡片,显示邮箱、套餐、首选标记、5 小时/7 天用量条、重置时间、配速和「截至 …,本次未主动刷新」,用量更新逻辑放在 ⓘ 里
- 添加账号:在后台运行官方登录命令(claude auth login --claudeai / codex login),浏览器由 CLI 打开,不弹终端,可取消,5 分钟超时
- 切换:设为首选会重启该 Agent 的连接,回复中或等待授权时拒绝;额度耗尽不会自动换号
- 会话收藏、重命名、隐藏按「工作区 + Agent + 账号」分开保存,默认账号沿用原有标注
- 用量只是适配器最近一次推送的快照,按账号保存,Lithe 不调用 Anthropic 接口也不轮询
- 同步共享翻译、功能矩阵(agent-subscription-multi-account)和 Agent Note

* fix(agent): 技能列表与开关跟随首选 Codex 账号目录 (#1457)

* fix(agent): Claude 技能跟随首选账号目录,切换账号后刷新技能页,新账号名避免重复 (#1457)
- 新增 MacPluginBackendSessions:每个插件一个后端进程、应用全局共享,
  由插件网页首次调用 functions.* 时按需启动,以 ${stateDir} 为根目录和
  工作目录;插件停用时停止、重新启用后可再启动,包替换/卸载前停止且本次
  运行不再启动;设置变化时重启
- 后端会话以 hostServices 启动;LanguageServerRuntimeSession 处理
  hostRequest 事件并经新命令 lsp.hostResponse 应答(离开主线程发送)
- 新增 MacPluginCredentialStore:每个插件独立的 Keychain service,
  读取不弹密码框;卸载时随插件状态目录一起删除,停用/更新保留
- 网页桥接:functions.list/invoke 省略 instance 时调用本插件后端,
  不弹同意框(安装审查已覆盖);无后端的插件返回 plugin.web.forbidden
- 安装时校验后端打包可执行文件;hostCapabilities 声明 backend: [1]
- Swift 契约:launch request 的 workspaceStateDirectory 可为空、
  backendLaunchPlan、descriptor.declaresBackend、事件携带 method
- Core 修正:lsp.hostResponse 的字段按契约拼写为 hostRequestID,
  测试改为从线上 JSON 解码以覆盖字段名
- README 更新 macOS 宿主能力说明

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ead of polling

The test-stability gate rejects real-time sleeps. The scripted Core now
resumes waiters as answers arrive, with a five-second watchdog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sdk/rust in lithe-plugin-docs implements plugin-function protocols 1 and 2
with the credentials host service for packaged plugin backends, and its
sample backend runs an end-to-end scenario against Core.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The client encodes DatabaseConnection.proxyURL as `proxyURL`, but the
sidecar's serde camelCase name was `proxyUrl`, so a connection's proxy
command was silently dropped and connections went direct. The field now
reads `proxyURL` and still accepts `proxyUrl`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SQL Server and MongoDB requests opened a tunnel and never stopped its ssh
client, so each such request left an orphaned ssh process holding the
local port after the sidecar exited. MySQL, PostgreSQL, SQLite, Redis,
and Nacos stopped it only on their normal path. SshTunnel now kills and
reaps the client when dropped, which covers early returns and every
adapter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
插件后端是无界面的子进程,数据库插件导入导出、备份恢复和 DBX 导入都需要
用户选文件。桥接版本升为 2(lithe.version),新增 dialog.openFile 与
dialog.saveFile:对话框由宿主弹出并写明发起的插件,同一页面同时只开一个,
页面只拿到用户选中的绝对路径(取消为 null),读写交给插件后端;页面在对话框
打开期间关闭则拿不到结果。旧宿主返回 plugin.web.unknownMethod,页面据版本号
决定是否提供导入导出。

同步更新插件契约 README、网页内容 Agent Note 与跨平台功能矩阵。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs(plugins): 提出 Windows 声明式插件宿主提案 Note

* feat(windows): 声明式插件宿主 v0 —— 包存储、启动校验与语言服务器启动接线

- 新增 src-tauri plugin_host 模块:包存储布局(app_local_data_dir/plugins 与
  plugin-state,bundled 从资源目录只读加载)、启动扫描(经
  plugins.declarative.validate 携带 hostCapabilities,拒绝包隔离并展示原因)、
  启动计划解析(packaged 入口拒绝 reparse point 与路径逃逸,runtime/
  systemCommand 走 PATH 与 LITHE_<TOOL>_PATH 约定)
- 共享 fixtures 验收:invalid-manifests.json 全部 154 个用例在 Windows 二进制
  内断言同一稳定错误码;合法样例按契约模式与 v0 能力门控模式分别断言
- 前端:resolve-editor-lsp-launch 在 Worker 扩展无服务器时回落契约插件启动;
  bootstrap 增加 declarative plugins 扫描步骤
- Note 转正为 implemented 并记录 M1 落地形状与 M2-M4 切分;矩阵
  declarative-plugin-contract Windows 状态随代码更新为 partial(pending)

* feat(windows): 声明式插件宿主 M2 —— 磁盘导入链、管理界面与版本探测

- plugin_host/install.rs:ZIP/目录→私有快照(拒绝 reparse point、路径逃逸、
  超限文件与恶意 ZIP 条目)→plugins.marketplace.installReview 全量审查→
  确认时摘要比对拒绝快照调包→staging 复验后激活;卸载、回滚、启用/停用
- launch.rs:runtime 启动按 versionArguments 探测实际版本,低于
  minimumVersion 拒绝启动;版本 token 解析容忍 v 前缀、引号与 go/java 输出
- 设置新增一级页"声明式插件(契约 v1)":安装审查卡(未认证发布者提示、
  权限与完整程序声明展开)、启用/停用/卸载/回滚,与 Worker 扩展分开列出;
  en-US 与 zh-CN 全套文案
- install_extension_from_url 等 Worker 非语言市场命令注册为显式占位错误
  (extensionStore.notAvailable),调用方得到可诊断失败而非命令不存在
- 矩阵 plugin-marketplace/plugin-extension-management/declarative-plugin-contract
  Windows 证据与 notes 随代码更新;Note 增补 M2 记录

* feat(windows): 声明式插件宿主 M3 —— 声明式设置、运行计划与契约 PHP 包

- 能力声明提升:languageServers [1,2]、settings [1,2],settings-v2 fixture
  由能力门控改为接受
- plugin_host/settings.rs:全局值(plugin-settings/<id>.json,默认值遗忘规则)
  与项目覆盖(工作区 .lithe/plugin-settings.json,空项清理、损坏拒写)双层
  存储;resolveSettings / storeSetting / workspaceConfiguration 三个命令;
  launch 请求现携带已存设置
- plugin_host/run_plans.rs:runPlan/testPlan 命令,展开 Core 模板后走共享
  run 链路(resolveRunLaunch → startRunProcess),进程归属复用 Worker 扩展
  的 ExtensionProcessOwner
- 设置编辑 UI:按声明 scope/effect 渲染控件,显示值来源徽标,immediate
  效果经 workspaceConfiguration 下推;show/hide 折叠进插件行
- Plugins/win/Official/PhpSupportContract:契约版 PHP bundled 包(API 2,
  launch kind runtime),随安装器资源分发;端到端测试覆盖 validate、
  runPlan、testPlan、resolveSettings。Worker 版 PHP 保留:其 composer
  scripts 动态运行动作在契约 v1 无等价能力,删除会造成功能退化,完整
  迁移推迟(Note 已记录)
- 矩阵 declarative-plugin-settings Windows partial、declarative-plugin-contract
  证据与 notes 更新;Note 增补 M3 记录

* feat(windows): 声明式插件宿主 M4 —— Web 工具窗口(ui 2)

- plugin_host/web.rs:lithe-plugin:// 自定义 scheme 只服务启用包内普通文件
  (拒 reparse point、路径逃逸、超 16MiB、非白名单扩展名),响应带
  CSP(default-src 'none'、拒 eval 与联网、frame-ancestors 'none')、
  nosniff、no-store、CORP
- window.lithe 桥 v0:document-start 注入冻结桥;context、
  ui.getState/setState(宿主持有状态,64KiB 上限)、workspace.openFile、
  事件泵;build.*/functions.* 在 Windows 构建系统能力接入前返回
  plugin.web.unknownMethod
- 页面生命周期命令:open(去重聚焦)/close;禁用卸载清状态
  (forget_plugin_state)
- 能力声明 ui 提升为 [1,2],web-panel fixture 转为被接受(门控测试同步)
- 管理区块新增 Web 工具窗口列表(打开/关闭),en-US/zh-CN 文案
- 矩阵 plugin-web-tool-windows Windows partial、declarative-plugin-contract
  evidence/notes 更新;Note 增补 M4 记录

* chore(windows): 清理 plugin_host/web.rs 未使用的 PageRequest 结构与 Deserialize 导入

* fix(windows): 修复插件宿主审查意见 —— 权限隔离、启动信封解包与端到端接线

P1(两项):
- 插件 WebView 脱离主窗口通配 capability:main.json 收窄为 main/workspace-*,
  新增 plugin-web capability(core:event 最小集,无 fs/http/shell/dialog);
  桥身份改由调用 webview label 反解(bridge_identity),核对插件启用、
  窗口声明与归属,伪造参数/跨插件/非插件窗口一律 plugin.web.forbidden
- launch 解包 Core 响应信封后再解析(outcome["plan"]),新增走真实
  Core 命令的回归测试(此前单测绕过了信封导致该路径必然失败)

P2:
- 设置编辑器按 ID 从宿主 catalog 取完整 manifest(新增
  declarative_plugins_manifest 命令),resolve/workspaceConfiguration 不再
  传 ID 占位清单;加载与解析错误保持可见
- 运行入口接通:新增 declarative_plugins_language_owner 归属查询,run
  动作发现接入 useRunActionDiscovery(source: declarative),运行菜单
  直接分发;删除会漂移的前端目录缓存
- 停用/卸载/回滚前关闭插件全部 Web 窗口并清状态;scheme 文件服务只服务
  enabled 包
- workspace.openFile 接前端监听(plugin-web-open-file.ts):限工作区根内
  路径,走 handleFileSelect(带 line/column)
- 版本探测宿主只跑 versionArguments,判断委托 Core
  checkRuntimeVersion(共享 runtime-versions 语义),删除自建解析器

* fix(windows): 修复第二轮 review 意见 —— IPC 命令隔离与端到端接线收口

P0:
- invoke_handler 包装插件页门控:label 为 plugin-web-* 的调用只允许
  declarative_plugins_web_bridge_request(改为直调的普通函数,消费原始
  Invoke,绕过宏推断问题),其余应用命令(run_start_process 等进程/文件/
  HTTP 面)一律 resolver.reject——插件页面无法再通过原始 Tauri IPC 调用
  宿主命令
- generate_handler 宏在非直接实参位置无法推断 R:用
  Box<InvokeHandler<Wry>> 在绑定处钉定(本地最小复现 crate 验证)

P2:
- initializePluginWebOpenFileListener 真正接入 bootstrap(此前只有定义)
- immediate 设置:编辑器取 Core 展开的 configuration 后经
  lsp.updateWorkspaceConfiguration 下推到运行中的 LSP 会话
- 停用/卸载时 Rust 发 declarative-plugin-lifecycle 事件,前端进程 owner
  停止该插件全部声明式运行会话
- test plan 产品入口:declares_tests 标记进入 catalog,运行菜单的声明式
  动作按插件测试模板走 testPlan(v1 传当前文件供项目标记判定)
- 同版本重装激活失败时备份/恢复原版本目录,不再出现安装记录指向缺失
  字节的隔离状态(新增恢复路径测试)

P3:
- 共享契约 README 更新 Windows ui: [1,2] 状态与桥 v0 方法范围

* fix(windows): close declarative plugin review gaps

* fix(windows): address plugin host review gaps

* fix(windows): harden declarative plugin page and probe boundaries

* fix(windows): drain declarative plugin owners before package changes

Preserve plugin identity and cancel in-flight starts; enforce launch requirements, scope web pages and events to their owners, and expose declarative UI contributions. Add bounded regression coverage and document the remaining parity work.

* test(windows): isolate plugin host in terminal lifecycle fixture

Keep the real activity rail and terminal docking coverage while stubbing declarative plugin state and native window launch at the feature boundary. This prevents the fixture's narrow pane mocks from being loaded by the unrelated workspace services.
* feat(macos): Agent 对话显示工具图片缩略图、点击放大,并将后台任务通知显示为状态行 (#1462)

* feat(macos): 图片放大支持缩放,折叠过程显示缩略图,适配更多 Claude Code 特殊消息格式 (#1462)

* fix(macos): 导航栏不再把 Claude Code 特殊消息当作提问,图片查看器不再让转录重绘 (#1462)

* fix(macos): 修复 Agent 图片显示评审问题:id 去重、哈希、焦点、缓存与解析边界 (#1472)

- 图片 id 去重,避免 ForEach 重复 id
- 指纹改用 SHA-256,避免主线程逐字节循环
- 用户消息解析结果按消息缓存
- 查看器 ←/→ 仅在持有焦点时翻页,拖动限制在画面边缘内
- 只移除消息首尾的模型专用块,不吞用户中间引用的标签
- 图片按原文位置排序,超出上限的引用显示 +N
- read 只对存在的文件生成缩略图,解码失败显示占位
- 缓存限制成本,键含修改时间,解码任务随行取消
- 内联数据须能被 ImageIO 识别,否则退回文字条目

* feat(macos): 后台任务通知并入后续过程区,恢复 Claude 会话时补全压缩前的完整历史 (#1472)

- 成功的后台任务通知不再单独成行,进入随后一轮的折叠“思考过程”;失败、被终止或后面没有过程的通知仍显示
- Claude 的英文 shell 任务摘要按界面语言显示(后台命令已完成:…)
- Rust 宿主在 session/load 前只读取会话文件中最后一个压缩点之前的记录,转成回放更新,压缩前的用户消息、回复、思考和工具调用都能查看
- 读取范围:只读 projects/*/<会话 id>.jsonl,按所选账号目录解析,大小和条数有上限
- 新增翻译放在 shared/i18n,更新功能矩阵与 Agent Note

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* perf(macos): 后台通知判断复用用户消息解析缓存

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(macos): 回放时相邻的用户消息不再合并成一条

连续的用户消息(例如后台通知后紧跟用户输入)在回放时被拼成一个气泡,导致通知标记无法识别而显示原文。
按上游 messageId 区分用户消息;压缩前的历史也带上记录 uuid。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(agent): 恢复 Claude Desktop 开始的会话时显示可读历史

- 宿主把 mcp__ccd_turn__wrap_up 改写成 Agent 回复,吞掉其后续 tool_call_update
- 宿主把 mcp__ccd_turn__update_plan(整表/增量)改写成完整 ACP plan 更新
- 压缩前文回放补上对话中途排队的用户消息(queued_command),工具调用带上 name
- 历史回放时计划快照作为清单显示在折叠过程之间,导出为任务列表,不计入消息数
- 折叠的过程标题附工具摘要(如运行了 N 条命令)

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
…s data into it

- OfficialPluginCatalog lists dev.lithe.plugin.database as a publisher
  package downloaded from the marketplace; language-only fields move into
  an optional Entry.language, so a non-language plugin needs none.
- MacDatabasePluginMigration moves the former module's connections,
  folders, SQL history, and forever-kept passwords into the plugin's
  ${stateDir} and credentials once, before its backend first starts
  (MacPluginBackendSessions gains a prepareState hook). The old data stays
  for older Lithe versions; the plugin's own state always wins.
- Workbench notifications can carry one action and then stay until used.
  People with saved connections and no database plugin get one prompt
  with an "Open Marketplace" action.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…in now

Lithe no longer ships a database module. The official plugin
dev.lithe.plugin.database (Lithe-IDEA/lithe-plugin-database) replaces it,
and the earlier commit moves saved connections into it.

- macOS: delete LitheDatabaseModule, the database views, adapters,
  recovery store, coordinator, sidecar locator, brand icons, dbx fixtures,
  and the database tool windows, editor tabs, theme tokens, console gutter
  and AppModel branches. Generic tests that used the database as a sample
  now use other modules. Dropdown/context-menu parameters only the database
  used are gone. Idle sleep keeps a visible module window open; only
  shutdown closes it.
- Rust: delete lithe-db-sidecar and lithe-db-mcp.
- Windows: delete features/database and its sidecar packaging, the
  databases extension contribution, and every database branch; openBuffer
  loses its two database-only parameters. No plugin adaptation yet.
- CI and scripts: delete the database workflow, validation docker setup
  and sidecar/MCP build and smoke scripts; packaging, preview, verifiers,
  CI change classification and lane reuse drop the database.
- i18n: drop strings only the removed UIs used and regenerate.
- Feature matrix, Agent Notes, README, docs and Skill: the database is an
  official plugin; the plugin note is implemented, the multi-schema tree
  note is archived.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	macos/Resources/en.lproj/Localizable.strings
#	macos/Resources/zh-Hans.lproj/Localizable.strings
#	shared/i18n/locales/en-US.json
#	shared/i18n/locales/zh-CN.json
#	shared/i18n/messages.json
#	shared/platform-feature-matrix/features/plugin-web-tool-windows.json
#	windows/tauri/src/features/window/components/window-menu-bar.tsx
Lithe's official signing path has never released a plugin and its v2
private key is out of reach, so the Database plugin is a community
plugin (io.github.lithe-idea.database, unsigned) listed in Lithe Store
like the other seven.

- OfficialPluginCatalog no longer lists the database plugin; the optional
  Entry.language refactor that only it needed is reverted.
- An unsigned plugin ID proves nothing, so MacDatabasePluginMigration now
  moves the old connections and passwords only into a copy installed from
  Lithe Store whose index entry names Lithe-IDEA/lithe-plugin-database.
  A copy from disk or another source gets nothing and leaves no marker,
  so installing from Lithe Store later still migrates. The backend
  sessions' prepareState hook receives the installation record for this.
- Feature matrix, README and the Agent Note describe the community plugin,
  why official signing is deferred, and the new trust boundary.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The migration from the former built-in module was accepted on a macOS
development-identity build: the one-time notice, installing Database 0.1.0
from Lithe Store, and the connections, folders, history, and passwords
arriving in the plugin as the Agent Note describes. The matrix marks the
migration row verified on macOS; the other database rows stay pending.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
feat(database): 数据库模块改造为组织仓库中的独立插件
* fix(agent): 恢复压缩过的 Claude 会话时保留压缩前用户消息里的截图

* fix(agent): 压缩前历史回放的截图超过客户端大小上限时不再发送
* feat(agent): 兼容 Claude Desktop 会话独有机制,Agent 面板以卡片呈现

- agent host 识别 Desktop 工具(章节、建议回复、任务、PR、目录、可视化),给出可读标题并在 _meta.lithe.claudeDesktop 中附带卡片
- claude.ai UUID 连接器显示为 Connector: <工具>
- macOS 面板渲染卡片:建议回复跟在回合总结后,卡片操作只填入输入框
- 可视化在禁网、禁导航的非持久 WKWebView 中渲染
- Desktop 事件包装与跨会话通知按上下文显示,不算用户发言
- 共享 LitheChipFlowLayout,更新 i18n、契约、Agent Note 与功能矩阵

* fix(agent): 可视化页面的 sendPrompt 只在用户点击或按键之后才填入输入框

* fix(agent): 按 review 修复可视化外链出口、任务失败记录丢失和压缩历史输入被截断
* fix(windows): open focused files with configurable F4 command

* ci(windows): include focused F4 navigation regression

* test(windows): await process exit signals and own fixture cleanup

* fix(search): open the focused excerpt line with F4

* refactor(plugins): 契约发布到 lithe-plugin-docs,fixture 按能力改名,SDK 移出主仓库 (#1442)

* refactor(plugins): 契约发布到 lithe-plugin-docs,fixture 按能力改名,SDK 移出主仓库

- 契约 fixture 按演示的能力改名(文件名和 dev.lithe.fixture.* ID),同步更新
  标准答案、Rust Core 测试、macOS 测试与展示副本、功能矩阵和 Agent Notes。
- 两份 schema 的 $id 改为 lithe-plugin-docs 的 raw 地址;verify-shared-contracts.sh
  要求 $id 完全相等,并拒绝离开契约目录的 README 相对链接。
- 契约 README 的目录外链接改为绝对地址,说明 lithe-plugin-docs 保存完整副本,
  官方 SDK 一节指向 lithe-plugin-docs。
- 删除 sdk/、SDK 端到端测试和 Java SDK 发版工作流;Rust Core 的 CI 脚本、
  ci-macos.yml、CI 分类和 .gitignore 去掉 SDK 相关内容。
- AGENTS.md 新增两仓库同步规则,新增 Agent Note 记录决策,并更新 SDK 相关
  Note、develop-lithe 布局表、Plugins README 和 docs/ci-builds.md。

* docs(plugins): SDK 与契约的每周检查跟踪 preview 而不是默认分支 main

* fix(macos): keep marketplace details inside split bounds (#1447)

* feat(agent): 完善技能、全局指令与 MCP 服务器设置 (#1381)

* feat(agent): add native global and project skill management

* fix(macos): make skill toggles respond immediately

* feat(agent): 新增原生全局指令并稳定技能开关反馈

在 AI 设置中保留独立的指令与技能入口,直接编辑 Codex/Claude 用户指令文件,提供草稿、冲突校验和原子保存。为技能成功提示保留布局空间,覆盖连续启停、深浅主题和窄宽页面的原生几何回归。

* fix(agent): 技能保存仅锁定当前行,避免其他开关变灰

将待确认选择按点击顺序串行保存,其他技能保留原生启用外观和交互能力。覆盖同一 Agent 连续写入、单行失败回滚、队列继续、重复点击去重、项目切换及离页清理;同步 Agent Note 与平台矩阵。

* feat(agent): add shared instruction cards and native synchronization

* feat(mcp): add bundled publisher icons and common featured servers

* feat(mcp): 增加工具检测与原生工具开关

* fix(agent): preserve cancellation and native MCP tool filters

* fix(skills): publish Windows skill packages without replacement

* fix(ci): bound multi-repository tests and join search fixture teardown

* test(windows): await owned process exit signals and clean fixtures

* fix(agent): close cancellation and MCP policy lifecycle gaps

* test(ci): bound Windows frontend path roundtrip startup

* fix(ci): match raw path test names for scoped deadlines

* test(ci): scope checkout and clone integration timing allowance

* fix(ci): allow Agent Host cold compilation within Rust suite budget

* fix(macos): 终端配色同步: 主题刷新、COLORFGBG 与订阅制背景通知 (#1448)

* fix(macos): 刷新已打开终端的主题色

* feat(macos): 终端环境导出 COLORFGBG

- `COLORFGBG` 是 Terminal.app、iTerm2、tmux 等终端的行业惯例环境变量;omp 等 TUI 在进程启动时同步读取其 bg 字段(<8 深、>=8 浅)选择配色,先于任何 OSC 往返,可消除首帧按回退深色渲染的闪变。
- Lithe 终端此前未导出该变量;且终端视图加入窗口前 effectiveAppearance 跟随系统外观,直接读它会与 Lithe 主题不一致。

- `TerminalTransport` 协议新增 `reportsLightBackground: Bool?`(宿主是否渲染浅色背景,无法判定时为 nil),extension 默认 nil
- `TerminalSession` 以可选值直赋导出 `COLORFGBG`(浅色 `0;15`、深色 `15;0`;fg;bg 惯例,判读位是 bg 字段),宿主无法判定时同时清除从外层终端继承的同名值
- macOS 实现按应用主题偏好解析:视图未挂载窗口时用主题 pin 的明暗,挂载后用窗口外观
- `TerminalModuleTests` 新增 4 个用例(浅色、深色、无法判定不写入、清除继承值);更新 `terminal-shell.json` 能力矩阵

- `TerminalModuleTests` 全绿(含 4 个新增)
- 平台能力矩阵门禁通过
- 真机浅色/深色首帧配色正确,无闪变;`echo $COLORFGBG` 输出 `0;15` / `15;0`

* fix(macos): 背景通知仅推送给订阅 kitty DEC mode 2031 的程序

- 背景变化通知由无条件推送改为按订阅发送: 解析进程输出中的 CSI ? 2031 h/l (含组合 DEC mode 与跨块分片), 未订阅的 shell 不再收到响应字节
- DSR 997 按背景亮度如实报告: 997;1n 暗色、997;2n 亮色
- 新进程启动与终端 RIS 重置清除订阅状态
- 单测 15 用例: 通知编码门控与明暗状态 + 订阅解析全路径

* feat(vcs): Core 与 Node SDK 实现插件 VCS Provider 底层(#827 P1) (#1430)

* feat(vcs): Core 实现插件 VCS Provider 底层(#827 P1)

- 插件清单 API 3 新增 vcsProviders 能力、process.vcs 权限和 onVcsRoot 激活事件,git 为保留 ID;安装审查以 vcsTool 列出 VCS 命令行
- 新增 vcs.detectRoots(静态标记识别根、歧义目录与用户映射、祖先工作副本)、vcs.ownerOf(最深根归属)、vcs.decodeReply(Provider 回复校验与归一化)
- LSP 会话:只向插件会话提供 litheVcs 协商,成功后发出 vcsProvider 事件;lsp.vcsRequest 按操作生成 lithe/vcs/* 请求并检查已协商能力;Provider 错误码只保留契约白名单
- lithe/vcs/execution 转为会话日志事件,lithe/vcs/authenticate 暂按未知请求回绝
- 契约、插件 README/schema、rust-core-api、fixtures、功能矩阵与提议 Note 同步
- 修复 unregistering_a_running_function_revokes_the_call 的竞态:改为有界等待 $/cancelRequest 写出

* feat(sdk): Node SDK 支持 litheVcs 并用示例 Provider 端到端验证(#827 P1)

- backend.vcs(id, handlers, traits) 按声明的处理函数协商 VCS 能力,必需 status/baseContent/checkin/rollback,git 保留,litheVcs 不能手写进 capabilities
- 只在宿主提供 litheVcs 1 时分发 lithe/vcs/* 请求;回复必须是对象,无返回值视为 {}
- VCS 处理函数的 context.run 自动发出 lithe/vcs/execution(命令行、退出码、耗时、截断到 16 KiB 的 stderr),可用 report: false 关闭
- 导出 VCS_ERRORS 与 isVcsId,补充类型声明、README 和单元测试
- 新增 sdk/node/examples/sample-vcs 玩具 VCS,Rust 端到端测试经真实 Core 会话跑通协商、全部 11 种操作、错误码和执行报告
- 契约写明 lithe/vcs/execution 的参数;Note 与功能矩阵更新 P1 完成状态

* fix(vcs): 按评审修正祖先根判断与示例移动回滚(#827 P1)

- 只有全部由 .. 段组成的根 ID 才是工作区外的祖先根;工作区内名为 ..repo 的目录按普通路径计算深度和包含关系,补充单元测试
- 示例 Provider 回滚移动目标时把文件移回原路径、恢复基线内容并清除移动记录;端到端测试覆盖移动后回滚
- 插件能力版本笔记补充 vcsProviders、其对 serverProcess 的依赖、两端宿主尚未声明的状态,以及 litheVcs 协商

* feat(vcs): macOS 宿主接入插件 VCS Provider,SVN 改为独立社区插件(#827 P3) (#1441)

* feat(vcs): Core 实现插件 VCS Provider 底层(#827 P1)

- 插件清单 API 3 新增 vcsProviders 能力、process.vcs 权限和 onVcsRoot 激活事件,git 为保留 ID;安装审查以 vcsTool 列出 VCS 命令行
- 新增 vcs.detectRoots(静态标记识别根、歧义目录与用户映射、祖先工作副本)、vcs.ownerOf(最深根归属)、vcs.decodeReply(Provider 回复校验与归一化)
- LSP 会话:只向插件会话提供 litheVcs 协商,成功后发出 vcsProvider 事件;lsp.vcsRequest 按操作生成 lithe/vcs/* 请求并检查已协商能力;Provider 错误码只保留契约白名单
- lithe/vcs/execution 转为会话日志事件,lithe/vcs/authenticate 暂按未知请求回绝
- 契约、插件 README/schema、rust-core-api、fixtures、功能矩阵与提议 Note 同步
- 修复 unregistering_a_running_function_revokes_the_call 的竞态:改为有界等待 $/cancelRequest 写出

* feat(sdk): Node SDK 支持 litheVcs 并用示例 Provider 端到端验证(#827 P1)

- backend.vcs(id, handlers, traits) 按声明的处理函数协商 VCS 能力,必需 status/baseContent/checkin/rollback,git 保留,litheVcs 不能手写进 capabilities
- 只在宿主提供 litheVcs 1 时分发 lithe/vcs/* 请求;回复必须是对象,无返回值视为 {}
- VCS 处理函数的 context.run 自动发出 lithe/vcs/execution(命令行、退出码、耗时、截断到 16 KiB 的 stderr),可用 report: false 关闭
- 导出 VCS_ERRORS 与 isVcsId,补充类型声明、README 和单元测试
- 新增 sdk/node/examples/sample-vcs 玩具 VCS,Rust 端到端测试经真实 Core 会话跑通协商、全部 11 种操作、错误码和执行报告
- 契约写明 lithe/vcs/execution 的参数;Note 与功能矩阵更新 P1 完成状态

* fix(vcs): 按评审修正祖先根判断与示例移动回滚(#827 P1)

- 只有全部由 .. 段组成的根 ID 才是工作区外的祖先根;工作区内名为 ..repo 的目录按普通路径计算深度和包含关系,补充单元测试
- 示例 Provider 回滚移动目标时把文件移回原路径、恢复基线内容并清除移动记录;端到端测试覆盖移动后回滚
- 插件能力版本笔记补充 vcsProviders、其对 serverProcess 的依赖、两端宿主尚未声明的状态,以及 litheVcs 协商

* feat(vcs): macOS 宿主接入插件 VCS Provider(#827 P3)

SVN 插件改为独立仓库 Lithe-IDEA/lithe-plugin-svn 的社区插件
(io.github.lithe-idea.svn-support),主仓库只保留与具体 VCS 无关的部分;
原 #1432 里宿主识别 vcsProviders 的通用改动并入本提交。

- 宿主识别:声明式清单解码 vcsProviders,声明了 VCS Provider 的插件生成一个
  <pluginID>.vcs-providers 扩展模块,只承载启用状态,默认关闭;
  PluginManifest.hostCapabilities 声明 vcsProviders: [1]。
- 安装审核:显示 Provider 的启动命令、客户端命令和是否连接仓库服务器。
- Provider 会话、Core 调用(vcs.detectRoots / ownerOf / decodeReply、
  lsp.vcsRequest)、VcsProvidersFeatureModel、左侧 VCS 工具窗口、历史与差异、
  项目树状态着色和移动跟踪。
- 测试改用契约里的 svn-provider 清单 fixture 和 SDK 的 sample-vcs 样例,
  不再依赖 SVN 插件源码。
- 契约的 Subversion provider notes 改为指向插件仓库;Note、功能矩阵和
  Plugins/mac/README.md 同步说明社区插件。

* fix(vcs): 按自审修正 VCS Provider 宿主(#827 P3)

- 包住工作区的工作副本(如 ../.svn)单独监听其声明的元数据目录,
  终端里的提交或更新也会触发刷新。
- 移动前按 Core 的归属规则确认两端都属于同一根,嵌套的 Git 仓库或
  未选择 VCS 的歧义目录不会被当成 svn move。
- 窗口关闭时调用 shutdown():停掉所有 Provider,之后迟到的工作区
  扫描也不会再把 Provider 拉起来。
- 工具窗口与命令沿用宿主版本控制图标;首次读取时显示“正在读取更改…”;
  变更行补充选择、打开/查看差异、纳入提交的辅助功能操作。
- 同步 Agent Note、能力版本 Note 与跨平台功能矩阵。

* fix(vcs): 隐藏 .svn 并按根监听元数据,补齐工具缺失与比较判断(#827 P3)

- 项目树、搜索、索引与工作区监听像 .git 一样隐藏 .svn(Swift 与 Rust Core 的内置隐藏列表同步),避免 .svn/pristine 进入索引
- 每个插件根单独监听自己的元数据目录(含包住工作区的 ../.svn);工作区里新出现的条目在后台检查标记,新检出的工作副本会重新识别
- 找不到 VCS 客户端时按契约报 vcs.tool.unavailable,工具窗口先显示安装提示
- 是否有基线统一由 VcsRootState.comparesWithBase 判断,工具窗口双击、辅助功能动作和项目树右键共用
- 等待 Core 判断移动归属期间开始了别的操作时,直接退回磁盘移动
- 同步 Agent Note、功能矩阵与 VcsProviderHostTests

* fix(macos): 修正 Agent 正文留白与 AI 设置排序 (#1450)

* fix(ci): 放宽 macOS Swift 编译预算并避免构建失败叠加报告失败 (#1449)

swift-tests 的冷编译在运行 39943871840 中超过 20 分钟上限,与插件通道 39741361768 同类;编译步骤放宽到 40 分钟(job 80 分钟),测试执行预算不变。构建失败时不再叠加合并报告失败,避免同一失败被重复计数。

* feat(windows): 终端活动栏拖动停靠并修正搜索快捷键 (#1436) (#1446)

* feat(windows): dock terminal panel at bottom or right (#1436)

* fix(windows): drag terminal activity entry to either side

* fix(terminal): leave project search shortcut to workbench

* fix(terminal): focus docked sessions after the pane becomes visible

* fix(windows): Ctrl+Z 优先恢复键盘移动后的光标 (#1443)

* fix(windows): Ctrl+Z 优先恢复键盘移动后的光标 (#1438)

* ci(windows): run cursor undo regression in frontend lane

* fix(editor): coordinate explicit cursor undo with generic redo

* docs(skill): gh 不支持 YAML 表单时允许按表单字段生成正文提交 Issue (#1458)

GitHub GraphQL repository.issueTemplates 只返回 Markdown 模板,gh 无法选择
YAML Issue Forms(cli/cli#5865)。Issue 门禁本就接受包含全部必填字段的正文,
因此 submit-lithe-issue 改为:原生模板不可用时用 gh issue create --body-file
提交逐字段生成的表单正文,仍禁止空白正文、API 直建和手工添加 issue-form 标签。

* feat(macos): 编辑区 Agent 大历史秒开与 Claude Desktop 式布局;Claude 支持官方订阅与 API Key 两种模式 (#1453)

* feat(macos): 优化编辑区 Agent 对话的大历史加载与 Claude Desktop 式布局

- 大历史回放性能:loadSession 回放期间消息写入不对外发布的缓冲区,
  sessionLoaded 时一次性提交,消除 @published 字典逐事件整体复制带来的
  平方级开销;1,200 轮(约 1 万事件)接收从 27s 降到 0.45s。
- 对话窗口化:首屏只构建最近 48 项,点「显示更早的 N 项」或导航栏跳到
  旧回合再展开,首次排版从 31s 降到 0.3s,总加载 <1s。
- 历史列表:按收藏/今天/昨天/过去 7 天/过去 30 天/更早/时间未知分组,
  行改为 Agent 磁贴 + 标题 + 消息数 + 会话 ID + 相对时间 + 「…」菜单;
  排序筛选改为一次快照。选择、多选、归档、已移除、导出等能力保留。
- 编辑区会话 UI 向 Claude Desktop 靠拢:用户消息中性灰气泡、16pt 圆角
  卡片输入框(仅添加/发送)、审批模式与模型下移到卡片下方状态行;
  详情栏改为上下文/更改/会话统计三个可折叠分区,并新增「更改」。
- 标题栏新增详情栏开关按钮,原菜单项保留。工具窗口侧栏样式不变。
- 新增 AgentLargeHistoryLoadTests;同步 Agent Note、功能矩阵、zh-Hans 本地化。

* perf(macos): 历史列表滚动不再掉帧;居中对话改为 Claude Desktop 式卡片详情栏

- 历史列表:排序结果、行数据、列表版本号三层记忆;流式输出期间刷新从
  p50 14ms(25% 掉帧)降到 1.7ms(0 掉帧),纯滚动 p95 从 8.6ms 降到 1.4ms
- 时间戳解析、本地化 .lproj 查找、DateFormatter 加缓存;canExport 改为打开
  菜单时按行计算(原先每行 O(n),整表 O(n²));managementSessions 只排序一次;
  消息数与临时标题不再复制整个对话
- 历史行:标题 + 消息数 + 时间 + 「•••」,1 小时内显示「N 分钟前」、之后显示
  具体时间;菜单为置顶/重命名/分叉/归档/复制 Session ID/导出/删除;固定行高、
  菜单只在悬停或当前行挂载
- 居中输入卡片内放 Agent、权限模式、模型、添加、发送;权限模式名称本地化
- 右侧详情栏 AgentEditorDetailsColumn:圆角卡片 + ▾ 折叠,上下文图例与更改列表
  按参考图排版;工具窗口输入框的会话详情弹窗恢复原样式

* feat(macos): 编辑区文件审查统一到「更改」卡片,活动卡只保留任务与子 Agent

- 「更改」卡片内可全部保留/全部回滚、逐个文件看 diff/回滚(悬停显示),
  回滚前确认;活动卡在编辑区不再重复显示文件修改行
- 批量菜单与筛选图标统一为「置顶」术语
- 清理不再使用的参数与常量,历史缓存清理已关闭对话的计数

* feat(agent): Claude 支持官方订阅与 API Key 两种模式;居中输入框改为状态圆环,权限模式汉化

- Claude 订阅(claudeSubscription):直接使用本机 Claude Code 已登录的
  claude.ai 账号。Host 新增 claude_subscription.rs:不注入 API Key/路由,
  移除继承的 ANTHROPIC_* 覆盖变量,初始化后读取适配器的登录状态,未登录时
  提示在终端用 /login 登录;Lithe 不读取、复制或刷新任何凭据
- 订阅只属于各自适配器(Codex 订阅不能给 Claude,反之亦然);供应商管理
  新增「Claude 官方订阅(本机账号)」开关,预检文案区分 API Key 与两种订阅
- 居中模式输入卡片去掉「+」与「发送」,右侧改为额度与上下文圆环,回复中
  才显示停止按钮;详情栏移除重复的额度卡片
- 权限模式按上游 ID 显示中文(Codex:请求批准/替我审批/完全访问;Claude:
  手动/接受编辑/计划/自动/跳过权限确认),菜单标题「模式」;修正 Claude
  「手动」的 ID 为 default
- 同步 Agent Note、新增功能矩阵 agent-claude-subscription、Rust 与 Swift 测试

* fix(agent): 评审修复——窄窗口保留活动入口、Claude 订阅额度圆环、权限模式翻译不误伤其他 Agent

- 居中模式详情栏关闭或宽度不足时,输入框上方恢复活动摘要(任务、子 Agent、
  文件审查与回滚),避免这些入口消失
- 上下文圆环始终显示(未上报时为空圈);Claude 订阅接入额度圆环:解析适配器
  转发的 rate_limit_event(_claude/rateLimit),按 five_hour/seven_day 等窗口
  累积,快照在窗口重置前有效,悬停显示「截至某时刻,仅在回复时更新」,不调用
  任何接口
- 权限模式只在「上游 ID + 英文原名」都匹配时翻译,其他 Agent 的同名 ID 保持原名;
  改写原先断言保留英文名的测试,Agent Note 记录决策变更
- 编辑区居中布局测试改用 Agent 切换按钮测量输入框左缘(附件按钮已移除)

* feat(macos): 新建项目向导,插件通过 projectGenerators 注入项目模板 (#1452)

* feat(macos): 新建项目向导,插件通过 projectGenerators 注入项目模板

- Rust Core 新增能力 projectGenerators 1(pluginAPIVersion 保持 3)和
  project.generatorCatalog / generatorForm / generationPlan / checkName /
  extractArchive 命令:校验声明、计算表单(派生默认值、显示条件、错误码)、
  展开模板文件/命令/下载地址,安全解压项目压缩包。
- 新增内置官方插件 Java Project Templates:Java(Lithe/Maven/Gradle)、
  Maven Archetype、Spring Boot(start.spring.io,可改服务器 URL)。
- macOS 新建项目窗口按 IDEA 布局,复用设置窗口的原生控件;抽出共享的
  侧栏行、插件字段控件和目录选择器。在临时目录生成后整体移动到位,
  失败或取消不留残留;所选 JDK 写入新项目,模板文件随项目打开。
- 需要的语言/构建插件已停用时可一键启用,未安装时跳转插件市场搜索。
- 修复克隆仓库窗口目标路径文案缺少插值。
- 更新插件契约、schema、fixture、Core API 文档、功能矩阵、打包与资源清单、
  Agent Note。

* refactor(java): 项目模板并入 Java Support,修复 CI 与生成器命令审批

- Java、Maven Archetype、Spring Boot 三个生成器改由 Java Support 声明,移除单独的 Java Project Templates 内置插件及其分发、校验、资源清单和目录条目
- 生成器的 command 步骤计入安装确认的 programs(kind: projectGenerator),更新新增或修改命令会要求重新确认;安装确认界面显示该类程序
- 生成器所在插件自己提供的 requirement 不再重复提示启用
- 模板目录禁用换行转换,修复 Windows 检出 CRLF 导致 golden_project_plans_match 失败
- 补齐 project.* 命令变体的文档注释,修复 missing_docs

* fix(project-generators): 处理评审:下载边收边限、目标 Java 不超过 JDK、固定 Maven 插件版本

- 项目压缩包改为流式下载,超过上限立即取消;错误响应最多读取 64 KiB 用于提示
- 生成器字段新增 maximumVersion(读取前面字段的模板),Spring Boot 的目标 Java 不得高于所选 JDK,Core 返回 versionTooHigh
- Java → Maven 模板固定 maven-compiler-plugin 3.14.0 与 maven-surefire-plugin 3.5.4,Maven 3.8 下 release 属性生效、可运行 JUnit Jupiter
- 补充下载上限、错误说明、版本约束和计划拒绝的测试,同步契约 schema 与文档

* fix(macos): 为声明生成器的语言插件注册 project-generators 模块

Java Support 同时声明语言与生成器后,启动时只为有贡献的模块及构建系统、VCS 模块创建工厂,遗漏 project-generators 模块,模块图校验失败导致启动崩溃。补充注册并增加回归测试。

* fix(macos): 新建项目窗口审查修复

- 未找到 JDK 时提示安装,不再一直显示“正在查找”
- 高级设置中的字段出错时自动展开,避免创建按钮无故不可用
- Spring Server URL 规则与 Core 一致:只接受 https 或本机 http
- 下载中取消按取消处理,不再显示错误
- 表单求值复用目录加载时的插件列表,输入时不再逐键重建插件快照
- 路径缩写改用 abbreviatingWithTildeInPath,避免主目录前缀误替换

* feat(remote): 远程开发 Rust 核心——协议、轻量远端服务与传输链 (#1460)

* feat(remote): 远程开发 Rust 核心——协议、轻量远端服务与传输链

- lithe-remote-protocol:帧格式、消息信封、方法与稳定错误码、主机能力描述
- lithe-remote-server:Rust 原生远端服务(Linux 静态约 0.7 MiB),提供文件与进程能力,Linux/macOS 差异集中在平台适配器
- lithe-remote-client:本机/SSH/Docker/Podman 可叠加的传输链、校验哈希的远端安装、会话
- 新增 Linux 专用 Remote Workspace CI lane 与 verify-remote-workspace.sh(含体积上限)
- 提案 Note、协议契约文档与功能矩阵条目

* fix(remote): 修复评审指出的并发创建、临时文件权限、进程组清理、写入超时与 SSH 嵌套引用问题

- fs.writeFile:只创建(不带 expected、不允许覆盖)时用不覆盖的改名提交,并发创建同一文件只有一个成功,另一个返回 ALREADY_EXISTS
- fs.writeFile:覆盖已有文件时,临时文件创建权限不超过原文件,写完再恢复原权限,不再短暂以 0644 暴露 0600 文件的新内容
- process:组长退出后,组里还有成员时继续持有该进程组;process.kill 和断线清理以“组内已无进程”为结束依据
- 客户端会话:改由独立写线程发送,请求只入有上限的队列,同一截止时间覆盖入队、发送和等待响应;超时未发出的帧直接丢弃
- 传输链:内层 SSH 跳转生成的命令行用 '"'"' 转义单引号,支持多个 SSH 跳转嵌套;原始参数的拒绝规则不变
- 新增回归测试,同步更新协议契约和提案 Note(含 SSH 连接配置界面的字段映射参考)

* fix(remote): 服务退出前等待进行中的文件请求完成,避免残留临时文件

- 断线或 server.shutdown 后,服务在清理进程组之后最多再等 5 秒,让文件请求完成,不在写入途中退出
- 进行中请求计数改为 Mutex + Condvar,支持有界等待;上限和 BUSY 行为不变
- 新增断线时写入仍在进行的回归测试;同步协议契约和提案 Note

* feat(agent): 新增 Codex / Claude Code 原生 Hook 管理 (#1459)

* feat(agent): add native Hook library for Codex and Claude

* feat(agent): align Hook editor with reference form layout

* fix(hooks): show feedback when Windows search has no matches

* fix(macos): shell 退出后自动关闭终端标签页 (#1456)

- TerminalSession 新增 onEnded 回调: 进程自行退出时通知宿主; 宿主主动 stop、restart 或启动失败不触发
- 交互式终端 shell 退出 (Ctrl+D / exit) 后复用既有关闭路径: 移除标签并重选相邻会话, 最后一个终端关闭时隐藏终端面板
- 调试与运行终端不挂接回调, 进程结束后保留输出, 由调试会话负责清理

Co-authored-by: Lichenkang <2188718831@qq.com>

* feat(remote): 远端后端补全——文件监听、终端、登录环境、隧道与断线重连 (#1461)

* feat(remote): 远端后端补全——文件监听、终端、登录环境、隧道与断线重连

- 服务改为会话与连接分离:常驻会话(--connect/--daemon)断线后终端和构建继续运行,事件重放给下一个连接,空闲超时后结束
- 所有子进程统一由专门的创建线程启动,修正 PR_SET_PDEATHSIG 跟随线程导致误杀的问题
- 新增目录遍历、文件监听(inotify / FSEvents)、PTY 终端、登录环境解析、TCP/Unix socket 隧道、监听端口列表、fs.copy/realPath/setPermissions、server.ping/state
- 资源 id 改为客户端分配;结束进程和关闭终端时信号发给整个会话
- 客户端新增按资源分发事件、强类型 API 和本地端口转发
- 按功能拆分端到端测试;更新协议契约、提案 Note 与功能矩阵

* fix(remote): 连接结束时关闭常驻进程保留的 socket,避免代理进程滞留远端

常驻进程为“新连接顶替旧连接”保留了每个连接 socket 的一份描述符,连接结束后
它仍然打开,代理收不到结束信号,每次断开都会在远端留下一个卡住的代理进程。
BSD/macOS 上对端半关闭后 shutdown 会返回 ENOTCONN,所以改为真正关闭这份描述符,
并新增回归测试。重连相关测试耗时从约 2.3 秒降到约 0.3 秒。

* test(remote): 端口转发测试改为通过共享句柄关闭会话,消除与桥接线程退出的竞态

* fix(remote): 修复代码审查发现的 10 个问题

- fs.copy:拒绝把文件复制到自身(同一路径、经过符号链接的任一方向、硬链接),避免截断源文件;在解析链接之后检查目录是否复制进自身
- fs.copy:socket、FIFO、设备文件不复制,作为复制对象本身时返回 UNSUPPORTED,在目录树里跳过并计数,避免打开 FIFO 永久阻塞
- tunnel:新增 tunnel.shutdownWrite,先写完排队数据再半关闭;端口转发在本地半关闭时使用它,响应照常返回
- 事件带递增 seq,服务端保留到客户端 server.ack 确认为止,连接断开时队列和内核缓冲区里的事件不再丢失
- 新增 server.resume:握手后等客户端订阅完再续传,重连后接上的终端能收到断开期间的输出
- 后台每 500ms 清理只为剩余成员保留的会话,kill 和关闭终端前先清理,缩小 pid 复用的风险窗口
- 会话存活检查合并为一次进程表扫描;kill 和关闭终端改在工作线程执行,不再阻塞有顺序要求的输入
- 常驻进程收到 shutdown 后先删除 socket 再回复;新常驻进程等待旧进程释放锁而不是静默退出;代理等待时间延长到 30 秒
- accept 失败(如 EMFILE)时退避,不再空转刷日志;PortForward 同样处理
- macOS lsof 退出码 1 视为成功(无匹配或无权检查部分进程)
- 每个问题都有回归测试;同步更新协议契约和提案 Note

* feat(macos): 插件声明式原生界面与公共控件统一 (#1351) (#1423)

* feat(macos): add declarative native plugin UI and unified public controls

* fix(macos): preserve drafts and actions in shared tree interactions

* test(macos): locate history search independently of native prompt

* test(plugins): add dedicated shared button acceptance panel

* fix(plugins): include required nodes in button acceptance panel

* test(macos): exercise dependency sidebar context menu business result

* test(core): bound search source-cap fixture filesystem work

* test(windows): await descendant process termination by handle

* ci(windows): budget real submodule watch-context integration

* ci(windows): budget workspace integration and avoid rebuilding failed tests

---------

Co-authored-by: Yao Jingxi <23722032@bjtu.edu.cn>

* feat(remote): 远程开发连接窗口——SSH 连接配置、测试、主机信息与打开远程文件夹 (#1463)

* feat(remote): 远程开发连接窗口——SSH 连接配置、测试、主机信息与打开远程文件夹

- 欢迎页新增“远程开发”:左侧连接列表,右侧连接概要、连接/认证/远程项目/主机信息/高级设置分组卡片
- 认证方式支持自动、SSH Agent、私钥、密码;密码和私钥口令可记住到独立钥匙串服务 remote,只在首次被要求时自动填入,验证码、主机指纹和重复提问弹窗询问
- 测试连接显示系统、内核、CPU、内存、磁盘、运行时长、主目录和解析地址;IP 地区仅在用户点击时通过 ipinfo.io 查询
- 单连接启动:一条 SSH 连接完成探测、按 SHA-256 复用或上传远端服务并启动,密码主机只认证一次
- App 附带 Linux x86_64/ARM64 远端服务(scripts/build-remote-servers.sh,只读放在 Resources/RemoteServers)
- 打开远程文件夹:以 Application Support 下的空占位根目录打开工作区,文件树与编辑器两个端口按根目录路由到远端,保存带冲突检测
- lithe-core 新增 remote.probe/connect/readDir/readFile/writeFile/disconnect/authRespond
- 新增 Note、契约、功能矩阵、worktree 资源登记与测试

* fix(ci): 守护进程抢锁时不再连 socket 探测;Hooks 设置页改用完整搜索框

- lithe-remote-server: 抢锁失败的守护进程原先用 UnixStream::connect 判断是否已有守护进程在服务,
  这个探测连接会被获胜的守护进程当成新客户端,替换并断开真正的客户端连接,导致
  concurrent_connections_share_one_daemon 稳定失败。改为检查 socket 文件是否存在。
- AgentHooksSettingsView: 搜索框从 LitheSearchTextField + .litheSearchField() 改为 LitheSearchField,
  满足 LitheTextInputTests 对淘汰输入写法的检查。

* fix(remote): 退出时关闭远程连接;文档版本按会话和路径隔离;远程存在性来自主机列表;远程新建统一不支持

* fix(remote): 私钥路径含空格时加引号;失败分类前等 stderr 读完;连接后使用连接时的表单快照;占位目录名不折叠;主机定位排除更多非公网地址

* fix(remote): 关闭项目时释放远程连接;存在性检查共用目录列表;服务端二进制按平台惰性读取;保存超时随文件增长;退出时中止正在建立的连接

* feat(remote): 连接断开后提示并重连同一远程文件夹;新增 connection_closed 错误码

* 对齐 IDEA 的 macOS 数据库树与连接编辑器 (#1451)

* feat(macos): align database explorer and connection editor with IDEA

* fix(macos): stop database test sidecar on cancellation and document UI

* fix(macos): cancel database tree sidecars on collapse and release

* fix(macos): cancel collapsed table metadata and replace forced loads

---------

Co-authored-by: Xiaoyumuxi <23722032@bjtu.edu.cn>

* fix(agent): 合并每轮思考与工具过程,默认折叠展示 (#1464)

Co-authored-by: Xiaoyumuxi <23722032@bjtu.edu.cn>

* fix(lsp): Java 调用补全默认留空实参 (#1437) (#1440)

* fix(lsp): leave Java completion arguments empty (#1437)

* test(windows): await process exit signals and own fixture cleanup

* fix(java): retain plugin completion settings across configuration channels

* test(windows): budget multi-repository push integration cost

---------

Co-authored-by: lick <2188718831@qq.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* feat(i18n): 统一双端完整语言资源与构建时生成 (#1449)

统一 macOS 与 Windows 的完整中英文语言资源,使用 shared/i18n 作为唯一维护来源。

- 集中 9,078 条语义词条,保留 3,927 个 macOS 历史 key 与双端既有译文、默认语言和持久化标识。
- 在构建阶段生成 macOS strings、AppLanguage 和 Windows 类型化 catalog,移除 Windows 分散字典与原生双语条件文本。
- 校验语言覆盖、fallback、参数类型、原生格式 ABI、位置参数、生成结果及打包资源;运行时保持发行资源只读。
- 补齐跨平台 fixtures、功能矩阵、Agent Notes、工作树资源复用规则和三系统 i18n CI。
- 修复生成文件换行及 Node 测试文件期限问题,保留单项测试预算。

验证:Shared i18n 三系统 CI、Windows 完整 CI、插件 CI、macOS Rust Core 与 arm64 Release 包验证通过。macOS 总门禁剩余两个与基线相同的数据库树测试失败,已在 PR 记录;按维护者明确授权使用管理员权限合并,不包含无关测试修复。

Closes #1173

* docs(notes): 提议把数据库拆成双端共用的独立插件

记录数据库模块的双端评估(规则三份不一致、Windows 从未接上后端)
和插件化方案:组织仓库独立插件、网页界面、Rust 后端、官方签名,
主仓库只提供插件后端、宿主凭据、MCP 声明等通用能力。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(windows): 数据库后端未接入时如实标记并按普通文件打开

Windows 的数据库后端从未接入(backend-capabilities 中 database 为 false,
前端调用的数据库命令没有原生实现),但 .db/.sqlite/.duckdb 文件仍被送进
数据库查看器,功能矩阵也标为 implemented。

- getDatabaseTypeFromPath 遵循同一能力开关,后端不可用时这类文件走普通
  二进制/文本路由,打开与会话恢复共用此判断
- 功能矩阵中 Windows 的四项数据库能力改为 missing / not-applicable
- README 注明数据库工作台目前仅支持 macOS

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(database): 生产保护按词法判定危险 SQL,执行前先由后端确认

- sidecar 的危险 SQL 判定从字符串前缀/" WHERE " 匹配改为词法分析:去掉注释、
  字符串、引号标识符和 $$ 块;按语句逐条检查;WHERE 必须直接限定该
  UPDATE/DELETE(子查询里的 WHERE 不算);识别 WITH ... DELETE 与数据修改型
  CTE;DROP/TRUNCATE(含 ALTER ... DROP)需要确认;排除 FOR UPDATE、
  ON DELETE CASCADE、GRANT、MySQL TRUNCATE() 等非写入用法;MySQL/MariaDB
  与 PostgreSQL E'' 字符串按反斜杠转义处理,SQL Server 识别 [标识符]。
- 修复根因:执行前格式化会把 WHERE 换到新行,旧判定只认 " WHERE ",导致
  生产保护连接上所有带 WHERE 的 UPDATE/DELETE 都被拒绝。
- sidecar 新增不连库的 checkWriteProtection 方法;macOS 在生产保护连接执行写入
  前先问后端,需要确认时弹出原有确认框,避免批量执行到一半被拒。
- 补充 Rust 金样例测试与 Swift 预检测试。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(notes): 记录数据库插件化的签名、远程开发与 Windows 决策

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(plugins): 插件后端能力与函数协议 v2 宿主凭据服务

- 新增 level 3 能力 `backend` 1:插件自有的长驻进程,复用 serverProcess
  启动字段与安装审查(packagedBackend 等),需 `backend.launch` 权限和
  web 工具窗,不绑定 workspace(拒绝 ${workspaceStateDir})
- 新增权限 `credentials.store`,无 backend 时声明即无效
- launch plan 支持 `backend: true` 选择器,返回 `backend.hostServices`;
  `workspaceStateDirectory` 改为可选,仅在进程用到时必填
- 插件函数协议 v2:`lithe/host/credentials/{get,set,delete}`,Core 校验
  版本、授权与参数(key 字母表/长度、secret ≤16 KiB、拒绝未知字段),
  通过 `hostRequest` 事件交给宿主,宿主用新命令 `lsp.hostResponse` 应答;
  每会话最多 16 个未应答请求
- `lsp.startServer.hostServices` 传入授予的服务
- 契约 README、rust-core-api、schema、fixture 与黄金用例同步更新

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(notes): 记录插件后端、协议 v2 凭据与 Agent 工具走 lithe MCP 的决策

- 修正“Agent 到 app 里查找 lithe-db-mcp”的描述:它只被打包,从未被启动
- 记录后端每插件一个进程、宿主全局、授权由安装审查覆盖等取舍
- 凭据生命周期:停用/更新保留,卸载删除
- 按平台可执行文件不改契约;Agent 工具后续经现有 lithe MCP 暴露
- 待确认清空

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(agent): Claude 与 Codex 官方订阅支持多账号与手动切换 (#1457) (#1471)

* feat(agent): Claude 与 Codex 官方订阅支持多账号与手动切换 (#1457)

每个额外账号是官方 CLI 的独立配置目录(CLAUDE_CONFIG_DIR / CODEX_HOME),
Lithe 只保存名称和路径,不读取、复制或刷新任何凭据。

- Host:AgentLaunch 新增 claudeConfigDir / codexHome,只对各自的订阅模式生效且必须是绝对路径;
  Codex 的额度查询和已归档历史使用同一账号目录;Claude 已登录账号的邮箱和套餐通过 account 事件发给前端
- 设置页:Agent 管理里新增「订阅账号」卡片,显示邮箱、套餐、首选标记、5 小时/7 天用量条、重置时间、配速和「截至 …,本次未主动刷新」,用量更新逻辑放在 ⓘ 里
- 添加账号:在后台运行官方登录命令(claude auth login --claudeai / codex login),浏览器由 CLI 打开,不弹终端,可取消,5 分钟超时
- 切换:设为首选会重启该 Agent 的连接,回复中或等待授权时拒绝;额度耗尽不会自动换号
- 会话收藏、重命名、隐藏按「工作区 + Agent + 账号」分开保存,默认账号沿用原有标注
- 用量只是适配器最近一次推送的快照,按账号保存,Lithe 不调用 Anthropic 接口也不轮询
- 同步共享翻译、功能矩阵(agent-subscription-multi-account)和 Agent Note

* fix(agent): 技能列表与开关跟随首选 Codex 账号目录 (#1457)

* fix(agent): Claude 技能跟随首选账号目录,切换账号后刷新技能页,新账号名避免重复 (#1457)

* docs: plan Windows plugin parity with macOS (#1468)

* docs(notes): 规划 Java Support 独立分发与内置包迁移 (#1473)

* feat(macos): 宿主运行插件后端并通过 Keychain 提供凭据服务

- 新增 MacPluginBackendSessions:每个插件一个后端进程、应用全局共享,
  由插件网页首次调用 functions.* 时按需启动,以 ${stateDir} 为根目录和
  工作目录;插件停用时停止、重新启用后可再启动,包替换/卸载前停止且本次
  运行不再启动;设置变化时重启
- 后端会话以 hostServices 启动;LanguageServerRuntimeSession 处理
  hostRequest 事件并经新命令 lsp.hostResponse 应答(离开主线程发送)
- 新增 MacPluginCredentialStore:每个插件独立的 Keychain service,
  读取不弹密码框;卸载时随插件状态目录一起删除,停用/更新保留
- 网页桥接:functions.list/invoke 省略 instance 时调用本插件后端,
  不弹同意框(安装审查已覆盖);无后端的插件返回 plugin.web.forbidden
- 安装时校验后端打包可执行文件;hostCapabilities 声明 backend: [1]
- Swift 契约:launch request 的 workspaceStateDirectory 可为空、
  backendLaunchPlan、descriptor.declaresBackend、事件携带 method
- Core 修正:lsp.hostResponse 的字段按契约拼写为 hostRequestID,
  测试改为从线上 JSON 解码以覆盖字段名
- README 更新 macOS 宿主能力说明

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(macos): wait for backend host responses with a continuation instead of polling

The test-stability gate rejects real-time sleeps. The scripted Core now
resumes waiters as answers arrive, with a five-second watchdog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(plugins): list the Rust SDK for plugin backends in the contract

sdk/rust in lithe-plugin-docs implements plugin-function protocols 1 and 2
with the credentials host service for packaged plugin backends, and its
sample backend runs an end-to-end scenario against Core.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(database): read the proxy URL the macOS client sends

The client encodes DatabaseConnection.proxyURL as `proxyURL`, but the
sidecar's serde camelCase name was `proxyUrl`, so a connection's proxy
command was silently dropped and connections went direct. The field now
reads `proxyURL` and still accepts `proxyUrl`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(database): end the SSH tunnel client with the request on every path

SQL Server and MongoDB requests opened a tunnel and never stopped its ssh
client, so each such request left an orphaned ssh process holding the
local port after the sidecar exited. MySQL, PostgreSQL, SQLite, Redis,
and Nacos stopped it only on their normal path. SshTunnel now kills and
reaps the client when dropped, which covers early returns and every
adapter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(plugins): 插件网页桥接第 2 版加入文件对话框

插件后端是无界面的子进程,数据库插件导入导出、备份恢复和 DBX 导入都需要
用户选文件。桥接版本升为 2(lithe.version),新增 dialog.openFile 与
dialog.saveFile:对话框由宿主弹出并写明发起的插件,同一页面同时只开一个,
页面只拿到用户选中的绝对路径(取消为 null),读写交给插件后端;页面在对话框
打开期间关闭则拿不到结果。旧宿主返回 plugin.web.unknownMethod,页面据版本号
决定是否提供导入导出。

同步更新插件契约 README、网页内容 Agent Note 与跨平台功能矩阵。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(windows): 声明式插件宿主(契约 v1)——包存储、安装链、设置、运行计划与 Web 工具窗口 (#1424)

* docs(plugins): 提出 Windows 声明式插件宿主提案 Note

* feat(windows): 声明式插件宿主 v0 —— 包存储、启动校验与语言服务器启动接线

- 新增 src-tauri plugin_host 模块:包存储布局(app_local_data_dir/plugins 与
  plugin-state,bundled 从资源目录只读加载)、启动扫描(经
  plugins.declarative.validate 携带 hostCapabilities,拒绝包隔离并展示原因)、
  启动计划解析(packaged 入口拒绝 reparse point 与路径逃逸,runtime/
  systemCommand 走 PATH 与 LITHE_<TOOL>_PATH 约定)
- 共享 fixtures 验收:invalid-manifests.json 全部 154 个用例在 Windows 二进制
  内断言同一稳定错误码;合法样例按契约模式与 v0 能力门控模式分别断言
- 前端:resolve-editor-lsp-launch 在 Worker 扩展无服务器时回落契约插件启动;
  bootstrap 增加 declarative plugins 扫描步骤
- Note 转正为 implemented 并记录 M1 落地形状与 M2-M4 切分;矩阵
  declarative-plugin-contract Windows 状态随代码更新为 partial(pending)

* feat(windows): 声明式插件宿主 M2 —— 磁盘导入链、管理界面与版本探测

- plugin_host/install.rs:ZIP/目录→私有快照(拒绝 reparse point、路径逃逸、
  超限文件与恶意 ZIP 条目)→plugins.marketplace.installReview 全量审查→
  确认时摘要比对拒绝快照调包→staging 复验后激活;卸载、回滚、启用/停用
- launch.rs:runtime 启动按 versionArguments 探测实际版本,低于
  minimumVersion 拒绝启动;版本 token 解析容忍 v 前缀、引号与 go/java 输出
- 设置新增一级页"声明式插件(契约 v1)":安装审查卡(未认证发布者提示、
  权限与完整程序声明展开)、启用/停用/卸载/回滚,与 Worker 扩展分开列出;
  en-US 与 zh-CN 全套文案
- install_extension_from_url 等 Worker 非语言市场命令注册为显式占位错误
  (extensionStore.notAvailable),调用方得到可诊断失败而非命令不存在
- 矩阵 plugin-marketplace/plugin-extension-management/declarative-plugin-contract
  Windows 证据与 notes 随代码更新;Note 增补 M2 记录

* feat(windows): 声明式插件宿主 M3 —— 声明式设置、运行计划与契约 PHP 包

- 能力声明提升:languageServers [1,2]、settings [1,2],settings-v2 fixture
  由能力门控改为接受
- plugin_host/settings.rs:全局值(plugin-settings/<id>.json,默认值遗忘规则)
  与项目覆盖(工作区 .lithe/plugin-settings.json,空项清理、损坏拒写)双层
  存储;resolveSettings / storeSetting / workspaceConfiguration 三个命令;
  launch 请求现携带已存设置
- plugin_host/run_plans.rs:runPlan/testPlan 命令,展开 Core 模板后走共享
  run 链路(resolveRunLaunch → startRunProcess),进程归属复用 Worker 扩展
  的 ExtensionProcessOwner
- 设置编辑 UI:按声明 scope/effect 渲染控件,显示值来源徽标,immediate
  效果经 workspaceConfiguration 下推;show/hide 折叠进插件行
- Plugins/win/Official/PhpSupportContract:契约版 PHP bundled 包(API 2,
  launch kind runtime),随安装器资源分发;端到端测试覆盖 validate、
  runPlan、testPlan、resolveSettings。Worker 版 PHP 保留:其 composer
  scripts 动态运行动作在契约 v1 无等价能力,删除会造成功能退化,完整
  迁移推迟(Note 已记录)
- 矩阵 declarative-plugin-settings Windows partial、declarative-plugin-contract
  证据与 notes 更新;Note 增补 M3 记录

* feat(windows): 声明式插件宿主 M4 —— Web 工具窗口(ui 2)

- plugin_host/web.rs:lithe-plugin:// 自定义 scheme 只服务启用包内普通文件
  (拒 reparse point、路径逃逸、超 16MiB、非白名单扩展名),响应带
  CSP(default-src 'none'、拒 eval 与联网、frame-ancestors 'none')、
  nosniff、no-store、CORP
- window.lithe 桥 v0:document-start 注入冻结桥;context、
  ui.getState/setState(宿主持有状态,64KiB 上限)、workspace.openFile、
  事件泵;build.*/functions.* 在 Windows 构建系统能力接入前返回
  plugin.web.unknownMethod
- 页面生命周期命令:open(去重聚焦)/close;禁用卸载清状态
  (forget_plugin_state)
- 能力声明 ui 提升为 [1,2],web-panel fixture 转为被接受(门控测试同步)
- 管理区块新增 Web 工具窗口列表(打开/关闭),en-US/zh-CN 文案
- 矩阵 plugin-web-tool-windows Windows partial、declarative-plugin-contract
  evidence/notes 更新;Note 增补 M4 记录

* chore(windows): 清理 plugin_host/web.rs 未使用的 PageRequest 结构与 Deserialize 导入

* fix(windows): 修复插件宿主审查意见 —— 权限隔离、启动信封解包与端到端接线

P1(两项):
- 插件 WebView 脱离主窗口通配 capability:main.json 收窄为 main/workspace-*,
  新增 plugin-web capability(core:event 最小集,无 fs/http/shell/dialog);
  桥身份改由调用 webview label 反解(bridge_identity),核对插件启用、
  窗口声明与归属,伪造参数/跨插件/非插件窗口一律 plugin.web.forbidden
- launch 解包 Core 响应信封后再解析(outcome["plan"]),新增走真实
  Core 命令的回归测试(此前单测绕过了信封导致该路径必然失败)

P2:
- 设置编辑器按 ID 从宿主 catalog 取完整 manifest(新增
  declarative_plugins_manifest 命令),resolve/workspaceConfiguration 不再
  传 ID 占位清单;加载与解析错误保持可见
- 运行入口接通:新增 declarative_plugins_language_owner 归属查询,run
  动作发现接入 useRunActionDiscovery(source: declarative),运行菜单
  直接分发;删除会漂移的前端目录缓存
- 停用/卸载/回滚前关闭插件全部 Web 窗口并清状态;scheme 文件服务只服务
  enabled 包
- workspace.openFile 接前端监听(plugin-web-open-file.ts):限工作区根内
  路径,走 handleFileSelect(带 line/column)
- 版本探测宿主只跑 versionArguments,判断委托 Core
  checkRuntimeVersion(共享 runtime-versions 语义),删除自建解析器

* fix(windows): 修复第二轮 review 意见 —— IPC 命令隔离与端到端接线收口

P0:
- invoke_handler 包装插件页门控:label 为 plugin-web-* 的调用只允许
  declarative_plugins_web_bridge_request(改为直调的普通函数,消费原始
  Invoke,绕过宏推断问题),其余应用命令(run_start_process 等进程/文件/
  HTTP 面)一律 resolver.reject——插件页面无法再通过原始 Tauri IPC 调用
  宿主命令
- generate_handler 宏在非直接实参位置无法推断 R:用
  Box<InvokeHandler<Wry>> 在绑定处钉定(本地最小复现 crate 验证)

P2:
- initializePluginWebOpenFileListener 真正接入 bootstrap(此前只有定义)
- immediate 设置:编辑器取 Core 展开的 configuration 后经
  lsp.updateWorkspaceConfiguration 下推到运行中的 LSP 会话
- 停用/卸载时 Rust 发 declarative-plugin-lifecycle 事件,前端进程 owner
  停止该插件全部声明式运行会话
- test plan 产品入口:declares_tests 标记进入 catalog,运行菜单的声明式
  动作按插件测试模板走 testPlan(v1 传当前文件供项目标记判定)
- 同版本重装激活失败时备份/恢复原版本目录,不再出现安装记录指向缺失
  字节的隔离状态(新增恢复路径测试)

P3:
- 共享契约 README 更新 Windows ui: [1,2] 状态与桥 v0 方法范围

* fix(windows): close declarative plugin review gaps

* fix(windows): address plugin host review gaps

* fix(windows): harden declarative plugin page and probe boundaries

* fix(windows): drain declarative plugin owners before package changes

Preserve plugin identity and cancel in-flight starts; enforce launch requirements, scope web pages and events to their owners, and expose declarative UI contributions. Add bounded regression coverage and document the remaining parity work.

* test(windows): isolate plugin host in terminal lifecycle fixture

Keep the real activity rail and terminal docking coverage while stubbing declarative plugin state and native window launch at the feature boundary. This prevents the fixture's narrow pane mocks from being loaded by the unrelated workspace services.

* feat(macos): Agent 对话显示工具图片缩略图、点击放大,并将后台任务通知显示为状态行 (#1462) (#1472)

* feat(macos): Agent 对话显示工具图片缩略图、点击放大,并将后台任务通知显示为状态行 (#1462)

* feat(macos): 图片放大支持缩放,折叠过程显示缩略图,适配更多 Claude Code 特殊消息格式 (#1462)

* fix(macos): 导航栏不再把 Claude Code 特殊消息当作提问,图片查看器不再让转录重绘 (#1462)

* fix(macos): 修复 Agent 图片显示评审问题:id 去重、哈希、焦点、缓存与解析边界 (#1472)

- 图片 id 去重,避免 ForEach 重复 id
- 指纹改用 SHA-256,避免主线程逐字节循环
- 用户消息解析结果按消息缓存
- 查看器 ←/→ 仅在持有焦点时翻页,拖动限制在画面边缘内
- 只移除消息首尾的模型专用块,不吞用户中间引用的标签
- 图片按原文位置排序,超出上限的引用显示 +N
- read 只对存在的文件生成缩略图,解码失败显示占位
- 缓存限制成本,键含修改时间,解码任务随行取消
- 内联数据须能被 ImageIO 识别,否则退回文字条目

* feat(macos): 后台任务通知并入后续过程区,恢复 Claude 会话时补全压缩前的完整历史 (#1472)

- 成功的后台任务通知不再单独成行,进入随后一轮的折叠“思考过程”;失败、被终止或后面没有过程的通知仍显示
- Claude 的英文 shell 任务摘要按界面语言显示(后台命令已完成:…)
- Rust 宿主在 session/load 前只读取会话文件中最后一个压缩点之前的记录,转成回放更新,压缩前的用户消息、回复、思考和工具调用都能查看
- 读取范围:只读 projects/*/<会话 id>.jsonl,按所选账号目录解析,大小和条数有上限
- 新增翻译放在 shared/i18n,更新功能矩阵与 Agent Note

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* perf(macos): 后台通知判断复用用户消息解析缓存

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(macos): 回放时相邻的用户消息不再合并成一条

连续的用户消息(例如后台通知后紧跟用户输入)在回放时被拼成一个气泡,导致通知标记无法识别而显示原文。
按上游 messageId 区分用户消息;压缩前的历史也带上记录 uuid。

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(agent): 恢复 Claude Desktop 开始的会话时显示可读历史

- 宿主把 mcp__ccd_turn__wrap_up 改写成 Agent 回复,吞掉其后续 tool_call_update
- 宿主把 mcp__ccd_turn__update_plan(整表/增量)改写成完整 ACP plan 更新
- 压缩前文回放补上对话中途排队的用户消息(queued_command),工具调用带上 name
- 历史回放时计划快照作为清单显示在折叠过程之间,导出为任务列表,不计入消息数
- 折叠的过程标题附工具摘要(如运行了 N 条命令)

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>

* feat(plugins): list the database plugin and move the built-in module's data into it

- OfficialPluginCatalog lists dev.lithe.plugin.database as a publisher
  package downloaded from the marketplace; language-only fields move into
  an optional Entry.language, so a non-language plugin needs none.
- MacDatabasePluginMigration moves the former module's connections,
  folders, SQL history, and forever-kept passwords into the plugin's
  ${stateDir} and credentials once, before its backend first starts
  (MacPluginBackendSessions gains a prepareState hook). The old data stays
  for older Lithe versions; the plugin's own state always wins.
- Workbench notifications can carry one action and then stay until used.
  People with saved connections and no database plugin get one prompt
  with an "Open Marketplace" action.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor: remove the built-in database module; the database is a plugin now

Lithe no longer ships a database module. The official plugin
dev.lithe.plugin.database (Lithe-IDEA/lithe-plugin-database) replaces it,
and the earlier commit moves saved connections into it.

- macOS: delete LitheDatabaseModule, the database views, adapters,
  recovery store, coordinator, sidecar locator, brand icons, dbx fixtures,
  and the database tool windows, editor tabs, theme tokens, console gutter
  and AppModel branches. Generic tests that used the database as a sample
  now use other modules. Dropdown/context-menu parameters only the database
  used are gone. Idle sleep keeps a visible module window open; only
  shutdown closes it.
- Rust: delete lithe-db-sidecar and lithe-db-mcp.
- Windows: delete features/database and its sidecar packaging, the
  databases extension contribution, and every database branch; openBuffer
  loses its two database-only parameters. No plugin adaptation yet.
- CI and scripts: delete the database workflow, validation docker setup
  and sidecar/MCP build and smoke scripts; packaging, preview, verifiers,
  CI change classification and lane reuse drop the database.
- i18n: drop strings only the removed UIs used and regenerate.
- Feature matrix, Agent Notes, README, docs and Skill: the database is an
  official plugin; the plugin note is implemented, the multi-schema tree
  note is archived.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(plugins): ship Database as a Lithe Store community plugin

Lithe's official signing path has never released a plugin and its v2
private key is out of reach, so the Database plugin is a community
plugin (io.github.lithe-idea.database, unsigned) listed in Lithe Store
like the other seven.

- OfficialPluginCatalog no longer lists the database plugin; the optional
  Entry.language refactor that only it needed is reverted.
- An unsigned plugin ID proves nothing, so MacDatabasePluginMigration now
  moves the old connections and passwords only into a copy installed from
  Lithe Store whose index entry names Lithe-IDEA/lithe-plugin-database.
  A copy from disk or another source gets nothing and leaves no marker,
  so installing from Lithe Store later still migrates. The backend
  sessions' prepareState hook receives the installation record for this.
- Feature matrix, README and the Agent Note describe the community plugin,
  why official signing is deferred, and the new trust boundary.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(database): record the macOS acceptance of the plugin migration

The migration from the former built-in module was accepted on a macOS
development-identity build: the one-time notice, installing Database 0.1.0
from Lithe Store, and the connections, folders, history, and passwords
arriving in the plugin as the Agent Note describes. The matrix marks the
migration row verified on macOS; the other database rows stay pending.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(agent): 恢复压缩过的 Claude 会话时保留压缩前用户消息里的截图 (#1479)

* fix(agent): 恢复压缩过的 Claude 会话时保留压缩前用户消息里的截图

* fix(agent): 压缩前历史回放的截图超过客户端大小上限时不再发送

* feat(agent): 兼容 Claude Desktop 会话独有机制,Agent 面板以卡片呈现 (#1480)

* feat(agent): 兼容 Claude Desktop 会话独有机制,Agent 面板以卡片呈现

- agent host 识别 Desktop 工具(章节、建议回复、任务、PR、目录、可视化),给出可读标题并在 _meta.lithe.claudeDesktop 中附带卡片
- claude.ai UUID 连接器显示为 Connector: <工具>
- macOS 面板渲染卡片:建议回复跟在回合总结后,卡片操作只填入输入框
- 可视化在禁网、禁导航的非持久 WKWebView 中渲染
- Desktop 事件包装与跨会话通知按上下文显示,不算用户发言
- 共享 LitheChipFlowLayout,更新 i18n、契约、Agent Note 与功能矩阵

* fix(agent): 可视化页面的 sendPrompt 只在用户点击或按键之后才填入输入框

* fix(agent): 按 review 修复可视化外链出口、任务失败记录丢失和压缩历史输入被截断

---------

Co-authored-by: Xiaoyumuxi <23722032@bjtu.edu.cn>
Co-authored-by: muchen <145200703+Mucheen@users.noreply.github.com>
Co-authored-by: 十二翼堕落天使 <61737634+icefery@users.noreply.github.com>
Co-authored-by: Lichenkang <2188718831@qq.com>
Co-authored-by: arkleselect <166632698+arkleselect@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@ghfind-review ghfind-review Bot added the review: high ghfind author score; see https://ghfind.com label Oct 25, 2026
@1lck
1lck merged commit 3714bd9 into main Oct 25, 2026
12 of 16 checks passed

This branch was successfully deployed

1 active deployment
github-pages — a9264ca2 Deployed Oct 25, 2026 by 1lck via deploy #411
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review: high ghfind author score; see https://ghfind.com

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants