diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 712aa7f47..fe9f270c0 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -41,9 +41,6 @@ jobs:
- platform: windows-2022
target: x86_64-pc-windows-msvc
name: Windows-x64
- - platform: ubuntu-22.04
- target: x86_64-unknown-linux-gnu
- name: Linux-x64
runs-on: ${{ matrix.platform }}
@@ -63,12 +60,6 @@ jobs:
with:
version: 9
- - name: Install Linux dependencies
- if: matrix.platform == 'ubuntu-22.04'
- run: |
- sudo apt-get update
- sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libssl-dev pkg-config libasound2-dev libxdo-dev
-
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
@@ -160,30 +151,6 @@ jobs:
security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
- - name: Build Tauri app (Linux)
- if: matrix.platform == 'ubuntu-22.04'
- uses: tauri-apps/tauri-action@v0
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- # 禁用 LTO 加速编译(正式发布可改为 thin)
- CARGO_PROFILE_RELEASE_LTO: "off"
- # 增加并行编译单元
- CARGO_PROFILE_RELEASE_CODEGEN_UNITS: 32
- CARGO_INCREMENTAL: 0
- SCCACHE_GHA_ENABLED: "true"
- RUSTC_WRAPPER: sccache
- OPENSSL_NO_VENDOR: "1"
- with:
- tauriScript: npx tauri
- projectPath: src-tauri
- tagName: ${{ github.event.inputs.version || github.ref_name }}
- releaseName: "Lime ${{ github.event.inputs.version || github.ref_name }}"
- releaseBody: ${{ env.RELEASE_BODY }}
- releaseDraft: false
- prerelease: false
- # 默认不启用 voice feature(包含 whisper-rs,编译很慢)
- args: --target ${{ matrix.target }}
-
- name: Build Tauri app (Windows offline)
if: matrix.platform == 'windows-2022'
uses: tauri-apps/tauri-action@v0
diff --git a/.gitignore b/.gitignore
index 509c9acc2..6cd66731d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -65,9 +65,11 @@ openspec
# Build artifacts (alternate cargo target dirs)
src-tauri/target*/
+src-tauri/.codex*
logo-lime.png
lime-claw.png
lime.db
+.codex-*
\ No newline at end of file
diff --git a/README.md b/README.md
index adc71c1fa..a10d83c34 100644
--- a/README.md
+++ b/README.md
@@ -1,25 +1,54 @@
+

+
# Lime
-**以创作为中心的本地优先 AI Agent 交互工作台**
+### 青柠一下,灵感即来
-一句话:用 Skills 组织经验与流程,用 MCP 接入标准能力,用 Claw 渠道把 Agent 带到飞书、Telegram 等入口,让创作、研究、执行与交付在同一个工作环境里闭合。
+**从一句想法,到成稿、成图、成片、成事**
+
+本地优先的 AI Agent 创作工作台
---
+## 界面预览
+
+Lime 把创作工作台、任务会话与 Provider 管理整合在同一个本地优先桌面应用里,下面是三个核心界面的快速预览:
+
+### 工作台首页
+
+
+
+在同一个 Workspace 中组织任务、技能、自动化、浏览器协助与对话输入,让一句想法继续推进为可执行结果。
+
+### 任务与会话协作
+
+
+
+围绕单个任务持续补充上下文、追踪执行轨迹,并在同一界面中完成对话推进、模型切换与结果沉淀。
+
+### Provider 与凭证管理
+
+
+
+统一管理 API Key、Connect、语音服务与 OAuth 凭证,并在同一处完成启用状态、模型配置与连接测试。
+
+---
+
## 这是什么
-Lime 是一个基于 Tauri 的桌面应用,面向创作者、内容团队与轻知识工作者。它把 Workspace、Agent、Skills、MCP、Claw 渠道和 Artifact 交付整合到同一个桌面环境里,让工作从输入需求直接走向可沉淀、可复用、可继续执行的结果。
+Lime 是一个基于 Tauri 的桌面应用,面向创作者、内容团队与轻知识工作者。它把 Workspace、Agent、Skills、MCP、Claw 渠道和 Artifact 交付整合到同一个桌面环境里,让一句想法可以继续推进为成稿、成图、成片,并最终走向可执行、可协作、可沉淀的结果。
-你可以在一个地方完成:
+你可以在一个地方完成从想法到交付的整条链路:
-- 在项目里与 Agent 协作
-- 生成和编辑文档、脚本、图文方案等产物
-- 使用浏览器、终端、MCP 和插件扩展执行空间
-- 让结果沉淀为可复用的记忆、风格和版本资产
+- 成稿:生成和编辑文档、脚本、提纲、长文等内容产物
+- 成图:产出图文方案、海报草稿与视觉素材
+- 成片:围绕视频脚本、分镜、素材与创作流程持续协作
+- 成事:通过 Workspace、MCP、Claw 和插件把结果继续执行、协作与交付
+- 沉淀:让对话、版本、记忆、风格和项目资产可复用、可继续
---
@@ -126,6 +155,7 @@ brew install --cask lime
从 [Releases](https://github.com/aiclientproxy/lime/releases) 下载对应平台安装包。
+- 当前仅提供 macOS 与 Windows 发布包,Linux 桌面端已暂停支持
- Windows 用户优先下载 `Lime_*_x64-offline-setup.exe`(NSIS 离线安装器,内置 WebView2,安装更完整)
- 如果只想下载更小的安装器,且当前网络可稳定访问微软下载源,再选择 `Lime_*_x64-online-setup.exe`
- 如被 SmartScreen 拦截,属于未签名或签名信誉不足的 Windows 常见提示,不代表安装包必然损坏
@@ -161,3 +191,15 @@ npm run tauri build
本项目仅供学习研究使用,用户需自行承担使用风险。
本项目不直接提供 AI 模型服务,模型能力由第三方提供商提供。
+
+---
+
+
+
+### 微信交流
+
+

+
+扫码加微信,备注 `Lime`,拉你进群讨论。
+
+
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index cb8c5acb7..af962eb44 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,26 +1,32 @@
-## Lime v0.90.0
+## Lime v0.91.0
### ✨ 主要更新
-- **Aster Agent 聊天链路完成收口**:前端统一走 `useAgentChatUnified -> useAsterAgentChat`,移除旧 `useAgentChat` / `agentStore` compat 路径;会话恢复、流式消息、工具状态与 topic snapshot 改为模块化协作
-- **Agent 会话与时间线持久化增强**:Aster session store、agent timeline DAO、数据库 schema 与迁移链路继续补强,聊天历史、统计与项目上下文构建更稳定
-- **托盘模型快捷切换上线**:新增全局托盘模型同步、主题感知的快捷模型组与模型选择联动,聊天页、侧边栏和模型选择器体验同步更新
-- **调试与性能诊断能力补齐**:新增前端 debug 上报 API、Tauri profiling 启动脚本、Perfetto / Tokio Console 支持与配套文档,运行时排障更直接
-- **OpenClaw 与运行时集成继续完善**:Browser Runtime、OpenClaw 页面与后端服务、Dev Bridge 查询和技能服务继续收口,提升桌面侧运行时协同
-- **品牌图标与托盘资产刷新**:应用图标、托盘状态图与启动页、侧边栏视觉资源同步更新
+- **Aster 运行时队列正式接入 Lime**:桌面端补齐 runtime queue service、Aster state support 与 session store 协作,Agent 会话恢复、排队执行和 runtime item 映射进一步收口
+- **Agent 聊天输入链路继续统一**:输入栏、空状态、图片附件、模型选择与会话 hooks 继续围绕 Aster 聊天主链路整理,减少旧 compat 路径分叉
+- **模型能力与视觉提示增强**:新增模型能力徽章、视觉能力提示与 provider model list 整理,模型选择和多模态提示更直接
+- **Skills / Social Post 执行链路补齐**:新增技能执行运行时与社交内容技能集成,Aster Skills 在 Lime 内的发现、执行与同步更完整
+- **数据库与治理清理继续推进**:移除旧 `unified_chat` / `tool_hooks` / `three stage workflow` 相关残留,统一到现役 Aster Agent、Memory 与 Workspace 路径
### ⚠️ 兼容性说明
-- Agent 聊天现役事实源已统一到 Aster 后端;旧 `useAgentChat` / `agentStore` 已移除,后续新功能不再沿 compat 路径扩展
-- Profiling 诊断能力仅在显式开发启动流程下启用;release / 生产构建默认忽略这些调试开关
+- Aster 相关聊天、会话与时间线事实源进一步集中到新的 runtime / session store 路径,旧 compat API 不再建议继续扩展
+- 模型可见性与能力展示依赖新的 provider model 推断逻辑,历史仅按名称匹配的前端分支需要逐步淘汰
+
+### 🔗 依赖同步
+
+- `src-tauri/Cargo.toml` 中的 `aster-rust` 依赖固定到 `v0.19.0`
### 🧪 测试
-- 发布前执行:`cargo test`、`cargo fmt --all`、`cargo clippy`、`npm run lint`
+- 发布前执行:`cd src-tauri && cargo test`
+- 发布前执行:`cd src-tauri && cargo fmt --all --check`
+- 发布前执行:`cd src-tauri && cargo clippy`
+- 发布前执行:`npm run lint`
### 📝 文档
-- 更新 Agent / Aster 集成、治理与 profiling 相关文档,补充前端诊断与发布说明
+- 更新 Aster 集成、治理、Skills 与发布相关文档,补充当前现役架构与发布说明
### 📦 Windows 下载说明
@@ -30,4 +36,4 @@
---
-**完整变更**: v0.89.1...v0.90.0
+**完整变更**: v0.90.0...v0.91.0
diff --git a/docs/aiprompts/aster-integration.md b/docs/aiprompts/aster-integration.md
index 36cf3e260..154aca4c1 100644
--- a/docs/aiprompts/aster-integration.md
+++ b/docs/aiprompts/aster-integration.md
@@ -7,6 +7,8 @@ Lime 已完整集成 aster-rust 框架,包括凭证池桥接。
## 当前事实源
- `Aster thread / turn / item runtime` 是运行态事实源。
+- Aster shared runtime store 与全局 session store 必须在 Lime bootstrap 启动期显式初始化;启动恢复时由 runtime support 统一完成 legacy queue 迁移与 queued session 枚举。
+- 运行时命令与 service 只允许读取已准备好的 shared store / shared queue service,不再在热路径偷偷 fallback 到默认路径。
- Lime 只负责事件映射、数据库投影和 UI 派生,不再伪造核心 runtime item。
- 会话删除统一收口到存储边界;命令层和 Dev Bridge 不应直接调用 `AgentDao::delete_session`。
- 需要恢复运行态时,优先从 Aster runtime 恢复,再映射到 Lime timeline。
diff --git a/docs/aiprompts/commands.md b/docs/aiprompts/commands.md
index 747f70128..3a231fdc7 100644
--- a/docs/aiprompts/commands.md
+++ b/docs/aiprompts/commands.md
@@ -23,9 +23,12 @@ Tauri 命令是前端与 Rust 后端通信的边界,但前端业务代码**不
## 当前事实源
-- 聊天主命令:`chat_*`
+- Agent / Codex 主命令:`agent_runtime_*`
+- 运行态摘要主链:Aster `runtime_status` item -> timeline `turn_summary`
+- `chat_*` 已停止注册,且不再纳入 `commands::mod` 编译图;旧 General / Creator / 历史桥接如仍需恢复,必须显式走新的 compat 评审
- 旧 `general_chat_*` 前端 compat 网关与 Rust 命令已删除
-- 当前剩余治理重点:统计、记忆等旁路仍在读取 `general_chat_*` 历史表
+- `Tauri runtime_status` 事件只保留前端瞬时状态用途,不再作为 timeline 事实源
+- 当前剩余治理重点:统计、记忆等旁路继续按 `runtime context` 与 `durable knowledge` 分层收口
## 治理案例:记忆系统
@@ -45,7 +48,8 @@ Tauri 命令是前端与 Rust 后端通信的边界,但前端业务代码**不
4. 如果存在旧命令又无任何调用,就直接删掉命令注册、桥接和 mock,不要继续保留空兼容壳
同理,对话系统也不应该重新引回已经删除的 `general_chat_*` 命令;
-后续如需扩展聊天能力,应继续收敛到 `chat_*` 与对应网关。
+后续如需扩展 Agent / Codex 工作流,应继续收敛到 `agent_runtime_*` 与对应网关;
+`chat_*` 只允许作为 dead-candidate 参考,不应重新回到 `commands::mod` 或 `generate_handler!`。
## 目录结构
diff --git a/docs/aiprompts/content-creator.md b/docs/aiprompts/content-creator.md
index 14fbe2daf..567d615cc 100644
--- a/docs/aiprompts/content-creator.md
+++ b/docs/aiprompts/content-creator.md
@@ -11,7 +11,7 @@
↓
用户发送消息 → useAgentChatUnified.sendMessage()
↓
-统一收口到 useAsterAgentChat / agent_runtime_*
+统一收口到 useAgentChatUnified / useAsterAgentChat / agent_runtime_*
↓
第一条消息时注入 systemPrompt → 发送到 Aster Agent
↓
@@ -40,7 +40,7 @@ src/components/
│ └── parser.ts # A2UI 和 write_file 解析器
├── agent/chat/
│ ├── hooks/
-│ │ ├── index.ts # useAgentChatUnified 统一入口
+│ │ ├── index.ts # Agent chat hooks 导出入口
│ │ └── useAsterAgentChat.ts # Agent 聊天主 Hook
│ ├── components/
│ │ ├── StreamingRenderer.tsx # 流式渲染(解析 write_file)
@@ -119,7 +119,7 @@ export function parseAIResponse(
- `write_file` - 完整的文件写入
- `pending_write_file` - 流式传输中的文件写入
-### 3. useAgentChatUnified / useAsterAgentChat - systemPrompt 注入
+### 3. useAsterAgentChat - systemPrompt 注入
在发送第一条消息时注入 systemPrompt,并通过现役 runtime adapter 提交到 `agent_runtime_*`。
diff --git a/docs/aiprompts/governance.md b/docs/aiprompts/governance.md
index 4fc5a637a..c92d99bfc 100644
--- a/docs/aiprompts/governance.md
+++ b/docs/aiprompts/governance.md
@@ -177,7 +177,7 @@ npm run governance:legacy-report
例如:
-> 聊天能力后续统一收敛到 `useUnifiedChat + chat_* + ChatDao`。
+> 聊天能力后续统一收敛到 `useAgentChatUnified -> useAsterAgentChat -> agent_runtime_* + lime_core::database::agent_session_repository`。
### 第三步:优先做减法
@@ -207,8 +207,8 @@ npm run governance:legacy-report
以聊天系统为例,遇到新旧并存时,必须同时问这几个问题:
-- 前端唯一入口是不是 `useAgentChatUnified` / `useAsterAgentChat`,还是 `useChat` / `useAgentChat` 还在继续长逻辑?
-- Rust 唯一入口是不是 `chat_*`,还是 `general_chat_*` / `agent_*` / `aster_agent_*` 还在平行演进?
+- 前端唯一入口是不是 `useAgentChatUnified -> useAsterAgentChat`,还是 `useChat` / `useAgentChat` / `useUnifiedChat` 还在继续长逻辑?
+- Rust 唯一入口是不是 `agent_runtime_*`,还是 `chat_*` / `general_chat_*` / `agent_*` / `aster_agent_*` 还在平行演进?
- 数据事实源是不是同一组表 / 同一套 Repository,还是还在同时写 `agent_*` 与 `general_chat_*`?
- 统计、记忆等旁路是不是已经切到新路径,还是还在读旧表?
diff --git a/docs/aiprompts/hooks.md b/docs/aiprompts/hooks.md
index b86ef5c17..02786951b 100644
--- a/docs/aiprompts/hooks.md
+++ b/docs/aiprompts/hooks.md
@@ -9,7 +9,6 @@
```
src/hooks/
├── index.ts # 导出入口
-├── useUnifiedChat.ts # 统一对话 Hook(新)
├── useProviderPool.ts # 凭证池管理
├── useOAuthCredentials.ts # OAuth 凭证
├── useFlowEvents.ts # 流量事件
@@ -22,69 +21,24 @@ src/hooks/
- 新的前端能力优先落在 `src/lib/api/*`,再由 Hook 或组件消费。
- 历史 `useTauri.ts` 兼容聚合层已删除,不要重新引入新的“大一统 API Hook”。
-- 旧聊天链路优先迁移到 `@/hooks/useUnifiedChat`,不要继续扩散 `useChat` / compat Hook。
+- Agent 工作台统一走 `src/components/agent/chat/hooks/index.ts` 暴露的 `useAgentChatUnified`,底层实现委托 `useAsterAgentChat`。
+- 历史 `@/hooks/useUnifiedChat` 与 `src/lib/api/unified-chat.ts` 已删除,不要重建 compat Hook / API。
## 核心 Hooks
-### useUnifiedChat(统一对话)
+### useAgentChatUnified / useAsterAgentChat(现役 Agent 对话)
-统一的对话 Hook,支持三种模式:Agent、General、Creator。
+现役 Agent / Codex 工作台事实源:
-```typescript
-import { useUnifiedChat } from "@/hooks/useUnifiedChat";
-
-// Agent 模式 - 支持工具调用
-const { messages, sendMessage, stopGeneration } = useUnifiedChat({
- mode: "agent",
- providerType: "claude",
- model: "claude-sonnet-4-20250514",
-});
-
-// Creator 模式 - 支持画布输出
-const creatorChat = useUnifiedChat({
- mode: "creator",
- systemPrompt: "你是内容创作助手...",
- harnessConfig: {
- theme: "social-media",
- artifactMode: "version-chain",
- },
- onHarnessEvent: (event) => {
- /* 接收阶段推进、产物创建等语义事件 */
- },
- onArtifactUpdate: (artifact) => {
- /* 接收产物快照 */
- },
- onCanvasUpdate: (path, content) => {
- /* 更新画布 */
- },
- onWriteFile: (content, fileName) => {
- /* 文件写入 */
- },
-});
-
-// General 模式 - 纯文本对话
-const generalChat = useUnifiedChat({ mode: "general" });
-```
-
-**返回值**:
-
-- `session` - 当前会话
-- `messages` - 消息列表
-- `isLoading` / `isSending` - 状态
-- `createSession()` / `loadSession()` / `deleteSession()` - 会话管理
-- `sendMessage()` / `stopGeneration()` - 消息操作
-- `configureProvider()` - Provider 配置
-
-**补充说明**:
-
-- Creator 模式现在支持 `harnessConfig`、`onHarnessEvent`、`onArtifactUpdate`
-- 社媒内容推荐把 `` 结果投影为“版本链产物”,而不是只按文件名覆盖
+- `useAgentChatUnified -> useAsterAgentChat -> useAgentContext / useAgentSession / useAgentTools / useAgentStream`
+- 命令主链:`agent_runtime_submit_turn -> runtime items(plan / runtime_status / artifact / tool / action) -> action_required -> respond_action`
+- 适用场景:Agent 工作台、任务执行、工具审批、timeline 渲染
**相关文件**:
-- 类型定义:`src/types/chat.ts`
-- API 封装:`src/lib/api/unified-chat.ts`
-- 架构文档:`docs/prd/chat-architecture-redesign.md`
+- 统一入口:`src/components/agent/chat/hooks/index.ts`
+- Hook 实现:`src/components/agent/chat/hooks/useAsterAgentChat.ts`
+- API 封装:`src/lib/api/agentRuntime.ts`
### useProviderPool
diff --git a/docs/aiprompts/services.md b/docs/aiprompts/services.md
index 22fcdac6b..b2d33045f 100644
--- a/docs/aiprompts/services.md
+++ b/docs/aiprompts/services.md
@@ -22,7 +22,7 @@ src-tauri/src/services/
## 核心服务
> 注意:`general_chat/` 兼容壳已删除。
-> 新功能与新治理都应直接落到 unified chat / `chat_*` 体系,不要重新引回旧入口。
+> 新功能与新治理都应直接落到 `agent_runtime_*` 与现役 `agent/chat` 体系,不要重新引回旧入口。
> `ProviderPoolService::select_credential_with_fallback_legacy` 也已删除,凭证选择统一走现役 `select_credential_with_fallback`。
### ProviderPoolService
diff --git a/docs/content/01.introduction/2.installation.md b/docs/content/01.introduction/2.installation.md
index 9c1a5b8c5..f64ab0c8f 100644
--- a/docs/content/01.introduction/2.installation.md
+++ b/docs/content/01.introduction/2.installation.md
@@ -20,6 +20,10 @@ navigation:
[下载 Lime](https://github.com/aiclientproxy/lime/releases)
+::alert{type="warning"}
+Lime 当前仅提供 macOS 与 Windows 桌面端安装包,Linux 版本已暂停支持,不再发布 `.deb` 或 `AppImage`。
+::
+
### 安装包
| 平台 | 文件名 | 说明 |
diff --git a/docs/content/06.development/3.building.md b/docs/content/06.development/3.building.md
index 2642f0e62..4039f8201 100644
--- a/docs/content/06.development/3.building.md
+++ b/docs/content/06.development/3.building.md
@@ -11,6 +11,10 @@ navigation:
## 本地开发
+::alert{type="warning"}
+Lime 桌面端当前仅支持 macOS 与 Windows,本页不再提供 Linux 打包与发布说明。
+::
+
### 环境准备
1. **安装 Node.js**
@@ -32,7 +36,7 @@ npm install -g pnpm
3. **安装 Rust**
```bash
-# macOS/Linux
+# macOS
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Windows
@@ -52,12 +56,6 @@ xcode-select --install
- 安装 Visual Studio Build Tools
- 安装 WebView2(开发模式必需;对外分发时默认推荐在线小包,离线或受限网络环境再提供离线大包)
-**Linux:**
-
-```bash
-sudo apt install libwebkit2gtk-4.1-dev build-essential curl wget file libssl-dev libayatana-appindicator3-dev librsvg2-dev
-```
-
### 启动开发
```bash
@@ -121,7 +119,6 @@ pnpm tauri build --debug
| ------- | --------------------------------------- |
| macOS | `src-tauri/target/release/bundle/dmg/` |
| Windows | `src-tauri/target/release/bundle/nsis/` |
-| Linux | `src-tauri/target/release/bundle/deb/` |
### 跨平台构建
@@ -150,13 +147,6 @@ pnpm tauri build --target x86_64-pc-windows-msvc --config src-tauri/tauri.window
> 建议默认对外分发在线小包;只有内网、离线或受限网络环境,再提供离线大包。
-#### Linux 构建
-
-```bash
-# 构建 deb 包
-pnpm tauri build --target x86_64-unknown-linux-gnu
-```
-
## 版本管理
### 更新版本号
@@ -208,7 +198,6 @@ git push origin v1.0.1
| macOS | arm64 | macos-latest |
| macOS | x64 | macos-13 |
| Windows | x64 | windows-2022 |
-| Linux | x64 | ubuntu-latest |
## 调试
@@ -229,7 +218,6 @@ RUST_LOG=debug pnpm tauri dev
| ------- | -------------------------------- |
| macOS | `~/Library/Logs/Lime/` |
| Windows | `%APPDATA%\Lime\logs\` |
-| Linux | `~/.local/share/lime/logs/` |
## 常见问题
diff --git a/docs/images/067c7d64-e116-4a30-b533-748873166f37.png b/docs/images/067c7d64-e116-4a30-b533-748873166f37.png
deleted file mode 100644
index 15e989ccd..000000000
Binary files a/docs/images/067c7d64-e116-4a30-b533-748873166f37.png and /dev/null differ
diff --git a/docs/images/151b4355-821c-4bda-a731-c4367b6b8716.png b/docs/images/151b4355-821c-4bda-a731-c4367b6b8716.png
deleted file mode 100644
index d38507ddc..000000000
Binary files a/docs/images/151b4355-821c-4bda-a731-c4367b6b8716.png and /dev/null differ
diff --git a/docs/images/25eb018a-5be2-4f82-ba22-e68f39160cac.png b/docs/images/25eb018a-5be2-4f82-ba22-e68f39160cac.png
deleted file mode 100644
index 8fe5b9470..000000000
Binary files a/docs/images/25eb018a-5be2-4f82-ba22-e68f39160cac.png and /dev/null differ
diff --git a/docs/images/943663ed-b17c-4b32-a74c-c0243ffb3dea.png b/docs/images/943663ed-b17c-4b32-a74c-c0243ffb3dea.png
deleted file mode 100644
index 71b933c8b..000000000
Binary files a/docs/images/943663ed-b17c-4b32-a74c-c0243ffb3dea.png and /dev/null differ
diff --git a/docs/images/aee62eb5-3aeb-4454-b14d-24b1d5f9a0fe.png b/docs/images/aee62eb5-3aeb-4454-b14d-24b1d5f9a0fe.png
deleted file mode 100644
index 98fb49fd3..000000000
Binary files a/docs/images/aee62eb5-3aeb-4454-b14d-24b1d5f9a0fe.png and /dev/null differ
diff --git a/docs/images/c7d8236b-ea6c-4496-ada5-288cd0a01738.png b/docs/images/c7d8236b-ea6c-4496-ada5-288cd0a01738.png
deleted file mode 100644
index 20f6d97e5..000000000
Binary files a/docs/images/c7d8236b-ea6c-4496-ada5-288cd0a01738.png and /dev/null differ
diff --git a/docs/images/coso.jpg b/docs/images/coso.jpg
new file mode 100644
index 000000000..da158adc3
Binary files /dev/null and b/docs/images/coso.jpg differ
diff --git a/docs/images/ffc70018-aa5f-4738-883d-045614488608.png b/docs/images/ffc70018-aa5f-4738-883d-045614488608.png
deleted file mode 100644
index 2b4113451..000000000
Binary files a/docs/images/ffc70018-aa5f-4738-883d-045614488608.png and /dev/null differ
diff --git a/docs/images/lime-claw-readme.png b/docs/images/lime-claw-readme.png
new file mode 100644
index 000000000..8104cf430
Binary files /dev/null and b/docs/images/lime-claw-readme.png differ
diff --git a/docs/images/screenshot-20260319-114622.png b/docs/images/screenshot-20260319-114622.png
new file mode 100644
index 000000000..dda929a22
Binary files /dev/null and b/docs/images/screenshot-20260319-114622.png differ
diff --git a/docs/images/screenshot-20260319-114807.png b/docs/images/screenshot-20260319-114807.png
new file mode 100644
index 000000000..55361c94f
Binary files /dev/null and b/docs/images/screenshot-20260319-114807.png differ
diff --git a/docs/images/screenshot-20260319-115011.png b/docs/images/screenshot-20260319-115011.png
new file mode 100644
index 000000000..933f06454
Binary files /dev/null and b/docs/images/screenshot-20260319-115011.png differ
diff --git a/eslint.config.js b/eslint.config.js
index f0489b8ed..367856be6 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -47,7 +47,7 @@ const generalChatRestrictedPaths = [
name: "@/components/general-chat",
importNames: ["useChat"],
message:
- "general-chat 的 useChat 属于旧路径,请优先使用 @/hooks/useUnifiedChat 或当前现役聊天入口。",
+ "general-chat 的 useChat 属于旧路径,请优先使用 useAgentChatUnified / useAsterAgentChat 或当前现役聊天入口。",
},
{
name: "@/components/general-chat",
@@ -65,18 +65,18 @@ const generalChatRestrictedPaths = [
name: "@/components/general-chat/hooks",
importNames: ["useChat"],
message:
- "general-chat/hooks/useChat 属于旧路径,请优先使用 @/hooks/useUnifiedChat 或当前现役聊天入口。",
+ "general-chat/hooks/useChat 属于旧路径,请优先使用 useAgentChatUnified / useAsterAgentChat 或当前现役聊天入口。",
},
{
name: "@/components/general-chat/hooks",
importNames: ["useSession", "useStreaming"],
message:
- "general-chat/hooks 下的 useSession/useStreaming 属于兼容实现,请优先接入统一对话链路。",
+ "general-chat/hooks 下的 useSession/useStreaming 属于兼容实现,请优先接入 useAgentChatUnified / useAsterAgentChat / agent_runtime_*。",
},
{
name: "@/components/general-chat/hooks/useChat",
message:
- "general-chat/hooks/useChat 属于旧路径,请优先使用 @/hooks/useUnifiedChat 或当前现役聊天入口。",
+ "general-chat/hooks/useChat 属于旧路径,请优先使用 useAgentChatUnified / useAsterAgentChat 或当前现役聊天入口。",
},
{
name: "@/components/general-chat/GeneralChatPage",
@@ -400,6 +400,11 @@ const generalChatRestrictedPaths = [
message:
"agentRuntime 中这些旧命名 helper 只允许留在兼容层或兼容测试;业务层请改用 agent_runtime_* 对应 API 或 useAsterAgentChat。",
},
+ {
+ name: "@/hooks/useUnifiedChat",
+ message:
+ "useUnifiedChat 已删除;Agent 工作台请改用 useAgentChatUnified / useAsterAgentChat,旧 General/Creator 路径如需恢复,必须基于 agent_runtime_* 重新设计。",
+ },
{
name: "@/lib/api/agent",
importNames: [
@@ -895,7 +900,7 @@ const unifiedChatCommandSelectors = [
].map((command) => ({
selector: `CallExpression[callee.name='safeInvoke'][arguments.0.value='${command}'], CallExpression[callee.name='invoke'][arguments.0.value='${command}']`,
message:
- "统一对话命令请统一通过 `src/lib/api/unified-chat.ts` 暴露的网关函数调用,避免继续在其他模块中直接拼接命令名。",
+ "`chat_*` 兼容命令已停用;不要继续直接拼接旧命令名,现役链路请统一收敛到 agent_runtime_*。",
}));
const unifiedMemoryCommandSelectors = [
@@ -1179,7 +1184,6 @@ export default [
"src/lib/api/memoryFeedback.ts",
"src/lib/api/toolHooks.ts",
"src/lib/api/terminal.ts",
- "src/lib/api/unified-chat.ts",
"src/lib/api/unifiedMemory.ts",
"src/lib/api/serverRuntime.ts",
"src/lib/api/logs.ts",
diff --git a/extensions/lime-chrome/README.md b/extensions/lime-chrome/README.md
index 1c1d1f497..d62bc3cf7 100644
--- a/extensions/lime-chrome/README.md
+++ b/extensions/lime-chrome/README.md
@@ -67,5 +67,5 @@ npm run bridge:e2e -- --server ws://127.0.0.1:8787 --key proxy_cast --profile de
## 兼容说明
- 扩展只负责浏览器侧采集与动作执行。
-- Agent 侧通过 `aster_agent_cmd` 与 `unified_chat_cmd` 注册的浏览器 MCP 兼容工具访问。
+- Agent 侧通过 `aster_agent_cmd` 暴露的现役浏览器 MCP 工具访问。
- 若你同时使用独立 Chrome Profile(Tauri `open_chrome_profile_window`),请在对应 Profile 内安装该扩展,并使用不同 `profileKey` 做隔离。
diff --git a/package.json b/package.json
index 58fa63995..b26f15a65 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "lime",
"private": true,
- "version": "0.90.0",
+ "version": "0.91.0",
"type": "module",
"engines": {
"node": ">=22.0.0"
diff --git a/scripts/report-legacy-surfaces.mjs b/scripts/report-legacy-surfaces.mjs
index 9179ec5be..58a2f0e52 100644
--- a/scripts/report-legacy-surfaces.mjs
+++ b/scripts/report-legacy-surfaces.mjs
@@ -41,17 +41,17 @@ const agentLegacyHelperSurfaceMonitors = (
const importSurfaceMonitors = [
{
id: "general-chat-root-entry",
- classification: "deprecated",
- description: "旧 general-chat 根导出入口",
+ classification: "dead-candidate",
+ description: "已删除的旧 general-chat 根导出入口",
targets: ["src/components/general-chat/index.ts"],
allowedPaths: [],
},
{
id: "general-chat-page-entry",
- classification: "deprecated",
- description: "旧 general-chat 页面实现入口",
+ classification: "dead-candidate",
+ description: "已删除的旧 general-chat 页面实现入口",
targets: ["src/components/general-chat/GeneralChatPage.tsx"],
- allowedPaths: ["src/components/general-chat/index.ts"],
+ allowedPaths: [],
},
{
id: "general-chat-legacy-session-hook",
@@ -62,22 +62,22 @@ const importSurfaceMonitors = [
},
{
id: "general-chat-legacy-streaming-hook",
- classification: "compat",
- description: "旧 general-chat 流式兼容 Hook",
+ classification: "dead-candidate",
+ description: "已删除的旧 general-chat 流式兼容 Hook",
targets: ["src/components/general-chat/hooks/useStreaming.ts"],
- allowedPaths: ["src/components/general-chat/GeneralChatPage.tsx"],
+ allowedPaths: [],
},
{
id: "general-chat-compat-gateway",
classification: "dead-candidate",
description: "general-chat compat API 网关",
targets: ["src/lib/api/generalChatCompat.ts"],
- allowedPaths: ["src/components/general-chat/store/useGeneralChatStore.ts"],
+ allowedPaths: [],
},
{
id: "agent-compat-gateway",
- classification: "deprecated",
- description: "Agent / Aster compat API 网关",
+ classification: "dead-candidate",
+ description: "已删除的 Agent / Aster compat API 网关",
targets: ["src/lib/api/agentCompat.ts"],
allowedPaths: [],
},
@@ -97,22 +97,22 @@ const importSurfaceMonitors = [
},
{
id: "heartbeat-api-gateway",
- classification: "deprecated",
- description: "旧 heartbeat 前端 API 入口",
+ classification: "dead-candidate",
+ description: "已删除的旧 heartbeat 前端 API 入口",
targets: ["src/lib/api/heartbeat.ts"],
allowedPaths: [],
},
{
id: "heartbeat-settings-page-entry",
- classification: "deprecated",
- description: "旧 heartbeat 设置页入口",
+ classification: "dead-candidate",
+ description: "已删除的旧 heartbeat 设置页入口",
targets: ["src/components/settings-v2/system/heartbeat/index.tsx"],
allowedPaths: [],
},
{
id: "assistant-settings-page-entry",
- classification: "deprecated",
- description: "旧助理服务设置页入口",
+ classification: "dead-candidate",
+ description: "已删除的旧助理服务设置页入口",
targets: ["src/components/settings-v2/agent/assistant/index.tsx"],
allowedPaths: [],
},
@@ -130,14 +130,56 @@ const importSurfaceMonitors = [
targets: ["src/stores/agentStore.ts"],
allowedPaths: [],
},
+ {
+ id: "use-unified-chat-compat-hook",
+ classification: "dead-candidate",
+ description: "useUnifiedChat compat Hook 入口",
+ targets: ["src/hooks/useUnifiedChat.ts"],
+ allowedPaths: [],
+ },
+ {
+ id: "unified-chat-compat-gateway",
+ classification: "dead-candidate",
+ description: "unified-chat compat API 网关",
+ targets: ["src/lib/api/unified-chat.ts"],
+ allowedPaths: [],
+ },
+ {
+ id: "three-stage-workflow-hook-entry",
+ classification: "dead-candidate",
+ description: "旧 three-stage workflow React Hook 入口",
+ targets: ["src/hooks/useThreeStageWorkflow.ts"],
+ allowedPaths: [],
+ },
+ {
+ id: "three-stage-workflow-manager-entry",
+ classification: "dead-candidate",
+ description: "旧 three-stage workflow 管理器入口",
+ targets: ["src/lib/workflow/threeStageWorkflow.ts"],
+ allowedPaths: [],
+ },
+ {
+ id: "tool-hooks-api-gateway",
+ classification: "dead-candidate",
+ description: "旧 tool hooks 前端 API 网关",
+ targets: ["src/lib/api/toolHooks.ts"],
+ allowedPaths: [],
+ },
+ {
+ id: "context-memory-legacy-api-gateway",
+ classification: "dead-candidate",
+ description: "旧 context memory 前端 API 网关",
+ targets: ["src/lib/api/contextMemory.ts"],
+ allowedPaths: [],
+ },
];
const commandSurfaceMonitors = [
...agentLegacyCommandSurfaceMonitors,
{
id: "general-chat-compat-commands",
- classification: "compat",
- description: "general_chat compat 命令前端边界",
+ classification: "dead-candidate",
+ description: "已零引用的 general_chat compat 命令前端边界",
commands: [
"general_chat_get_session",
"general_chat_list_sessions",
@@ -146,31 +188,64 @@ const commandSurfaceMonitors = [
"general_chat_rename_session",
"general_chat_get_messages",
],
- allowedPaths: ["src/lib/api/generalChatCompat.ts"],
+ allowedPaths: [],
},
{
id: "conversation-memory-legacy-commands",
- classification: "compat",
- description: "旧 conversation memory 命令前端边界",
+ classification: "dead-candidate",
+ description: "已零引用的旧 conversation memory 命令前端边界",
commands: [
"get_conversation_memory_overview",
"get_conversation_memory_stats",
"request_conversation_memory_analysis",
"cleanup_conversation_memory",
],
- allowedPaths: ["src/lib/api/memoryRuntime.ts"],
+ allowedPaths: [],
+ },
+ {
+ id: "context-memory-legacy-commands",
+ classification: "dead-candidate",
+ description: "旧 context memory 命令前端边界",
+ commands: [
+ "save_memory_entry",
+ "get_session_memories",
+ "get_memory_context",
+ "record_error",
+ "should_avoid_operation",
+ "mark_error_resolved",
+ "get_memory_stats",
+ "cleanup_expired_memories",
+ ],
+ allowedPaths: [],
+ },
+ {
+ id: "chat-compat-commands",
+ classification: "dead-candidate",
+ description: "chat_* compat 命令前端边界",
+ commands: [
+ "chat_create_session",
+ "chat_list_sessions",
+ "chat_get_session",
+ "chat_delete_session",
+ "chat_rename_session",
+ "chat_get_messages",
+ "chat_send_message",
+ "chat_stop_generation",
+ "chat_configure_provider",
+ ],
+ allowedPaths: [],
},
{
id: "prompt-switch-legacy-command",
- classification: "deprecated",
- description: "旧 prompt 切换命令前端边界",
+ classification: "dead-candidate",
+ description: "已零引用的旧 prompt 切换命令前端边界",
commands: ["switch_prompt"],
allowedPaths: [],
},
{
id: "api-key-legacy-migration-commands",
- classification: "deprecated",
- description: "旧 API Key 迁移命令前端边界",
+ classification: "dead-candidate",
+ description: "已零引用的旧 API Key 迁移命令前端边界",
commands: [
"get_legacy_api_key_credentials",
"migrate_legacy_api_key_credentials",
@@ -180,8 +255,8 @@ const commandSurfaceMonitors = [
},
{
id: "heartbeat-legacy-commands",
- classification: "deprecated",
- description: "旧 heartbeat 命令前端边界",
+ classification: "dead-candidate",
+ description: "已零引用的旧 heartbeat 命令前端边界",
commands: [
"get_heartbeat_config",
"update_heartbeat_config",
@@ -203,14 +278,29 @@ const commandSurfaceMonitors = [
],
allowedPaths: [],
},
+ {
+ id: "tool-hooks-legacy-commands",
+ classification: "dead-candidate",
+ description: "旧 tool hooks 命令前端边界",
+ commands: [
+ "execute_hooks",
+ "add_hook_rule",
+ "remove_hook_rule",
+ "toggle_hook_rule",
+ "get_hook_rules",
+ "get_hook_execution_stats",
+ "clear_hook_execution_stats",
+ ],
+ allowedPaths: [],
+ },
];
const frontendTextSurfaceMonitors = [
...agentLegacyHelperSurfaceMonitors,
{
id: "frontend-assistant-settings-surfaces",
- classification: "deprecated",
- description: "前端助理服务设置页与配置面回流",
+ classification: "dead-candidate",
+ description: "已零引用的前端助理服务设置页与配置面回流",
patterns: [
"SettingsTabs.Assistant",
"settings.tab.assistant",
@@ -225,8 +315,8 @@ const frontendTextSurfaceMonitors = [
},
{
id: "stores-root-barrel-imports",
- classification: "deprecated",
- description: "从 @/stores 根 barrel 回流遗留 store 导入",
+ classification: "dead-candidate",
+ description: "已零引用的 @/stores 根 barrel 回流",
patterns: ['from "@/stores"', "from '@/stores'"],
allowedPaths: [],
},
@@ -235,8 +325,8 @@ const frontendTextSurfaceMonitors = [
const rustTextSurfaceMonitors = [
{
id: "rust-general-chat-dao",
- classification: "deprecated",
- description: "Rust 业务层 direct GeneralChatDao 依赖",
+ classification: "dead-candidate",
+ description: "已零引用的 Rust 业务层 direct GeneralChatDao 依赖",
patterns: ["GeneralChatDao", "database::dao::general_chat"],
allowedPaths: [],
},
@@ -248,15 +338,14 @@ const rustTextSurfaceMonitors = [
allowedPaths: [
"src-tauri/crates/core/src/app_paths.rs",
"src-tauri/crates/core/src/database/migration/general_chat_migration.rs",
- "src-tauri/crates/core/src/database/pending_general_chat.rs",
"src-tauri/crates/core/src/database/migration.rs",
"src-tauri/crates/core/src/database/schema.rs",
],
},
{
id: "rust-legacy-general-helper-usage",
- classification: "compat",
- description: "Rust runtime pending general raw helper 扩散",
+ classification: "dead-candidate",
+ description: "Rust runtime pending general raw helper 回流",
patterns: [
"load_pending_general_session_messages_raw",
"load_pending_general_messages_raw",
@@ -269,15 +358,27 @@ const rustTextSurfaceMonitors = [
"count_unmigrated_legacy_general_messages",
"sum_unmigrated_legacy_general_message_chars",
],
- allowedPaths: [
- "src-tauri/crates/core/src/database/pending_general_chat.rs",
- "src-tauri/crates/core/src/database/mod.rs",
+ allowedPaths: [],
+ },
+ {
+ id: "rust-pending-general-wrapper-usage",
+ classification: "dead-candidate",
+ description: "Rust 业务层 pending general 兼容 wrapper 回流",
+ patterns: [
+ "load_pending_general_messages(",
+ "load_pending_general_session_messages(",
+ "count_pending_general_sessions(",
+ "count_pending_general_messages(",
+ "sum_pending_general_message_chars(",
+ "summarize_pending_general(",
],
+ includePathPrefixes: ["src-tauri/src", "src-tauri/crates"],
+ allowedPaths: [],
},
{
id: "rust-legacy-general-module-imports",
- classification: "deprecated",
- description: "Rust 外部模块直接引用 pending/legacy general 子模块",
+ classification: "dead-candidate",
+ description: "已零引用的 Rust 外部模块 direct pending/legacy general 子模块",
patterns: [
"crate::database::legacy_general_chat::",
"lime_core::database::legacy_general_chat::",
@@ -296,14 +397,12 @@ const rustTextSurfaceMonitors = [
],
allowedPaths: [
"src-tauri/crates/core/src/database/migration/general_chat_migration.rs",
- "src-tauri/crates/core/src/database/migration.rs",
- "src-tauri/crates/core/src/database/mod.rs",
],
},
{
id: "rust-services-crate-general-chat-compat",
- classification: "deprecated",
- description: "services crate 内部继续依赖 general_chat 兼容壳",
+ classification: "dead-candidate",
+ description: "已零引用的 services crate general_chat 兼容壳回流",
patterns: [
"use crate::general_chat::",
"use crate::general_chat::{",
@@ -314,22 +413,22 @@ const rustTextSurfaceMonitors = [
},
{
id: "rust-cross-crate-general-chat-compat",
- classification: "deprecated",
- description: "跨 crate 引回 lime_services::general_chat 兼容壳",
+ classification: "dead-candidate",
+ description: "已零引用的跨 crate lime_services::general_chat 兼容壳回流",
patterns: ["lime_services::general_chat::"],
allowedPaths: [],
},
{
id: "rust-provider-pool-legacy-selector",
- classification: "deprecated",
- description: "provider pool legacy 凭证选择兼容方法",
+ classification: "dead-candidate",
+ description: "已零引用的 provider pool legacy 凭证选择兼容方法",
patterns: ["select_credential_with_fallback_legacy"],
allowedPaths: [],
},
{
id: "rust-memory-legacy-command-shells",
- classification: "deprecated",
- description: "旧 conversation memory Rust 命令壳回流",
+ classification: "dead-candidate",
+ description: "已零引用的旧 conversation memory Rust 命令壳回流",
patterns: [
"get_conversation_memory_stats",
"get_conversation_memory_overview",
@@ -340,9 +439,138 @@ const rustTextSurfaceMonitors = [
allowedPaths: [],
},
{
- id: "rust-request-tool-policy-compat-service",
+ id: "rust-memory-profile-prompt-helper-leak",
classification: "deprecated",
- description: "request_tool_policy 旧服务壳回流",
+ description: "低层 build_memory_profile_prompt helper 泄漏到统一装配边界之外",
+ patterns: ["build_memory_profile_prompt("],
+ includePathPrefixes: ["src-tauri/src"],
+ allowedPaths: ["src-tauri/src/services/memory_profile_prompt_service.rs"],
+ },
+ {
+ id: "rust-memory-sources-prompt-helper-leak",
+ classification: "deprecated",
+ description: "低层 build_memory_sources_prompt helper 泄漏到统一装配边界之外",
+ patterns: ["build_memory_sources_prompt("],
+ includePathPrefixes: ["src-tauri/src"],
+ allowedPaths: [
+ "src-tauri/src/services/memory_profile_prompt_service.rs",
+ "src-tauri/src/services/memory_source_resolver_service.rs",
+ ],
+ },
+ {
+ id: "rust-project-session-config-helper-leak",
+ classification: "dead-candidate",
+ description: "旧 create_session_config_with_project helper 回流",
+ patterns: ["create_session_config_with_project("],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-unified-chat-command-module-leak",
+ classification: "dead-candidate",
+ description: "Rust unified_chat compat 命令模块重新回到 commands 编译图",
+ patterns: ["pub mod unified_chat_cmd;"],
+ includePathPrefixes: ["src-tauri/src/commands"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-tool-hooks-command-module-leak",
+ classification: "dead-candidate",
+ description: "Rust tool_hooks 旧命令模块重新回到 commands 编译图",
+ patterns: ["pub mod tool_hooks;"],
+ includePathPrefixes: ["src-tauri/src/commands"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-tool-hooks-service-module-leak",
+ classification: "dead-candidate",
+ description: "services crate 旧 tool_hooks_service 模块重新回到编译图",
+ patterns: ["pub mod tool_hooks_service;"],
+ includePathPrefixes: ["src-tauri/crates/services/src"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-three-stage-workflow-tool-leak",
+ classification: "dead-candidate",
+ description: "legacy three_stage_workflow 工具名重新回到 Lime Rust 编译图",
+ patterns: ['"three_stage_workflow"', "three_stage_workflow"],
+ includePathPrefixes: ["src-tauri/src", "src-tauri/crates"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-skill-workflow-tauri-orchestration-leak",
+ classification: "dead-candidate",
+ description: "已零引用的 skill workflow 执行主链回流到 Tauri skills 模块",
+ patterns: [
+ "SessionConfigBuilder::new(",
+ "convert_agent_event(",
+ "WriteArtifactEventEmitter::new(",
+ ".reply(",
+ ],
+ includePathPrefixes: ["src-tauri/src/skills"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-skill-prompt-command-orchestration-leak",
+ classification: "dead-candidate",
+ description: "已零引用的 skill prompt 执行主链回流到 skill_exec_cmd 命令层",
+ patterns: [
+ "SessionConfigBuilder::new(",
+ "convert_agent_event(",
+ "WriteArtifactEventEmitter::new(",
+ ".reply(",
+ ],
+ includePathPrefixes: ["src-tauri/src/commands/skill_exec_cmd.rs"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-skill-runtime-command-bootstrap-leak",
+ classification: "dead-candidate",
+ description: "已零引用的 skill runtime 准备与 provider fallback 回流到 skill_exec_cmd 命令层",
+ patterns: [
+ "ensure_browser_mcp_tools_registered(",
+ "ensure_social_image_tool_registered(",
+ "ensure_creation_task_tools_registered(",
+ "build_memory_profile_prompt(",
+ ".configure_provider_from_pool(",
+ "TauriExecutionCallback::new(",
+ ],
+ includePathPrefixes: ["src-tauri/src/commands/skill_exec_cmd.rs"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-skill-catalog-command-leak",
+ classification: "dead-candidate",
+ description: "已零引用的 skill catalog 枚举与详情装配回流到 skill_exec_cmd 命令层",
+ patterns: [
+ "get_skill_roots(",
+ "load_skills_from_directory(",
+ "find_skill_by_name(",
+ "invalid_skill_message(",
+ "load_skill_from_file(",
+ "parse_skill_frontmatter(",
+ "parse_allowed_tools(",
+ "parse_boolean(",
+ ],
+ includePathPrefixes: ["src-tauri/src/commands/skill_exec_cmd.rs"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-skill-mode-branch-command-leak",
+ classification: "dead-candidate",
+ description: "已零引用的 skill execution_mode 分支回流到 skill_exec_cmd 命令层",
+ patterns: [
+ "skill.execution_mode == \"workflow\"",
+ "!skill.workflow_steps.is_empty()",
+ "execute_skill_workflow(",
+ "execute_skill_prompt(",
+ ],
+ includePathPrefixes: ["src-tauri/src/commands/skill_exec_cmd.rs"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-request-tool-policy-compat-service",
+ classification: "dead-candidate",
+ description: "已零引用的 request_tool_policy 旧服务壳回流",
patterns: [
"crate::services::request_tool_policy_prompt_service::",
"lime_lib::services::request_tool_policy_prompt_service::",
@@ -352,8 +580,8 @@ const rustTextSurfaceMonitors = [
},
{
id: "rust-service-agent-table-query-leak",
- classification: "deprecated",
- description: "Tauri service 层 direct agent_sessions/agent_messages 查询回流",
+ classification: "dead-candidate",
+ description: "已零引用的 Tauri service 层 direct agent_sessions/agent_messages 查询回流",
patterns: [
"FROM agent_sessions s",
"FROM agent_messages m",
@@ -364,33 +592,90 @@ const rustTextSurfaceMonitors = [
},
{
id: "rust-service-model-usage-table-query-leak",
- classification: "deprecated",
- description: "Tauri service 层 direct model_usage_stats 查询回流",
+ classification: "dead-candidate",
+ description: "已零引用的 Tauri service 层 direct model_usage_stats 查询回流",
patterns: ["FROM model_usage_stats", "SELECT COUNT(*) FROM model_usage_stats"],
includePathPrefixes: ["src-tauri/src/services"],
allowedPaths: [],
},
+ {
+ id: "rust-dev-bridge-unified-memory-sql-leak",
+ classification: "dead-candidate",
+ description: "已零引用的 DevBridge unified_memory SQL 绕路回流",
+ patterns: [
+ "FROM unified_memory",
+ "INSERT INTO unified_memory",
+ "UPDATE unified_memory",
+ "DELETE FROM unified_memory",
+ ],
+ includePathPrefixes: ["src-tauri/src/dev_bridge/dispatcher/memory.rs"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-agent-runtime-legacy-queue-table-leak",
+ classification: "deprecated",
+ description: "legacy runtime queue 表名从数据库迁移边界向外扩散",
+ patterns: ["agent_runtime_queued_turns"],
+ includePathPrefixes: ["src-tauri/src", "src-tauri/crates"],
+ allowedPaths: ["src-tauri/crates/core/src/database/agent_runtime_queue_repository.rs"],
+ },
+ {
+ id: "rust-agent-runtime-legacy-queue-migration-leak",
+ classification: "dead-candidate",
+ description: "已零引用的 legacy runtime queue 启动迁移 helper 回流到其他模块",
+ patterns: ["migrate_legacy_runtime_queue_to_aster_store("],
+ includePathPrefixes: ["src-tauri/src", "src-tauri/crates"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-agent-session-legacy-todo-state-leak",
+ classification: "dead-candidate",
+ description: "已零引用的 Lime 业务层 direct legacy TodoState 读取回流",
+ patterns: ["TodoState::from_extension_data(", "TodoState::new("],
+ includePathPrefixes: ["src-tauri/src", "src-tauri/crates"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-agent-session-structured-todo-helper-bypass",
+ classification: "dead-candidate",
+ description: "已零引用的 Lime 业务层绕过 unified todo helper 直接读取 TodoListState",
+ patterns: ["TodoListState::from_extension_data(", "TodoListState::from_markdown("],
+ includePathPrefixes: ["src-tauri/src", "src-tauri/crates"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-services-default-workspace-query-leak",
+ classification: "dead-candidate",
+ description: "已零引用的 services crate direct 默认 workspace root 查询回流",
+ patterns: ["SELECT root_path FROM workspaces WHERE is_default = 1 LIMIT 1"],
+ includePathPrefixes: ["src-tauri/crates/services/src"],
+ allowedPaths: [],
+ },
{
id: "rust-agent-session-direct-record-access",
classification: "deprecated",
description: "Rust 上层模块 direct Agent session 记录与消息读写回流",
patterns: [
"AgentDao::get_session(",
+ "AgentDao::get_session_with_messages(",
"AgentDao::list_sessions(",
+ "AgentDao::list_session_overviews(",
"AgentDao::get_message_count(",
"AgentDao::get_messages(",
+ "AgentDao::get_session_overview(",
"AgentDao::session_exists(",
"AgentDao::update_title(",
"AgentDao::update_session_time(",
+ "AgentDao::rename_session(",
"AgentDao::update_working_dir(",
"AgentDao::update_execution_strategy(",
],
- allowedPaths: ["src-tauri/crates/agent/src/session_store.rs"],
+ allowedPaths: ["src-tauri/crates/core/src/database/agent_session_repository.rs"],
},
{
id: "rust-agent-session-direct-delete",
- classification: "deprecated",
- description: "Rust 业务层 direct AgentDao::delete_session 回流",
+ classification: "dead-candidate",
+ description: "已零引用的 Rust 业务层 direct AgentDao::delete_session 回流",
patterns: ["AgentDao::delete_session("],
allowedPaths: [],
},
@@ -399,12 +684,191 @@ const rustTextSurfaceMonitors = [
classification: "deprecated",
description: "Rust 业务层 direct AgentDao::create_session 回流",
patterns: ["AgentDao::create_session("],
- allowedPaths: ["src-tauri/crates/agent/src/session_store.rs"],
+ allowedPaths: ["src-tauri/crates/core/src/database/agent_session_repository.rs"],
+ },
+ {
+ id: "rust-agent-dao-row-type-leak",
+ classification: "dead-candidate",
+ description: "agent crate 重新泄漏 core DAO row 类型",
+ patterns: ["AgentSessionOverviewRow"],
+ includePathPrefixes: ["src-tauri/crates/agent/src"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-agent-workspace-query-leak",
+ classification: "dead-candidate",
+ description: "agent runtime direct workspaces 绑定查询回流",
+ patterns: ["SELECT id FROM workspaces WHERE root_path = ? LIMIT 1"],
+ includePathPrefixes: ["src-tauri/crates/agent/src"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-agent-session-record-repository-module-leak",
+ classification: "dead-candidate",
+ description: "lime-agent 本地 session_record_repository 壳重新回到编译图",
+ patterns: ["mod session_record_repository;"],
+ includePathPrefixes: ["src-tauri/crates/agent/src/lib.rs"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-agent-session-compat-surface",
+ classification: "dead-candidate",
+ description: "agent crate 旧 compat session API 回流",
+ patterns: [
+ "CompatSessionInfo",
+ "list_compat_sessions_sync(",
+ "get_compat_session_sync(",
+ ],
+ includePathPrefixes: ["src-tauri/crates/agent/src"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-agent-session-store-public-module-leak",
+ classification: "dead-candidate",
+ description: "lime-agent 重新对 crate 外暴露 session_store 模块",
+ patterns: ["pub mod session_store;"],
+ includePathPrefixes: ["src-tauri/crates/agent/src/lib.rs"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-agent-session-store-direct-module-usage",
+ classification: "dead-candidate",
+ description: "上层模块重新 direct 依赖 lime_agent::session_store 模块路径",
+ patterns: ["lime_agent::session_store::"],
+ includePathPrefixes: ["src-tauri/src"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-agent-session-record-create-api-leak",
+ classification: "dead-candidate",
+ description: "lime-agent crate 根重新暴露内部 session record 创建 API",
+ patterns: ["create_session_record_sync,", "CreateSessionRecordInput,"],
+ includePathPrefixes: ["src-tauri/crates/agent/src/lib.rs"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-agent-integration-public-module-leak",
+ classification: "dead-candidate",
+ description: "agent 集成模块重新对外暴露 integration 模块路径",
+ patterns: ["pub mod integration;"],
+ includePathPrefixes: ["src-tauri/src/agent/mod.rs"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-agent-integration-module-compiled-leak",
+ classification: "dead-candidate",
+ description: "已退出编译图的 agent integration 模块重新回到 agent 根模块",
+ patterns: ["mod integration;"],
+ includePathPrefixes: ["src-tauri/src/agent/mod.rs"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-agent-integration-direct-module-usage",
+ classification: "dead-candidate",
+ description: "应用层重新 direct 依赖 crate::agent::integration 模块路径",
+ patterns: ["crate::agent::integration::"],
+ includePathPrefixes: ["src-tauri/src"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-agent-subagent-direct-module-usage",
+ classification: "dead-candidate",
+ description: "应用层重新 direct 依赖 crate::agent::subagent_scheduler 模块路径",
+ patterns: ["crate::agent::subagent_scheduler::"],
+ includePathPrefixes: ["src-tauri/src"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-aster-runtime-snapshot-helper-leak",
+ classification: "dead-candidate",
+ description: "已零引用的 Lime 业务层 direct Aster runtime snapshot helper 回流",
+ patterns: ["load_session_runtime_snapshot("],
+ includePathPrefixes: ["src-tauri/src", "src-tauri/crates"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-aster-runtime-store-leak",
+ classification: "dead-candidate",
+ description: "已零引用的 Lime 业务层 direct Aster shared runtime store 回流",
+ patterns: [
+ "shared_thread_runtime_store(",
+ "initialize_shared_thread_runtime_store(",
+ "initialize_shared_sqlite_thread_runtime_store(",
+ ],
+ includePathPrefixes: ["src-tauri/src", "src-tauri/crates"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-aster-runtime-store-public-require-api-leak",
+ classification: "dead-candidate",
+ description: "Aster runtime support 重新对 crate 外暴露 require_aster_thread_runtime_store",
+ patterns: ["pub fn require_aster_thread_runtime_store("],
+ includePathPrefixes: ["src-tauri/crates/agent/src/aster_runtime_support.rs"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-aster-runtime-init-return-store-api-leak",
+ classification: "dead-candidate",
+ description: "Aster runtime 启动初始化 API 重新向 crate 外返回 runtime store",
+ patterns: [
+ "pub fn initialize_aster_thread_runtime_store() -> Result, String>",
+ ],
+ includePathPrefixes: ["src-tauri/crates/agent/src/aster_runtime_support.rs"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-aster-runtime-public-legacy-init-helper-leak",
+ classification: "dead-candidate",
+ description: "Aster runtime support 重新对 crate 外暴露旧 initialize_aster_thread_runtime_store helper",
+ patterns: ["pub fn initialize_aster_thread_runtime_store("],
+ includePathPrefixes: ["src-tauri/crates/agent/src/aster_runtime_support.rs"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-aster-runtime-snapshot-root-export-leak",
+ classification: "dead-candidate",
+ description: "lime-agent crate 根重新暴露 load_aster_runtime_snapshot helper",
+ patterns: ["load_aster_runtime_snapshot"],
+ includePathPrefixes: ["src-tauri/crates/agent/src/lib.rs"],
+ allowedPaths: [],
+ },
+ {
+ id: "rust-aster-runtime-queue-service-leak",
+ classification: "dead-candidate",
+ description: "已零引用的 Lime 业务层 direct Aster shared runtime queue service 回流",
+ patterns: [],
+ regexPatterns: [String.raw`(?
- monitor.patterns.some((pattern) => sourceCode.includes(pattern));
+ monitor.patterns.some((pattern) => sourceCode.includes(pattern)) ||
+ (monitor.regexPatterns ?? []).some((pattern) =>
+ new RegExp(pattern, "m").test(sourceCode),
+ );
const references = filteredRuntimeSources
.filter((file) => matchesPattern(file.sourceCode))
@@ -1019,15 +1504,43 @@ function evaluateTextCountMonitor(monitor, runtimeSources, testSources) {
};
}
+function getImportStatus(result) {
+ return result.violations.length > 0
+ ? "违规"
+ : result.references.length === 0 && result.existingTargets.length === 0
+ ? "已删除"
+ : result.references.length === 0
+ ? "零引用"
+ : "受控";
+}
+
+function getCommandStatus(result) {
+ const flattenedReferences = [...result.referencesByCommand.values()].flat();
+ const uniqueReferences = [...new Set(flattenedReferences)].sort();
+ return result.violations.length > 0
+ ? "违规"
+ : uniqueReferences.length === 0
+ ? "零引用"
+ : "受控";
+}
+
+function getTextStatus(result) {
+ return result.violations.length > 0
+ ? "违规"
+ : result.references.length === 0
+ ? "零引用"
+ : "受控";
+}
+
+function isStatusClassificationDrift(status, classification) {
+ return (
+ (status === "已删除" || status === "零引用") &&
+ classification !== "dead-candidate"
+ );
+}
+
function printImportReport(result) {
- const status =
- result.violations.length > 0
- ? "违规"
- : result.references.length === 0 && result.existingTargets.length === 0
- ? "已删除"
- : result.references.length === 0
- ? "零引用"
- : "受控";
+ const status = getImportStatus(result);
console.log(
`- [${status}] ${result.id} (${result.classification}):${result.description}`,
@@ -1046,14 +1559,7 @@ function printImportReport(result) {
}
function printCommandReport(result) {
- const flattenedReferences = [...result.referencesByCommand.values()].flat();
- const uniqueReferences = [...new Set(flattenedReferences)].sort();
- const status =
- result.violations.length > 0
- ? "违规"
- : uniqueReferences.length === 0
- ? "零引用"
- : "受控";
+ const status = getCommandStatus(result);
console.log(
`- [${status}] ${result.id} (${result.classification}):${result.description}`,
@@ -1074,17 +1580,16 @@ function printCommandReport(result) {
}
function printTextReport(result) {
- const status =
- result.violations.length > 0
- ? "违规"
- : result.references.length === 0
- ? "零引用"
- : "受控";
+ const status = getTextStatus(result);
console.log(
`- [${status}] ${result.id} (${result.classification}):${result.description}`,
);
- console.log(` 关键字:${result.patterns.join(", ")}`);
+ const keywords = [
+ ...result.patterns,
+ ...(result.regexPatterns ?? []).map((pattern) => `regex:${pattern}`),
+ ];
+ console.log(` 关键字:${keywords.join(", ")}`);
console.log(` 允许引用:${result.allowedPaths.join(", ") || "无"}`);
console.log(` 实际引用:\n${formatPaths(result.references)}`);
console.log(` 测试引用:\n${formatPaths(result.testReferences)}`);
@@ -1169,6 +1674,65 @@ const zeroReferenceCandidates = importResults
result.references.length === 0 && result.existingTargets.length > 0,
)
.map((result) => `${result.id} (${result.description})`);
+const classificationDriftCandidates = [
+ ...importResults
+ .filter((result) =>
+ isStatusClassificationDrift(
+ getImportStatus(result),
+ result.classification,
+ ),
+ )
+ .map(
+ (result) =>
+ `${result.id} -> ${result.classification} / ${getImportStatus(result)}`,
+ ),
+ ...commandResults
+ .filter((result) =>
+ isStatusClassificationDrift(
+ getCommandStatus(result),
+ result.classification,
+ ),
+ )
+ .map(
+ (result) =>
+ `${result.id} -> ${result.classification} / ${getCommandStatus(result)}`,
+ ),
+ ...frontendTextResults
+ .filter((result) =>
+ isStatusClassificationDrift(
+ getTextStatus(result),
+ result.classification,
+ ),
+ )
+ .map(
+ (result) =>
+ `${result.id} -> ${result.classification} / ${getTextStatus(result)}`,
+ ),
+ ...rustTextResults
+ .filter((result) =>
+ isStatusClassificationDrift(
+ getTextStatus(result),
+ result.classification,
+ ),
+ )
+ .map(
+ (result) =>
+ `${result.id} -> ${result.classification} / ${getTextStatus(result)}`,
+ ),
+ ...rustTextCountResults
+ .filter((result) =>
+ isStatusClassificationDrift(
+ result.runtimeMatches.length === 0 ? "零引用" : "受控",
+ result.classification,
+ ),
+ )
+ .map(
+ (result) =>
+ `${result.id} -> ${result.classification} / ${
+ result.runtimeMatches.length === 0 ? "零引用" : "受控"
+ }`,
+ ),
+];
const violations = [
...importResults.flatMap((result) =>
result.violations.map((item) => `${result.id} -> ${item}`),
@@ -1225,6 +1789,10 @@ console.log(`- 零引用候选:${zeroReferenceCandidates.length}`);
for (const candidate of zeroReferenceCandidates) {
console.log(` - ${candidate}`);
}
+console.log(`- 分类漂移候选:${classificationDriftCandidates.length}`);
+for (const candidate of classificationDriftCandidates) {
+ console.log(` - ${candidate}`);
+}
console.log(`- 边界违规:${violations.length}`);
for (const violation of violations) {
console.log(` - ${violation}`);
diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock
index 398633789..670910617 100644
--- a/src-tauri/Cargo.lock
+++ b/src-tauri/Cargo.lock
@@ -369,7 +369,7 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "aster-core"
-version = "0.18.0"
+version = "0.19.0"
dependencies = [
"ahash",
"anyhow",
@@ -461,7 +461,7 @@ dependencies = [
[[package]]
name = "aster-models"
-version = "0.18.0"
+version = "0.19.0"
dependencies = [
"serde",
"serde_json",
@@ -1313,7 +1313,7 @@ dependencies = [
"bitflags 2.11.0",
"cexpr",
"clang-sys",
- "itertools 0.13.0",
+ "itertools 0.12.1",
"proc-macro2",
"quote",
"regex",
@@ -2399,7 +2399,7 @@ dependencies = [
"dtoa-short",
"itoa",
"matches",
- "phf 0.10.1",
+ "phf 0.8.0",
"proc-macro2",
"quote",
"smallvec",
@@ -2415,7 +2415,7 @@ dependencies = [
"cssparser-macros",
"dtoa-short",
"itoa",
- "phf 0.11.3",
+ "phf 0.8.0",
"smallvec",
]
@@ -4336,7 +4336,7 @@ dependencies = [
"js-sys",
"log",
"wasm-bindgen",
- "windows-core 0.57.0",
+ "windows-core 0.56.0",
]
[[package]]
@@ -4716,15 +4716,6 @@ dependencies = [
"either",
]
-[[package]]
-name = "itertools"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
-dependencies = [
- "either",
-]
-
[[package]]
name = "itertools"
version = "0.14.0"
@@ -5071,7 +5062,7 @@ dependencies = [
[[package]]
name = "lime"
-version = "0.90.0"
+version = "0.91.0"
dependencies = [
"anyhow",
"arboard",
@@ -5174,7 +5165,7 @@ dependencies = [
[[package]]
name = "lime-agent"
-version = "0.90.0"
+version = "0.91.0"
dependencies = [
"aster-core",
"async-trait",
@@ -5185,6 +5176,7 @@ dependencies = [
"lime-mcp",
"lime-providers",
"lime-services",
+ "lime-skills",
"regex",
"rmcp",
"rusqlite",
@@ -5200,7 +5192,7 @@ dependencies = [
[[package]]
name = "lime-browser-runtime"
-version = "0.90.0"
+version = "0.91.0"
dependencies = [
"chrono",
"futures",
@@ -5217,7 +5209,7 @@ dependencies = [
[[package]]
name = "lime-config"
-version = "0.90.0"
+version = "0.91.0"
dependencies = [
"async-trait",
"lime-core",
@@ -5233,7 +5225,7 @@ dependencies = [
[[package]]
name = "lime-core"
-version = "0.90.0"
+version = "0.91.0"
dependencies = [
"aster-models",
"async-trait",
@@ -5273,7 +5265,7 @@ dependencies = [
[[package]]
name = "lime-credential"
-version = "0.90.0"
+version = "0.91.0"
dependencies = [
"axum 0.7.9",
"base64 0.22.1",
@@ -5308,7 +5300,7 @@ dependencies = [
[[package]]
name = "lime-gateway"
-version = "0.90.0"
+version = "0.91.0"
dependencies = [
"axum 0.7.9",
"chrono",
@@ -5329,7 +5321,7 @@ dependencies = [
[[package]]
name = "lime-infra"
-version = "0.90.0"
+version = "0.91.0"
dependencies = [
"chrono",
"dashmap 5.5.3",
@@ -5349,7 +5341,7 @@ dependencies = [
[[package]]
name = "lime-mcp"
-version = "0.90.0"
+version = "0.91.0"
dependencies = [
"async-trait",
"dirs 5.0.1",
@@ -5381,7 +5373,7 @@ dependencies = [
[[package]]
name = "lime-processor"
-version = "0.90.0"
+version = "0.91.0"
dependencies = [
"async-trait",
"lime-core",
@@ -5400,7 +5392,7 @@ dependencies = [
[[package]]
name = "lime-providers"
-version = "0.90.0"
+version = "0.91.0"
dependencies = [
"anyhow",
"async-stream",
@@ -5454,7 +5446,7 @@ dependencies = [
[[package]]
name = "lime-server"
-version = "0.90.0"
+version = "0.91.0"
dependencies = [
"aster-core",
"async-stream",
@@ -5499,7 +5491,7 @@ dependencies = [
[[package]]
name = "lime-server-utils"
-version = "0.90.0"
+version = "0.91.0"
dependencies = [
"axum 0.7.9",
"futures",
@@ -5514,7 +5506,7 @@ dependencies = [
[[package]]
name = "lime-services"
-version = "0.90.0"
+version = "0.91.0"
dependencies = [
"anyhow",
"aster-core",
@@ -5556,7 +5548,7 @@ dependencies = [
[[package]]
name = "lime-skills"
-version = "0.90.0"
+version = "0.91.0"
dependencies = [
"async-trait",
"dirs 5.0.1",
@@ -5574,7 +5566,7 @@ dependencies = [
[[package]]
name = "lime-terminal"
-version = "0.90.0"
+version = "0.91.0"
dependencies = [
"async-trait",
"base64 0.22.1",
@@ -5601,7 +5593,7 @@ dependencies = [
[[package]]
name = "lime-websocket"
-version = "0.90.0"
+version = "0.91.0"
dependencies = [
"axum 0.7.9",
"chrono",
@@ -6274,7 +6266,7 @@ version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7"
dependencies = [
- "proc-macro-crate 2.0.2",
+ "proc-macro-crate 1.3.1",
"proc-macro2",
"quote",
"syn 2.0.117",
@@ -7001,7 +6993,9 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
dependencies = [
+ "phf_macros 0.8.0",
"phf_shared 0.8.0",
+ "proc-macro-hack",
]
[[package]]
@@ -7010,9 +7004,7 @@ version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
dependencies = [
- "phf_macros 0.10.0",
"phf_shared 0.10.0",
- "proc-macro-hack",
]
[[package]]
@@ -7116,12 +7108,12 @@ dependencies = [
[[package]]
name = "phf_macros"
-version = "0.10.0"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0"
+checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c"
dependencies = [
- "phf_generator 0.10.0",
- "phf_shared 0.10.0",
+ "phf_generator 0.8.0",
+ "phf_shared 0.8.0",
"proc-macro-hack",
"proc-macro2",
"quote",
@@ -7533,7 +7525,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d"
dependencies = [
"anyhow",
- "itertools 0.13.0",
+ "itertools 0.12.1",
"proc-macro2",
"quote",
"syn 2.0.117",
@@ -9000,7 +8992,7 @@ version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b1fdf65dd6331831494dd616b30351c38e96e45921a27745cf98490458b90bb"
dependencies = [
- "dirs 6.0.0",
+ "dirs 4.0.0",
]
[[package]]
diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml
index 41853deea..44a8b6844 100644
--- a/src-tauri/Cargo.toml
+++ b/src-tauri/Cargo.toml
@@ -3,7 +3,7 @@ members = ["crates/*"]
resolver = "2"
[workspace.package]
-version = "0.90.0"
+version = "0.91.0"
edition = "2021"
authors = ["coso"]
repository = "https://github.com/aiclientproxy/lime"
@@ -127,8 +127,8 @@ enigo = "0.3"
# 如需联调本地 aster-rust,请运行:
# npm run setup:local-aster -- /path/to/aster-rust
# 脚本会在仓库根 .cargo/config.toml 写入本地 patch 覆盖;该文件已被 .gitignore 忽略。
-aster = { package = "aster-core", git = "https://github.com/astercloud/aster-rust", tag = "v0.18.0" }
-aster-models = { git = "https://github.com/astercloud/aster-rust", tag = "v0.18.0" }
+aster = { package = "aster-core", git = "https://github.com/astercloud/aster-rust", tag = "v0.19.0" }
+aster-models = { git = "https://github.com/astercloud/aster-rust", tag = "v0.19.0" }
# MCP (Model Context Protocol)
rmcp = { version = "0.12.0", features = ["client", "transport-io", "transport-child-process"] }
@@ -191,7 +191,7 @@ version = "2.4"
[package]
name = "lime"
-version = "0.90.0"
+version = "0.91.0"
description = "AI API Proxy Desktop App"
authors = ["you"]
edition = "2021"
diff --git a/src-tauri/crates/agent/Cargo.toml b/src-tauri/crates/agent/Cargo.toml
index 1e3238e39..c339f37ea 100644
--- a/src-tauri/crates/agent/Cargo.toml
+++ b/src-tauri/crates/agent/Cargo.toml
@@ -10,6 +10,7 @@ lime-core.workspace = true
lime-mcp.workspace = true
lime-services.workspace = true
lime-providers.workspace = true
+lime-skills.workspace = true
aster.workspace = true
rmcp.workspace = true
serde.workspace = true
diff --git a/src-tauri/crates/agent/src/ask_bridge.rs b/src-tauri/crates/agent/src/ask_bridge.rs
index 264e0b62c..b2100ef59 100644
--- a/src-tauri/crates/agent/src/ask_bridge.rs
+++ b/src-tauri/crates/agent/src/ask_bridge.rs
@@ -4,6 +4,8 @@
//! 通过 elicitation 事件把问题发送到前端并等待用户输入。
use aster::action_required_manager::ActionRequiredManager;
+use aster::conversation::message::ActionRequiredScope;
+use aster::session_context::{current_action_scope, current_session_id};
use aster::tools::AskCallback;
use serde_json::{json, Value};
use std::time::Duration;
@@ -15,9 +17,11 @@ pub fn create_ask_callback() -> AskCallback {
std::sync::Arc::new(|question: String, options: Option>| {
Box::pin(async move {
let requested_schema = build_requested_schema(&question, options.as_deref());
+ let scope = resolve_action_scope();
match ActionRequiredManager::global()
- .request_and_wait(
+ .request_and_wait_scoped(
+ scope,
question.clone(),
requested_schema,
Duration::from_secs(DEFAULT_ASK_TIMEOUT_SECS),
@@ -38,6 +42,17 @@ pub fn create_ask_callback() -> AskCallback {
})
}
+fn resolve_action_scope() -> ActionRequiredScope {
+ current_action_scope().unwrap_or_else(|| {
+ let session_id = current_session_id();
+ ActionRequiredScope {
+ session_id: session_id.clone(),
+ thread_id: session_id,
+ turn_id: None,
+ }
+ })
+}
+
/// 构建 elicitation 的请求 schema
fn build_requested_schema(question: &str, options: Option<&[String]>) -> Value {
if let Some(options) = options {
@@ -107,3 +122,39 @@ pub fn extract_response(user_data: &Value) -> Option {
.filter(|s| !s.is_empty()),
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use aster::session_context::{with_action_scope, with_session_id};
+
+ #[tokio::test]
+ async fn resolve_action_scope_prefers_runtime_scope() {
+ let scope = ActionRequiredScope {
+ session_id: Some("session-1".to_string()),
+ thread_id: Some("thread-1".to_string()),
+ turn_id: Some("turn-1".to_string()),
+ };
+
+ let resolved = with_action_scope(scope.clone(), async { resolve_action_scope() }).await;
+
+ assert_eq!(resolved, scope);
+ }
+
+ #[tokio::test]
+ async fn resolve_action_scope_falls_back_to_session_id() {
+ let resolved = with_session_id(Some("session-2".to_string()), async {
+ resolve_action_scope()
+ })
+ .await;
+
+ assert_eq!(
+ resolved,
+ ActionRequiredScope {
+ session_id: Some("session-2".to_string()),
+ thread_id: Some("session-2".to_string()),
+ turn_id: None,
+ }
+ );
+ }
+}
diff --git a/src-tauri/crates/agent/src/aster_runtime_support.rs b/src-tauri/crates/agent/src/aster_runtime_support.rs
new file mode 100644
index 000000000..291150cf2
--- /dev/null
+++ b/src-tauri/crates/agent/src/aster_runtime_support.rs
@@ -0,0 +1,326 @@
+//! Aster runtime 支持模块
+//!
+//! 收口 Lime 对 Aster thread runtime store 的访问边界,
+//! 避免业务层散落依赖上游 free function。
+
+use crate::aster_state::QueuedTurnTask;
+use crate::queued_turn::QueuedTurnSnapshot;
+use aster::session::{
+ initialize_shared_session_runtime_with_root, load_shared_session_runtime_snapshot,
+ require_shared_session_runtime_store, QueuedTurnRuntime, SessionRuntimeSnapshot,
+ ThreadRuntimeStore,
+};
+use lime_core::app_paths;
+use lime_core::database::agent_runtime_queue_repository::{self, LegacyRuntimeQueuedTurn};
+use lime_core::database::{lock_db, DbConnection};
+use lime_services::aster_session_store::LimeSessionStore;
+use serde_json::Value;
+use std::collections::{HashMap, HashSet};
+use std::future::Future;
+use std::path::PathBuf;
+use std::sync::{Arc, OnceLock};
+
+const QUEUED_TURN_EVENT_NAME_METADATA_KEY: &str = "event_name";
+const DEFAULT_QUEUE_EVENT_NAME: &str = "agent_stream";
+static ASTER_RUNTIME_ROOT: OnceLock> = OnceLock::new();
+
+#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
+struct LegacyRuntimeQueueMigrationReport {
+ pub session_count: usize,
+ pub migrated_turn_count: usize,
+ pub skipped_existing_turn_count: usize,
+ pub invalid_turn_count: usize,
+}
+
+pub(crate) fn ensure_aster_runtime_dirs() -> Result {
+ ASTER_RUNTIME_ROOT
+ .get_or_init(initialize_aster_runtime_dirs)
+ .clone()
+}
+
+pub(crate) fn require_aster_runtime_dirs() -> Result {
+ match ASTER_RUNTIME_ROOT.get() {
+ Some(result) => result.clone(),
+ None => Err(
+ "Aster 运行时尚未初始化;应在应用启动期先调用 ensure_aster_runtime_dirs()".to_string(),
+ ),
+ }
+}
+
+#[cfg(test)]
+pub(crate) fn ensure_aster_runtime_dirs_with_root(root: PathBuf) -> Result {
+ ASTER_RUNTIME_ROOT
+ .get_or_init(|| initialize_aster_runtime_dirs_with_root(root))
+ .clone()
+}
+
+/// 启动期显式初始化 Aster runtime 目录、共享 runtime store 与全局 session store。
+pub fn initialize_aster_runtime(db: DbConnection) -> Result<(), String> {
+ let runtime_root = ensure_aster_runtime_dirs()?;
+ let session_store = Arc::new(LimeSessionStore::new(db.clone()));
+ let migration_db = db.clone();
+
+ block_on_aster_runtime_init(async move {
+ initialize_shared_session_runtime_with_root(runtime_root, Some(session_store))
+ .await
+ .map_err(|error| format!("初始化 Aster runtime 失败: {error}"))?;
+ migrate_legacy_runtime_queue_to_aster_store(&migration_db).await?;
+ Ok(())
+ })
+}
+
+fn block_on_aster_runtime_init(future: F) -> Result<(), String>
+where
+ F: Future