diff --git a/.gitignore b/.gitignore index b32ab6f17..5d7c1df98 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ docs/gongzonghao/ docs/bussniss/ docs/oem/ docs/tech/ +docs/research/ # Issues tracking (internal use only) .issues/ diff --git a/AGENTS.md b/AGENTS.md index bf5750340..3687fee1f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -21,6 +21,8 @@ 6. **优先平台无关入口** - 优先复用 `npm`、`cargo`、Tauri 命令和仓库脚本,不新增只适用于 Bash/zsh 的流程 7. **未验证的平台假设要显式说明** - 涉及文件系统、进程、终端、快捷键、窗口、托盘、权限时尤其如此 8. **不要继续扩展 compat / deprecated 路径** - 新 API、新命令、新前端入口默认落在当前 `current` 主路径 +9. **规划改了且明确无需兼容时,优先删旧实现** - 如果用户已明确“上一版无人使用 / 不用兼容 / 旧实现阻碍主线”,旧实现默认按 `dead` 或带退出条件的 `deprecated` 处理,不要继续修补、包裹或平移 +10. **`legacy current reference` 不是续命许可** - 旧路线图、旧实现锚点只用于理解现状与迁移,不等于允许继续往旧页面、旧命令、旧协议上加功能 ## 工程硬规则 @@ -40,6 +42,7 @@ 2. **每一刀都要可追踪** - 改动要么回挂到 `docs/roadmap/`,要么登记到 `docs/exec-plans/` 或技术债追踪 3. **清理不能替代交付** - 连续两轮主要在做治理减法后,下一轮优先回到未完成主线 4. **长任务必须落计划** - 超过一轮的实现、迁移、清理,写入 `docs/exec-plans/` 并持续更新进度日志 +5. **主线冲突先清障,不保旧面** - current 规划与旧实现直接冲突时,先删或下线阻碍主线的旧页面、旧命名、旧命令、旧文档,再继续实现;不要为了“看起来兼容”保留双轨 ## 文档导航 diff --git a/README.md b/README.md index 3c50818e8..6880bf7ad 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@
-Lime Logo +Lime Logo # Lime diff --git a/docs/README.md b/docs/README.md index 4123dacbc..7ccdb6dc5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,18 +4,20 @@ `docs/` 是 Lime 文档中心,分为两类受众: -- 普通创作者:优先阅读 `content/` 下的入门与用户指南 +- 普通创作者:`content/` 当前处于 LimeNext V2 重建期,只保留少量进阶页与法律说明 - 开发者与维护者:阅读 `aiprompts/`、`develop/`、`tech/`、`tests/` 等工程文档 文档站基于 Nuxt Content 构建。 ## 目录索引 -- `content/`:对外文档站正文(产品介绍、用户指南、进阶能力) +- `content/`:Nuxt Content 对外文档站入口,当前已删除过时入门/旧导航/旧开发文档,只保留少量仍与实现对齐的进阶页和法律说明 - `aiprompts/`:模块级工程文档(前后端组件、服务、命令、数据层) +- `research/`:外部产品、竞品与技术参考研究文档 - `exec-plans/`:执行计划、进度日志、技术债追踪 - `tech/`:跨模块技术蓝图与专题工程文档(当前已包含 Harness Engineering 指导文档) - `bussniss/`:商务合作与代理运营方案 +- `oem/`:品牌、slogan、Logo 替换与 OEM 物料 - `develop/`:开发流程与协作规范 - `plugins/`:插件与扩展相关文档 - `tests/`:测试策略与用例文档 @@ -26,6 +28,8 @@ - `exec-plans/upstream-runtime-alignment-plan.md`:参考运行时主链对齐总计划与排期事实源 - `exec-plans/upstream-runtime-alignment-progress.md`:参考运行时主链对齐进度日志 - `exec-plans/tech-debt-tracker.md`:技术债持续追踪表 +- `bussniss/README.md`:商业与 OEM 文档导航,定义 current/compat 业务文档边界 +- `oem/README.md`:OEM 品牌文档导航,统一品牌、slogan 与替换口径 - `develop/execution-tracker-technical-plan.md`:统一执行追踪(Execution Tracker)专项技术规划 - `develop/execution-tracker-deprecation-plan.md`:统一执行追踪旧路径退场计划(P0 收口) - `develop/execution-tracker-p0-acceptance-report.md`:统一执行追踪 P0 验收报告 @@ -40,8 +44,11 @@ - `aiprompts/persistence-map.md`:Runtime 文件快照持久化主链、FileArtifact/sidecar/version/checkpoint 边界 - `aiprompts/state-history-telemetry.md`:State / History / Telemetry current 主链、session/thread/request/evidence/history 边界与 current/compat 分类 - `develop/scheduler-task-governance-p1.md`:调度任务治理 P1(连续失败、自动停用、冷却恢复) -- `roadmap/lime-skills-standardization-roadmap.md`:Skills 标准化与产品化路线图 -- `roadmap/limenext/README.md`:LimeNext 平台总纲入口,统一挂接 Workspace、Scene、Runtime、Remote、Governance 与选品系统,并提供业务优先阅读顺序 +- `aiprompts/skill-standard.md`:Skills 包标准、运行时投影与 current/compat 边界总文档 +- `roadmap/lime-skills-standardization-roadmap.md`:Skills 标准化 supporting 收口计划,主要保留迁移边界与剩余差距 +- `research/ribbi/README.md`:Ribbi 研究总入口,作为后续 LimeNext V2 的外部对照事实源 +- `roadmap/limenextv2/README.md`:LimeNext V2 当前主规划入口,固定前台对象、skill-first 主线与运行时骨架 +- `roadmap/limenext/README.md`:LimeNext 旧总纲入口,当前降级为 `legacy current reference`,主要保留实现锚点与阶段性收口记录 - `roadmap/limenext/sceneapp-capability-model.md`:SceneApp 底层能力模型,定义本地、浏览器、云端、混合场景需要的能力模块范围 - `roadmap/limenext/sceneapp-blueprints.md`:用 `x-article-export`、`@配音`、`每日趋势摘要 / 账号增长跟踪` 三条样板把 SceneApp 分类翻译成业务语言 - `roadmap/limenext/artifact-evidence-scorecards.md`:把样板场景继续翻译成“交付物、失败证据、经营评分”三层,方便业务与产品判断该继续做还是收缩 @@ -55,17 +62,24 @@ - `roadmap/limenext/sequences.md`:LimeNext 的业务时序与技术时序合集 - `prd/gongneng/x-article-export/prd.md`:`Browser-grounded SceneApp` 样板功能包,定义 `/x文章转存` 如何把真实网页沉淀成项目内 Markdown bundle - `roadmap/lime-service-skill-cloud-config-prd.md`:服务型技能的端优先执行与云配置同步 PRD -- `roadmap/lime-browser-site-capability-prd.md`:站点能力按真实浏览器优先接入的产品需求文档 +- `aiprompts/site-adapter-standard.md`:站点适配器标准与 `managed_cdp / existing_session` 当前执行边界 - `ops.md`:运维与发布说明 - `app.config.ts` / `nuxt.config.ts` / `package.json`:文档站配置 ## 当前叙事基线 -对外文档(`content/`)默认采用以下口径: +对外文档(`content/`)以及商业/品牌文档(`bussniss/`、`oem/`)默认采用以下口径: -1. 主叙事是“创作类 AI Agent 平台”,不再以“代理服务”作为首页主线 -2. 先讲创作流程与场景,再讲模型连接和 API 兼容 -3. 首页与入门页优先覆盖核心工作区主题与资源沉淀能力 +1. 主叙事是“本地优先的内容闭环 Agent 系统”,不再主打“创作类 AI Agent 平台”或“通用 Agent 平台” +2. 前台主词固定为 `技能 / 灵感库 / 生成`,其中 `生成` 是唯一主执行面 +3. 先讲任务闭环与结果推进,再讲模型连接、协议兼容、渠道入口和工具接入 +4. `项目结果 / 复盘` 是生成链的结果视角,不默认讲成并列一级主舞台 + +涉及商务合作、官网定位、品牌与 OEM 时,优先阅读: + +1. `roadmap/limenextv2/README.md` +2. `bussniss/README.md` +3. `oem/README.md` ## 维护原则 diff --git a/docs/aiprompts/governance.md b/docs/aiprompts/governance.md index ec9fa7fd3..716833397 100644 --- a/docs/aiprompts/governance.md +++ b/docs/aiprompts/governance.md @@ -17,6 +17,21 @@ 其余实现必须被明确归类。 +## 无历史包袱原则 + +如果用户已经明确下面任一前提: + +- 上一版无人使用 +- 不需要兼容 +- 旧实现正在阻碍 current 路线图主线 + +则额外遵守: + +1. 不要因为旧实现“还能跑”就默认保留它 +2. 与 current 规划直接冲突的旧实现,优先判成 `dead`;若必须分步删除,才判成带明确退出条件的 `deprecated` +3. `legacy current reference` 只表示“它曾经是实现锚点”,不表示“后续还能继续在这条旧实现上长功能” +4. 不要为了减少表面 diff,把旧页面、旧命令、旧协议包装成新的 compat 壳继续留在主链旁边 + ## 路线图任务防跑偏 如果用户明确绑定了某份路线图,尤其是要求“按顺序继续”“对齐目标”“先完成主线”,治理动作必须服从路线图主线,而不是反过来主导路线图。 @@ -103,6 +118,12 @@ 没有退出条件的 compat,最终都会常驻。 +如果当前任务已经明确“无兼容需求”,分类时额外遵守: + +- 不要把“现在还有调用”自动翻译成必须保留 compat +- 先判断这些调用是不是也属于同一批应迁或应删的旧实现 +- 只要同轮能迁完或删完,就直接按 `dead` / `deprecated` 收口,不要再补一层过渡包装 + ### 4. 优先做减法 默认优先执行这些动作,而不是再加一层抽象: @@ -115,6 +136,14 @@ 除非用户明确要求保留兼容,否则不要新增新的 compat 层。 +如果路线图已经切换,而旧实现又在阻碍主线,优先级进一步固定为: + +1. 删掉或下线阻碍主线的旧实现 +2. 封住旧路回流 +3. 再把 current 主链补完整 + +不要把“先让旧实现也顺手支持一下”当成折中方案。 + ### 5. 先封旧路,再谈“推荐新路” 治理不能靠口头约定,必须靠守卫机制。 diff --git a/docs/aiprompts/limecore-collaboration-entry.md b/docs/aiprompts/limecore-collaboration-entry.md index 2f8448454..f459e6e8e 100644 --- a/docs/aiprompts/limecore-collaboration-entry.md +++ b/docs/aiprompts/limecore-collaboration-entry.md @@ -7,6 +7,18 @@ - 绝对路径:`/Users/coso/Documents/dev/ai/limecloud/limecore/docs/aiprompts/lime-limecore-collaboration.md` - 在 `limecore` 仓库内的相对路径:`docs/aiprompts/lime-limecore-collaboration.md` +已确认的服务端真实落点: + +- `/Users/coso/Documents/dev/ai/limecloud/limecore/services/control-plane-svc` +- `/Users/coso/Documents/dev/ai/limecloud/limecore/services/gateway-svc` +- `/Users/coso/Documents/dev/ai/limecloud/limecore/services/scene-orchestrator-svc` +- `/Users/coso/Documents/dev/ai/limecloud/limecore/services/worker-svc` + +固定纠偏: + +- 不要再把控制面写成 “`lime` 仓库内待新建本地模块” +- `lime` 仓库默认是消费方,不是控制面唯一背景事实源 + ## 什么时候先读主文档 遇到下面这些任务时,默认先读 `limecore` 主文档: diff --git a/docs/aiprompts/query-loop.md b/docs/aiprompts/query-loop.md index d2813c427..6c67d310c 100644 --- a/docs/aiprompts/query-loop.md +++ b/docs/aiprompts/query-loop.md @@ -226,13 +226,11 @@ ### `compat` -- `docs/roadmap/lime-conversation-execution-efficiency-roadmap.md` - `docs/roadmap/lime-aster-codex-alignment-roadmap.md` -- `docs/roadmap/lime-aster-codex-state-model-implementation-plan.md` - `src-tauri/src/commands/persona_cmd.rs::generate_persona` - `src-tauri/src/commands/theme_context_cmd.rs::aster_agent_theme_context_search` -这些文档与专用命令仍可保留各自职责,但不再承担 Query Loop 唯一事实源职责。 +这份历史档案与专用命令仍可保留各自职责,但不再承担 Query Loop 唯一事实源职责。 这两条命令属于专用一次性会话能力:允许显式拼自己的临时 `SessionConfig`,但不能参与 submit turn、runtime queue、turn context snapshot 或 evidence 真相定义。 当前命令层允许保留的原始执行面只剩这 3 处:`action_runtime` 属于 current 恢复链,`persona_cmd` 与 `theme_context_cmd` 属于受控 compat 一次性命令。 diff --git a/docs/aiprompts/state-history-telemetry.md b/docs/aiprompts/state-history-telemetry.md index 03ef37895..cf14e9167 100644 --- a/docs/aiprompts/state-history-telemetry.md +++ b/docs/aiprompts/state-history-telemetry.md @@ -200,7 +200,7 @@ ### `compat` -- `docs/roadmap/lime-aster-codex-state-model-implementation-plan.md` +- `docs/roadmap/lime-aster-codex-alignment-roadmap.md` - `docs/roadmap/reliability/README.md` - `docs/roadmap/reliability/*` - `src-tauri/src/commands/telemetry_cmd.rs` diff --git a/docs/content/01.introduction/1.overview.md b/docs/content/01.introduction/1.overview.md deleted file mode 100644 index fc7bc7f98..000000000 --- a/docs/content/01.introduction/1.overview.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: 概述 -description: 了解 Lime 如何支持从灵感到发布的完整创作流程 -navigation: - icon: i-heroicons-home ---- - -# Lime 概述 - -Lime 是一款创作类 AI Agent 桌面应用。 -它把对话、内容生成、图片创作、项目管理、资源沉淀放到同一个工作台里。 - -::alert{type="warning"} -**免责声明**: 请在合法合规前提下使用本产品。[查看完整声明](/legal/disclaimer) -:: - -## 你可以用它做什么 - -### 九类工作区主题 - -- 通用对话 -- 社媒内容 -- 图文海报 -- 歌词曲谱 -- 知识探索 -- 计划规划 -- 办公文档 -- 短视频 -- 小说创作 - -### 创作全流程 - -1. 用 Agent 把想法变成清晰方向 -2. 生成文案、脚本或结构化草稿 -3. 按需要生成图片并继续迭代 -4. 把结果沉淀到项目和资源库,方便长期复用 - -### 一站式工作台 - -- AI 对话与创作在同一处完成 -- 项目隔离上下文,避免内容串线 -- 资源按文档/图片/语音/视频分类管理 -- 支持参考图参与图片生成与编辑链路 - -## 使用场景 - -1. **自媒体创作**:每天稳定产出选题、文案、配图 -2. **短视频团队**:快速完成脚本与分镜草稿 -3. **小说连载**:持续积累设定、章节与角色信息 -4. **品牌运营**:统一管理活动素材与历史版本 - -## 下一步 - -- [安装指南](/introduction/installation) - 下载并安装 Lime -- [快速开始](/introduction/quickstart) - 3 步完成首次创作 -- [首页与工作台](/user-guide/dashboard) - 熟悉核心入口 diff --git a/docs/content/01.introduction/2.installation.md b/docs/content/01.introduction/2.installation.md deleted file mode 100644 index 2d6ffad2a..000000000 --- a/docs/content/01.introduction/2.installation.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: 安装指南 -description: 下载、安装并验证 Lime 可正常启动 -navigation: - icon: i-heroicons-arrow-down-tray ---- - -# 安装指南 - -## 系统要求 - -| 平台 | 最低版本 | 架构 | -|------|----------|------| -| macOS | 11.0 (Big Sur) | Apple Silicon (arm64) | -| Windows | 10 | x64 | - -## 下载 - -从 GitHub Releases 下载最新版本安装包: - -[下载 Lime](https://github.com/aiclientproxy/lime/releases) - -::alert{type="warning"} -Lime 当前仅提供 macOS 与 Windows 桌面端安装包,Linux 版本已暂停支持,不再发布 `.deb` 或 `AppImage`。 -:: - -### 安装包 - -| 平台 | 文件名 | 说明 | -|------|--------|------| -| macOS | `Lime_x.x.x_aarch64.dmg` | Apple Silicon Mac | -| Windows | `Lime_x.x.x_x64-online-setup.exe` | 默认推荐,体积更小,安装时按需下载 WebView2 | -| Windows | `Lime_x.x.x_x64-offline-setup.exe` | 离线、内网或受限网络环境使用 | - -## macOS 安装 - -1. 下载 `.dmg` 文件 -2. 双击打开 DMG 镜像 -3. 将 Lime 拖入 Applications 文件夹 -4. 首次运行时,右键点击应用选择"打开"(绕过 Gatekeeper) - -::alert{type="info"} -如果提示"无法验证开发者",请在系统偏好设置 > 安全性与隐私中点击"仍要打开"。 -:: - -## Windows 安装 - -1. 优先下载 `Lime_x.x.x_x64-online-setup.exe` -2. 双击运行安装程序 -3. 按照安装向导完成安装 -4. 从开始菜单启动 Lime - -::alert{type="info"} -如果设备处于离线、内网或受限网络环境,请改用 `Lime_x.x.x_x64-offline-setup.exe`。 -:: - -## 验证安装 - -启动 Lime 后,你应该看到: - -1. 主窗口正常打开 -2. 左侧出现主要入口(AI Agent、项目、资源、设置等) -3. 可以进入设置页并看到版本信息 - -## 常见安装问题 - -### macOS: "应用已损坏" - -```bash -# 移除隔离属性 -xattr -cr /Applications/Lime.app -``` - -### Windows: SmartScreen 警告 - -点击"更多信息" > "仍要运行"即可继续安装。 - -## 下一步 - -安装完成后,继续阅读 [快速开始](/introduction/quickstart),用 3 步完成第一次创作。 diff --git a/docs/content/01.introduction/3.quickstart.md b/docs/content/01.introduction/3.quickstart.md deleted file mode 100644 index ef11f9b0d..000000000 --- a/docs/content/01.introduction/3.quickstart.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: 快速开始 -description: 3 步完成首次创作并沉淀到项目资源库 -navigation: - icon: i-heroicons-rocket-launch ---- - -# 快速开始 - -本指南帮助你在几分钟内完成第一次完整创作流程。 - -## 前置准备 - -确保你已经: - -- [x] 安装了 Lime -- [x] 可以正常打开应用主界面 - -## 步骤 1:选择主题方向与项目 - -1. 启动 Lime,进入 AI Agent 或项目入口 -2. 选择你的主题方向(如社媒、短视频、小说) -3. 新建项目,作为本次创作的工作空间 - -## 步骤 2:输入需求并生成内容 - -1. 用一句话描述你的目标 -2. 让 Agent 先给结构,再生成首稿 -3. 如需视觉内容,在 AI Agent 中用 `@素材` 搜图或触发图片生成,再把结果沉淀到资源库 - -## 步骤 3:沉淀到资源库 - -1. 将文档、图片等结果保存到当前项目资源库 -2. 在资源页按分类查看(文档/图片/语音/视频) -3. 下次创作直接复用历史素材和上下文 - -## 一个最小创作示例 - -1. 主题:`短视频` -2. 输入:`做一条 30 秒“高效晨间复盘”口播内容` -3. 产出: - - 3 个开场钩子 - - 1 版结构化口播稿 - - 1 组配图提示词或参考图改写结果 - -## 常见问题 - -### 我可以只用对话,不做图片吗? - -可以。你可以只用 AI Agent 完成文本创作和项目沉淀。 - -### 我可以直接改图吗? - -可以。先在资源库上传参考图,再从 Claw 发起图片任务;若所选模型支持编辑接口,会自动走对应链路。 - -### 我还需要排查底层协议怎么办? - -可以继续阅读 [API 参考](/api-reference/overview)。 - -## 下一步 - -- [首页与工作台](/user-guide/dashboard) - 理解核心导航 -- [资源库](/user-guide/resources) - 管理创作资产 -- [图片生成与素材链路](/user-guide/image-generation) - 理解 Claw 与资源页如何协同 diff --git a/docs/content/02.user-guide/1.dashboard.md b/docs/content/02.user-guide/1.dashboard.md deleted file mode 100644 index d7b4185c4..000000000 --- a/docs/content/02.user-guide/1.dashboard.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: 首页与工作台 -description: 首页与创作工作台总览 -navigation: - icon: i-heroicons-chart-bar ---- - -# 首页与工作台 - -首页是你进入 Lime 后的主入口。 -建议把它理解为“创作操作台”,而不是单一功能面板。 - -## 左侧核心入口 - -- **AI Agent**:对话、任务推进、内容初稿 -- **项目**:按创作目标管理长期内容 -- **资源**:统一查看文档、图片、语音、视频 -- **设置**:调整主题、模块开关、连接与高级选项 - -## 推荐工作方式 - -1. 先在项目中选择一个主题方向 -2. 在 AI Agent 中完成结构和首稿 -3. 需要视觉时在 AI Agent 中使用 `@素材` 或图片任务 -4. 回到资源库统一管理本地图片、图库素材与回流结果 - -## 主题方向 - -当前支持的主题包括: - -- 通用对话 -- 社媒内容 -- 图文海报 -- 歌词曲谱 -- 知识探索 -- 计划规划 -- 办公文档 -- 短视频 -- 小说创作 - -## 常见操作 - -### 新建一个创作项目 - -1. 进入项目页 -2. 选择主题并创建项目 -3. 开始持续沉淀对话与素材 - -### 从资源继续创作 - -1. 在资源页选中历史文档或图片 -2. 跳转到 AI Agent 继续改写或扩展 -3. 将新结果再次沉淀回资源库 - -### 只看某类素材 - -在资源页切换分类视图,可只看文档、图片、语音或视频。 diff --git a/docs/content/02.user-guide/10.prompts.md b/docs/content/02.user-guide/10.prompts.md deleted file mode 100644 index f76195b89..000000000 --- a/docs/content/02.user-guide/10.prompts.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: 提示词模板 -description: 管理可复用提示词,提升稳定产出效率 -navigation: - icon: i-heroicons-document-text ---- - -# 提示词模板 - -提示词模板用于把“经常重复的表达方式”沉淀下来,减少每次从零开始。 - -## 模板结构建议 - -每个模板建议包含: - -- 名称(便于检索) -- 使用场景(何时用) -- 模板正文(可复用) -- 变量占位(可选) - -## 示例:短视频口播模板 - -```text -你是一名内容策划。 -请基于主题「{{topic}}」生成一段 {{duration}} 秒口播稿,要求: -1. 开头 3 秒有抓力 -2. 中段给出 3 个关键点 -3. 结尾有明确行动引导 -语气风格:{{tone}} -``` - -## 推荐组织方式 - -- 按主题分类:社媒、短视频、小说、办公 -- 按阶段分类:灵感、初稿、润色、发布 -- 统一标签:例如 `#高频`、`#可复用` - -## 使用建议 - -### 一次只优化一个模板 - -避免同时改太多模板,难以判断效果。 - -### 模板要留“可变空间” - -把固定规则写清楚,把创意部分留给变量。 - -### 和项目结合 - -在项目中沉淀效果好的模板,后续同类任务可直接复用。 diff --git a/docs/content/02.user-guide/11.skills.md b/docs/content/02.user-guide/11.skills.md deleted file mode 100644 index f07414092..000000000 --- a/docs/content/02.user-guide/11.skills.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: 技能工作流 -description: 把常见任务封装成可复用的 AI 技能 -navigation: - icon: i-heroicons-sparkles ---- - -# 技能工作流 - -技能可以理解为“可复用的任务卡片”: - -- 预设目标 -- 预设风格 -- 预设步骤 - -这样每次执行同类任务时,不必重复手工组织提示。 - -## 技能适合做什么 - -- 固定流程写作(如周报、复盘、活动文案) -- 固定结构产出(如短视频脚本、小说章节骨架) -- 固定标准检查(如发布前检查清单) - -## 技能卡建议字段 - -- 名称:明确任务类型 -- 描述:写清输入与输出 -- 系统指令:定义角色与规则 -- 参数:控制风格与长度 -- 输出格式:约束结果结构 - -## 示例:活动文案技能 - -```yaml -name: "活动文案生成" -description: "根据主题生成活动预热文案与发布文案" -system_prompt: | - 你是一名品牌内容策划,输出要简洁、有行动感。 -output_format: "markdown" -``` - -## 组合为流程 - -你可以把多个技能串成流程,例如: - -1. 选题拆解 -2. 初稿生成 -3. 风格统一 -4. 发布前检查 - -## 团队使用建议 - -1. 共享高频技能模板 -2. 每个技能指定维护人 -3. 定期清理低使用技能,保持列表可维护 diff --git a/docs/content/02.user-guide/12.settings.md b/docs/content/02.user-guide/12.settings.md deleted file mode 100644 index 4679c1de2..000000000 --- a/docs/content/02.user-guide/12.settings.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: 设置 -description: 管理应用偏好、导航模块和进阶系统选项 -navigation: - icon: i-heroicons-cog-6-tooth ---- - -# 设置 - -设置页用于管理你的创作体验与系统行为。 - -## 通用 - -常见选项: - -- 主题模式(浅色 / 深色 / 跟随系统) -- 语言选择 -- 启动行为(开机自启动、最小化到托盘) -- 声音反馈开关 - -## 创作与导航偏好 - -你可以按使用习惯定制入口: - -- 启用或停用工作区主题(如社媒、短视频、小说) -- 启用或停用导航模块(如 AI Agent、项目、资源、设置、插件) - -这样可以让侧边栏更聚焦,减少干扰。 - -## 连接与系统 - -系统相关设置在这里管理: - -- 连接与网络代理 -- 安全与证书 -- 存储目录与配额 -- 外部工具联动 -- 实验室与开发者选项 - -## 关于与版本 - -在“关于”标签页可以查看: - -- 当前版本号 -- 更新检查入口 -- 相关项目信息 - -## 建议配置 - -### 个人创作者 - -- 保留:AI Agent、项目、资源 -- 关闭:暂时不用的高级模块 -- 目的:让工作台聚焦在“日常产出” - -### 团队协作 - -- 统一主题配置 -- 固定项目命名规则 -- 约定资源标签方式 diff --git a/docs/content/02.user-guide/13.plugins.md b/docs/content/02.user-guide/13.plugins.md index 795b97f17..7cae16a1c 100644 --- a/docs/content/02.user-guide/13.plugins.md +++ b/docs/content/02.user-guide/13.plugins.md @@ -1,6 +1,6 @@ --- title: 插件中心 -description: 安装和管理扩展插件,按需扩展创作能力 +description: 通过本地包或 URL 安装、启停与卸载插件 navigation: icon: i-heroicons-puzzle-piece --- @@ -8,97 +8,66 @@ navigation: # 插件中心 ::alert{type="info"} -📢 插件属于进阶能力。若你只做日常创作,可先跳过本页。 +插件属于进阶能力。当前页面只覆盖已经落地的安装与管理链路,不再承诺“推荐插件市场”或“一键精选区”。 :: -插件中心用于扩展 Lime 的能力,例如新增工具、接入外部流程、扩展特定场景工作流。 +插件中心用于安装和管理扩展插件。当前可确认的主路径只有两条:从本地插件包安装,或从 URL 安装。 -## 访问插件中心 +## 当前可做的事 -点击左侧导航栏的「插件中心」进入插件管理页面。 - -## 你能做什么 - -- 浏览推荐插件并一键安装 -- 通过本地文件或 URL 安装插件包 -- 管理启用状态与卸载 -- 查看插件加载与执行状态 +- 从本地文件安装插件包 +- 从 URL 安装插件包 +- 查看 `已安装插件包` 与 `已加载插件` +- 启用、禁用、卸载、重新加载插件 +- 查看基础状态、最近错误与任务执行情况 ## 安装插件 -### 方式一:推荐插件一键安装 +### 从本地文件安装 -1. 在「推荐插件」区域找到想要的插件 -2. 点击「一键安装」 -3. 等待下载和安装完成 +1. 打开 `插件中心` +2. 点击 `安装插件` +3. 选择本地插件包 +4. 等待校验、解压和安装完成 -### 方式二:从 URL 安装 +当前文件安装支持: -1. 点击「安装插件」按钮 -2. 输入插件 ZIP 包的下载 URL -3. 点击「安装」 +- `.zip` +- `.tar.gz` +- `.tgz` -支持的 URL 格式: -- GitHub Release: `https://github.com/org/repo/releases/latest/download/plugin.zip` -- 直接下载链接: `https://example.com/plugin.zip` +### 从 URL 安装 -### 方式三:从本地文件安装 +1. 打开 `插件中心` +2. 点击 `安装插件` +3. 切换到 `URL` 页签 +4. 输入插件包直链并开始安装 -1. 点击「安装插件」按钮 -2. 点击「选择文件」 -3. 选择本地的 `.zip` 文件 -4. 点击「安装」 +当前 URL 安装接受 `http://` 或 `https://` 链接;如果用于团队分发,建议优先使用 `https://` 直链。 -## 使用建议 +## 安装时会校验什么 -### 从小处开始 +插件安装器会先做基础校验,再继续安装: -先安装 1 到 2 个高频插件,观察是否真正提升你的创作效率,再决定是否扩展更多插件。 +- 压缩包格式是否有效 +- 包内是否包含可解析的 `plugin.json` +- `name`、`version`、`entry` 等清单字段是否满足当前规则 +- 如果声明了 `hooks`,其命名是否满足当前格式限制 -### 明确用途 +通过校验后,插件会进入 `已安装插件包` 列表;是否真正加载成功,还要以 `已加载插件` 区域的状态为准。 -每个插件都应对应明确目的,例如: +## 日常管理 -- 扩展素材处理 -- 增加内容生成模板 -- 对接外部工作流 +你可以在插件中心完成这些操作: -## 管理插件 +- 启用或禁用已安装插件 +- 卸载不再需要的插件包 +- 手动重新加载插件 +- 查看插件状态、最近错误和基础执行信息 -### 启用/禁用 +如果某个插件声明了最低 Lime 版本要求,插件中心会给出版本提示;发布方是否兼容当前版本,仍应以实际安装和加载结果为准。 -在已加载插件列表中,点击电源图标可以启用或禁用插件。 +## 继续阅读 -### 卸载 - -1. 在「已安装插件包」列表中找到要卸载的插件 -2. 点击红色的删除按钮 -3. 确认卸载 - -卸载会删除插件文件和配置,但不会删除插件产生的数据。 - -## 进阶阅读 - -- [开放平台 - 总览](/open-platform/overview) -- [开放平台 - 插件中心](/open-platform/plugins) -- [开放平台 - 插件开发](/open-platform/plugin-development) - -## 常见问题 - -### 插件安装失败 - -1. 检查网络连接 -2. 确认 URL 正确且可访问 -3. 检查 ZIP 包格式是否正确 - -### 插件无法加载 - -1. 检查 Lime 版本是否满足插件要求 -2. 查看日志了解详细错误信息 -3. 尝试重新安装插件 - -### 二进制插件权限问题 - -部分二进制插件需要管理员权限: -- **Windows**: 以管理员身份运行 Lime -- **macOS/Linux**: 插件会提示需要的权限 +- [插件打包指南](/open-platform/plugin-development) +- [扩展接入概览](/open-platform/overview) diff --git a/docs/content/02.user-guide/14.resources.md b/docs/content/02.user-guide/14.resources.md deleted file mode 100644 index cce5f23b5..000000000 --- a/docs/content/02.user-guide/14.resources.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: 资源库 -description: 管理项目中的文档、图片、语音和视频素材 -navigation: - icon: i-heroicons-folder-open ---- - -# 资源库 - -资源库是 Lime 的创作资产中心。 -它和项目绑定,用来长期沉淀你的创作结果。 - -## 资源分类 - -资源页支持按分类查看: - -- 全部 -- 文档 -- 图片 -- 语音 -- 视频 - -当你只想找图或找文档时,直接切换分类即可。 - -## 常见操作 - -### 新建与上传 - -1. 选择左侧资源库(项目) -2. 新建文件夹或新建文档 -3. 上传本地文件到当前目录 - -### 搜索与排序 - -- 支持按名称、描述、标签搜索 -- 支持按更新时间、创建时间、名称排序 - -### 重命名与删除 - -在资源列表的操作菜单中,可对资源进行重命名、删除等操作。 - -## 资源与创作联动 - -### 从 Claw 与图片任务回流资源库 - -在 Claw 中发起图片生成任务,或从图片任务结果执行入库后,成功生成的图片会自动写入当前项目。 - -资料库的图片视图还统一承接: - -- 本地图片上传 -- 我的图片库浏览 -- 选图后插入当前画布 - -### 从资源继续对话创作 - -在资源页选中素材后,可继续进入 AI Agent 进行改写、扩写或二次创作。 - -## 常见问题 - -### 为什么看不到某些图片? - -先确认: - -1. 当前选择的是否是正确资源库(项目) -2. 是否切到了“图片”分类 -3. 文件后缀或 MIME 类型是否被识别为图片 - -### 为什么资源数量和预期不一致? - -常见原因是“分类过滤”或“项目切换”导致显示范围变化。 -建议先切换到“全部”分类再确认总量。 diff --git a/docs/content/02.user-guide/15.image-generation.md b/docs/content/02.user-guide/15.image-generation.md deleted file mode 100644 index 3847274e1..000000000 --- a/docs/content/02.user-guide/15.image-generation.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: 图片生成与素材链路 -description: 通过 Claw 与资源库完成搜图、图片生成、编辑与资产沉淀 -navigation: - icon: i-heroicons-photo ---- - -# 图片生成与素材链路 - -Lime 不再把图片能力拆成独立页面。 -现在的事实源是: - -- Claw:负责联网搜图、图片生成、参考图编辑和任务推进 -- 资源库:负责本地图片上传、我的图片库浏览、结果沉淀和插图复用 -- 设置:负责图片模型、Provider 与联网搜图 Key 配置 - -## 基本流程 - -1. 在 AI Agent 中明确视觉目标 -2. 需要找参考图时,用 Claw `@素材` 进行联网搜图 -3. 需要生成或编辑图片时,在 Claw 发起对应图片任务 -4. 结果自动或手动沉淀到资源库 -5. 在资源库图片视图继续筛选、上传、插图或复用 - -## 联网搜图与生成 - -### 联网搜图 - -当你需要灵感图、风格参考或可复用素材时: - -- 在 Claw 中使用 `@素材` -- 联网图片搜索结果会以任务结果或素材候选的形式返回 -- 选中的图片可以继续进入正文插图、封面或图片任务链路 - -### 图片生成与编辑 - -当你已经明确提示词或参考图后: - -- 在 Claw 发起图片生成任务 -- 如模型支持参考图编辑,系统会优先走编辑链路 -- 若某条接口不可用,运行时会回退到可用生成链路,尽量保障出图成功率 - -## 本地图片与我的图片库 - -本地图片与历史沉淀图片已经统一收口到资源库图片视图,你可以在这里: - -- 上传本地图片 -- 浏览“我的图片库” -- 选图后直接插入当前画布 -- 在当前项目下统一管理图片资产 - -## 与资源库联动 - -### 结果回流 - -图片任务会根据当前项目和资源库选择自动回流;如果需要,也可以在结果完成后再手动入库。 - -### 插图复用 - -进入资源库的图片可以直接被当前画布复用,不需要再回到旧图片页面挑选。 - -## 配置入口 - -相关配置分布在两个位置: - -- 图片模型与默认策略:设置中的媒体服务配置 -- 联网图片搜索 Key:设置中的网络搜索配置 - -## 实用建议 - -### 先定方向再出图 - -先在 AI Agent 里明确画面目标,再决定是 `@素材` 搜图还是直接发起图片任务,会减少无效尝试。 - -### 一次只改一个变量 - -每轮仅调整一个维度(提示词、比例、参考图),更容易稳定收敛到理想结果。 - -### 把可用版本及时入库 - -选中可用图片后尽快入库,方便后续在资源页检索、插图和复用。 diff --git a/docs/content/02.user-guide/16.gateway-tunnel-webhook.md b/docs/content/02.user-guide/16.gateway-tunnel-webhook.md index acbb4d637..a4fb00bff 100644 --- a/docs/content/02.user-guide/16.gateway-tunnel-webhook.md +++ b/docs/content/02.user-guide/16.gateway-tunnel-webhook.md @@ -25,8 +25,8 @@ cloudflared --version 2. 已准备 Cloudflare 账号和域名(若使用固定域名) 3. 飞书应用已创建,拿到 `App ID` 与 `App Secret` -> 桌面端已支持在「渠道管理 > Gateway 公共隧道」中直接点击: -> `检测 cloudflared`、`一键安装 cloudflared`(支持 macOS / Windows / Ubuntu 等常见 Linux 发行版)。 +> 当前界面已支持在「渠道管理 > Gateway 公共隧道」中直接点击: +> `检测 cloudflared`、`一键安装 cloudflared`。安装动作会按当前系统检测到的包管理器环境执行,例如 `brew`、`winget`、`apt-get`、`dnf`、`yum`、`scoop` 或 `choco`。 ## 步骤 1:配置 Gateway 公共隧道 @@ -65,6 +65,11 @@ Cloudflare 相关字段(二选一): - 将飞书渠道切换为 `webhook` 模式 - 回填飞书 `webhook_host/webhook_port/webhook_path` +注意: + +- 当前同步动作只支持 `feishu` +- 同步前需要已经拿到 `public_base_url`,或已填写可推导公网地址的 `DNS Name` + ## 步骤 3:启动隧道并验证状态 在 Gateway 公共隧道卡片依次点击: @@ -150,9 +155,9 @@ Cloudflare 相关字段(二选一): 桌面端建议按环境选择: 1. `managed`(应用内托管,默认) - 由 Lime 在启动后自动拉起 tunnel,并定时检查进程状态;异常退出会自动重拉。 + Lime 启动后会启动守护逻辑,约每 `10` 秒检查一次 tunnel 状态;若隧道异常退出且不是手动停止,守护器会尝试重新拉起。 2. `external`(系统级常驻,生产更稳) - 由系统服务管理 `cloudflared`,Lime 仅做状态诊断与 webhook 同步。 + 由系统服务管理 `cloudflared`,Lime 只做状态诊断与 webhook 同步,不负责应用内启动。 ### 何时用 external @@ -160,6 +165,10 @@ Cloudflare 相关字段(二选一): - 本机网络波动较大,应用重启不希望影响 tunnel - 需要把 tunnel 运维与桌面应用生命周期解耦 +补充说明: + +- 如果你在 `managed` 模式下手动点过 `停止`,守护器不会立刻自动再拉起,需手动重新 `启动` 或 `重启` + ### 常见连通性检查 ```bash diff --git a/docs/content/02.user-guide/17.runtime-agents.md b/docs/content/02.user-guide/17.runtime-agents.md index 9ce44a5df..061cd1865 100644 --- a/docs/content/02.user-guide/17.runtime-agents.md +++ b/docs/content/02.user-guide/17.runtime-agents.md @@ -1,164 +1,101 @@ --- title: 运行时 AGENTS 规则 -description: 使用 `~/.lime/AGENTS.md` 与 Workspace `.lime/AGENTS.md` 为 Lime 运行时会话提供稳定指令 +description: 用 `.lime/AGENTS.md` 体系为 Lime 运行时会话提供指令 navigation: icon: i-heroicons-document-text --- # 运行时 AGENTS 规则 -Lime 应用运行时会话现在默认读取 `.lime/AGENTS.md` 体系,而不是仓库根的 `AGENTS.md`。 +Lime 应用运行时会话不读取仓库根 `AGENTS.md`,而是使用 `.lime/AGENTS.md` 体系。 -你也可以在「设置 → 记忆」里点击按钮,显式生成全局、Workspace 或本机私有模板文件。 -如果是本机私有模板,还可以继续点击按钮,把 `.lime/AGENTS.local.md` 一键加入 Workspace 的 `.gitignore`。 -首次创建新项目后,Lime 也会弹出一个非强制提示,允许你直接一键初始化这两个 Workspace 模板。 +## 当前事实源 -这让“开发 Lime 源码仓库本身的规则”和“Lime 应用实际运行时的规则”彻底分开: +运行时 AGENTS 相关能力当前分成两层: -- 仓库根 `AGENTS.md`:给外部 AI 编辑器或源码协作使用 -- `~/.lime/AGENTS.md`:你的全局运行时偏好 -- `/.lime/AGENTS.md`:当前项目 / 工作区的运行时规则 +1. 运行时 AGENTS 主层 -## 加载顺序 +- 全局:`~/.lime/AGENTS.md` +- 工作区:`/.lime/AGENTS.md` -Lime 运行时会话默认按下面顺序加载: +这两层会直接进入 Lime 运行时 AGENTS 提示拼接。 -1. 全局:`~/.lime/AGENTS.md` -2. 工作区:`/.lime/AGENTS.md` - -如果你保留默认记忆来源设置,Lime 还会继续把下面这个文件作为**本机私有补充**读取: +2. 本机私有补充层 - `/.lime/AGENTS.local.md` -推荐做法: +这层默认通过记忆来源配置进入当前 workspace 的有效记忆,不会向父目录递归查找。 -- 把长期个人偏好写进 `~/.lime/AGENTS.md` -- 把项目约束写进 `/.lime/AGENTS.md` -- 把不想提交到仓库的本机补充写进 `/.lime/AGENTS.local.md` +## 当前加载口径 -## 什么时候用哪个文件 +默认情况下,可以按下面这条顺序理解: -### `~/.lime/AGENTS.md` +1. 先读全局:`~/.lime/AGENTS.md` +2. 再读工作区:`/.lime/AGENTS.md` +3. 如果保留默认记忆来源配置,再把 `/.lime/AGENTS.local.md` 作为本机私有补充带入 -适合放所有项目都通用的偏好,例如: +推荐分工: -- 统一回复语言 -- 默认输出结构 -- 常用代码风格 -- 你长期偏好的解释方式 +- `~/.lime/AGENTS.md` + - 放长期个人偏好 +- `/.lime/AGENTS.md` + - 放团队共享的项目规则 +- `/.lime/AGENTS.local.md` + - 放不想提交到仓库的本机补充 -直接复制下面模板即可: +## 在哪里生成模板 -```md -# 我的全局 Lime 运行时规则 +当前在 `设置 → 记忆` 页面可以显式生成这些模板: -## 回复习惯 +- 全局模板 +- Workspace 模板 +- Workspace 本机模板 -- 默认使用中文简体 -- 先给结论,再给关键步骤 -- 没必要时保持简洁,不要过度展开 +如果是本机模板,还可以继续一键把 `.lime/AGENTS.local.md` 写入当前 Workspace 的 `.gitignore`。 -## 工程偏好 +## 新项目提示 -- 优先选择 KISS 方案 -- 优先修根因,不做表面补丁 -- 先说明影响范围,再做改动 +首次创建新项目后,Lime 会弹出一个非强制提示,允许你一键初始化: -## 代码风格 +- `.lime/AGENTS.md` +- `.lime/AGENTS.local.md` -- 尽量沿用现有项目风格 -- 避免无关重构 -- 没有明确收益时,不新增抽象层 -``` - -## Workspace `.lime/AGENTS.md` - -适合放当前项目独有的规则,例如: - -- 仓库使用的语言 -- 文档与注释风格 -- 目录边界 -- 测试、构建、提交前检查要求 - -把下面内容保存为工作区内的 `.lime/AGENTS.md`: - -```md -# 当前项目运行时规则 - -## 项目背景 - -- 这是一个 React + Rust + Tauri 项目 -- 前端使用 TypeScript -- 回答和文档默认使用中文简体 - -## 修改原则 - -- 先读后写 -- 只改当前任务直接相关内容 -- 保持现有目录结构和命名习惯 - -## 验证要求 - -- 前端改动后优先跑相关前端测试 -- Rust 改动后优先跑相关单测 -- 若无法完整验证,需要明确说明未验证部分 - -## 禁止事项 - -- 不要把临时排障脚本提交进仓库 -- 不要修改与当前任务无关的配置 -- 不要默认进行 git commit 或 push -``` - -## `.lime/AGENTS.local.md` 示例 - -如果你想保留**只在自己机器生效**的补充规则,可以新建 `.lime/AGENTS.local.md`,并把它加入 `.gitignore`。 - -例如: - -```md -# 本机私有补充 - -- 优先使用本机已安装的 Node 与 Rust 工具链 -- 如需浏览器调试,优先使用本机开发配置 -- 涉及大体量编译时,先做定向测试再跑全量 -``` - -## 推荐目录结构 - -```text -workspace-root/ -├─ .lime/ -│ ├─ AGENTS.md -│ └─ AGENTS.local.md -├─ src/ -├─ src-tauri/ -└─ ... -``` - -你的全局文件位于: - -```text -~/.lime/AGENTS.md -``` +同时自动补 `.gitignore` 的本机模板忽略规则。 ## 注意事项 - Lime 运行时不会读取仓库根 `AGENTS.md` -- Workspace `.lime/AGENTS.md` 只读取当前 workspace,不会向父目录递归回溯 +- `.lime/AGENTS.md` 与 `.lime/AGENTS.local.md` 都只看当前 workspace 根目录 - 如果团队要共享规则,请提交 `.lime/AGENTS.md` - 如果规则只属于你自己,请放进 `.lime/AGENTS.local.md` -## 推荐起步模板 +## 最小示例 -如果你想先快速用起来,最小可用版本可以直接写: +`~/.lime/AGENTS.md` ```md -# Lime 运行时规则 +# 我的全局 Lime 运行时规则 - 默认使用中文简体 -- 先给结论,再展开说明 -- 保持简洁,优先可执行建议 -- 修改代码时先读后写 -- 只改当前任务相关内容 +- 先给结论,再给关键步骤 +- 没必要时保持简洁 +``` + +`/.lime/AGENTS.md` + +```md +# 当前项目运行时规则 + +- 先读后写 +- 只改当前任务直接相关内容 +- 若无法完整验证,需要明确说明 +``` + +`/.lime/AGENTS.local.md` + +```md +# 本机私有补充 + +- 优先使用本机已安装工具链 +- 涉及大体量编译时先跑定向测试 ``` diff --git a/docs/content/02.user-guide/2.monitoring.md b/docs/content/02.user-guide/2.monitoring.md deleted file mode 100644 index 3fdc530f9..000000000 --- a/docs/content/02.user-guide/2.monitoring.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: 创作数据与监控 -description: 查看创作产出趋势、调用状态与问题定位信息 -navigation: - icon: i-heroicons-eye ---- - -# 创作数据与监控 - -监控页帮助你回答三个问题: - -1. 最近创作是否稳定 -2. 哪些任务成功率更高 -3. 出现异常时该从哪里排查 - -## 你能看到什么 - -### 概览指标 - -常见指标包括: - -- 请求总量与成功率 -- 平均响应耗时 -- 活跃连接数量 -- 近期错误趋势 - -### 趋势视图 - -你可以按时间查看: - -- 调用量变化 -- 成功率变化 -- 延迟波动 - -这能帮助你判断问题是偶发,还是持续性异常。 - -## 日志排查 - -当某次生成失败时,优先看请求日志: - -1. 找到失败时间点 -2. 查看模型与请求参数 -3. 对照错误信息定位问题(超时、认证、限流等) - -## 对创作者最有用的用法 - -### 判断工作流是否健康 - -如果成功率持续下降,建议先减少并发任务,确认连接状态后再恢复批量生成。 - -### 对比不同创作任务 - -同样是生成任务,不同主题的耗时差异可能很大。通过趋势图可以更快选择稳定方案。 - -### 复盘高峰时段 - -高峰期(例如集中出图)出现波动时,可根据日志回看是否需要拆分任务批次。 - -## 数据导出 - -如果你需要做团队复盘,可导出统计数据用于周报或复盘记录。 diff --git a/docs/content/02.user-guide/3.credential-pool.md b/docs/content/02.user-guide/3.credential-pool.md deleted file mode 100644 index c7e0a5075..000000000 --- a/docs/content/02.user-guide/3.credential-pool.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: 模型连接与账号 -description: 管理模型连接方式与多账号状态(进阶) -navigation: - icon: i-heroicons-key ---- - -# 模型连接与账号 - -::alert{type="info"} -这是进阶页。普通创作者可直接使用默认连接能力,按需再回来配置。 -:: - -该页面用于管理模型连接与账号状态,适合以下场景: - -- 你有多个账号需要统一管理 -- 你需要手动添加 API Key -- 你希望在连接异常时快速排查 - -## 常见连接方式 - -### 自动检测 - -应用会尝试检测本地常见凭证文件,检测成功后可直接使用。 - -### 手动添加 - -如果自动检测失败,可手动添加: - -1. 选择连接类型 -2. 填写必要凭证信息 -3. 保存后执行连接测试 - -## 账号状态说明 - -- 可用:可正常调用 -- 即将过期:建议尽快刷新 -- 已失效:需重新登录或更新凭证 -- 未验证:建议先执行测试 - -## 多账号使用建议 - -### 日常创作 - -保留 1 到 2 个稳定账号即可,优先保证可用性。 - -### 高强度创作 - -如果你需要长时间连续生成,可配置多个账号做冗余,降低单点失败影响。 - -## 安全建议 - -1. 不在聊天记录或公开文档里粘贴密钥 -2. 定期清理失效连接 -3. 导出配置时确认敏感信息不会被带出 diff --git a/docs/content/02.user-guide/4.configuration-example.md b/docs/content/02.user-guide/4.configuration-example.md deleted file mode 100644 index 519d566f3..000000000 --- a/docs/content/02.user-guide/4.configuration-example.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: 进阶配置示例 -description: 按创作场景选择配置思路(示例) -navigation: - icon: i-heroicons-document-text ---- - -# 进阶配置示例 - -::alert{type="info"} -本页示例用于说明配置思路,不要求你逐字段照抄。具体字段以应用设置界面为准。 -:: - -## 示例 1:个人创作者(推荐起步) - -目标:少配置、快开始。 - -```yaml -profile: "solo-content" -navigation: - enabled: - - agent - - projects - - resources - - image-gen -themes: - enabled: - - general -``` - -适用:统一通用工作台入口,按项目内容继续细分任务。 - -## 示例 2:团队协作 - -目标:统一入口和主题,降低沟通成本。 - -```yaml -profile: "team-content" -navigation: - enabled: - - agent - - projects - - resources - - tools -themes: - enabled: - - general -resource: - naming: "project-date-version" -``` - -适用:品牌运营、活动策划、小团队协作的统一工作台配置。 - -## 示例 3:API 缓存策略(高级) - -目标:精确控制哪些响应状态码参与短时缓存(非流式)。 - -```yaml -server: - host: "127.0.0.1" - port: 8999 - api_key: "your-api-key" - response_cache: - enabled: true - ttl_secs: 600 - max_entries: 200 - max_body_bytes: 1048576 - cacheable_status_codes: [200] # 默认仅缓存 200;可按需扩展 [200, 201] -``` - -适用:对缓存命中与语义一致性有要求的自动化/API 调用场景。 - -## 示例 4:运行时诊断接口(高级) - -目标:像 ClawRouter 一样快速查看网关健康、缓存与统计信息。 - -```bash -# 基础健康检查(兼容旧行为) -curl "http://127.0.0.1:8999/health" - -# 扩展健康检查(包含完整诊断) -curl "http://127.0.0.1:8999/health?full=true" - -# 响应缓存配置与命中统计 -curl "http://127.0.0.1:8999/cache" - -# 统计诊断(默认最近 7 天,可传 days=1~30) -curl "http://127.0.0.1:8999/stats?days=7" - -# 查看请求级调试头(缓存/去重/幂等等状态) -curl -i "http://127.0.0.1:8999/v1/chat/completions" \ - -H "Authorization: Bearer your-api-key" \ - -H "Content-Type: application/json" \ - -d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"ping"}]}' -``` - -适用:排查“为什么慢/为什么回退/是否命中缓存”等线上联调问题。 - -可观测调试头示例: -- `x-lime-request-id` -- `x-lime-cache`(`hit/store/skip-*`) -- `x-lime-dedup`(`replay/wait-replay/new/removed-on-error`) -- `x-lime-idempotency`(`replay/in-progress/new/removed-on-error`) -- `x-lime-requested-provider` / `x-lime-effective-provider` / `x-lime-model` - -## 调整顺序建议 - -1. 先确认导航与主题 -2. 再确认连接与稳定性 -3. 最后再做自动化与诊断扩展 diff --git a/docs/content/02.user-guide/4.smart-routing.md b/docs/content/02.user-guide/4.smart-routing.md deleted file mode 100644 index 0b4dd7233..000000000 --- a/docs/content/02.user-guide/4.smart-routing.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: 模型分发规则 -description: 按任务类型将请求分发到不同模型(进阶) -navigation: - icon: i-heroicons-arrows-right-left ---- - -# 模型分发规则 - -::alert{type="info"} -这是进阶能力。只有在“多模型并行使用”时才需要配置。 -:: - -分发规则用于把不同任务自动交给更合适的模型。 - -## 什么时候需要它 - -- 文本创作和图片任务使用不同模型 -- 同一主题需要“快速草稿 + 高质量润色”两种路径 -- 你希望把高成本任务限制在特定模型上 - -## 常见策略 - -### 按任务类型分发 - -- 长文写作走高质量模型 -- 快速问答走低延迟模型 -- 图片任务走图片专用模型 - -### 按阶段分发 - -- 初稿阶段:速度优先 -- 定稿阶段:质量优先 - -### 按兜底分发 - -主模型异常时,自动回退到备用模型。 - -## 示例(示意) - -```yaml -routes: - - pattern: "video-script-*" - provider: "primary" - model: "high-quality-model" - priority: 10 - - pattern: "quick-*" - provider: "fast-lane" - model: "fast-model" - priority: 20 - - pattern: "*" - provider: "fallback" - priority: 100 -``` - -## 配置建议 - -1. 先只配 2 到 3 条关键规则 -2. 给兜底规则留最后优先级 -3. 每次改完都做一次路由测试 - -## 常见误区 - -- 规则过多导致难以维护 -- 没有兜底规则,异常时直接失败 -- 频繁改规则但不做回归测试 diff --git a/docs/content/02.user-guide/5.resilience.md b/docs/content/02.user-guide/5.resilience.md deleted file mode 100644 index 26f207841..000000000 --- a/docs/content/02.user-guide/5.resilience.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: 稳定性与容错 -description: 在高强度创作下保持调用稳定(进阶) -navigation: - icon: i-heroicons-shield-check ---- - -# 稳定性与容错 - -::alert{type="info"} -这是进阶能力。只有在你频繁遇到超时、失败、波动时才需要细调。 -:: - -稳定性配置的核心目标是: - -- 少失败 -- 失败后可恢复 -- 出错时可定位 - -## 三个关键参数 - -### 重试 - -用于处理偶发失败。 - -建议: - -- 最大重试次数:2 到 3 次 -- 首次重试延迟:1 秒左右 -- 使用递增退避,避免短时间反复打满请求 - -### 超时 - -用于避免单次请求长时间卡住。 - -建议: - -- 普通文本任务:较短超时 -- 长文或复杂任务:适当放宽 -- 图片任务:通常需要更长超时 - -### 故障回退 - -主连接失败后自动走备用连接,减少中断。 - -## 推荐调参顺序 - -1. 先调超时 -2. 再调重试 -3. 最后配置回退策略 - -## 诊断建议 - -### 连续失败 - -优先检查: - -1. 连接状态是否可用 -2. 当前模型是否可调用 -3. 是否触发限流 - -### 偶发失败 - -通常先提高重试效果更明显。 - -### 高峰波动 - -建议拆分任务批次,避免同一时刻大量并发。 diff --git a/docs/content/02.user-guide/6.config-management.md b/docs/content/02.user-guide/6.config-management.md deleted file mode 100644 index 9cc38a7cf..000000000 --- a/docs/content/02.user-guide/6.config-management.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: 配置管理与迁移 -description: 导出、导入、备份与跨设备迁移配置 -navigation: - icon: i-heroicons-document-duplicate ---- - -# 配置管理与迁移 - -配置管理适合两类人: - -- 想把当前工作台快速迁移到另一台设备 -- 团队内需要统一一套基础配置 - -## 导出配置 - -你可以将当前设置导出为配置文件,常用于备份和迁移。 - -常见导出内容: - -- 主题与导航偏好 -- 部分连接与路由策略 -- 稳定性相关参数 - -::alert{type="warning"} -导出文件通常不包含敏感凭证信息。导入后需重新检查连接状态。 -:: - -## 导入配置 - -1. 在设置页选择导入 -2. 预览配置差异 -3. 选择覆盖或合并策略 -4. 导入后做一次连接与功能自检 - -## 备份建议 - -### 个人用户 - -至少保留最近 2 到 3 份配置备份。 - -### 团队用户 - -建议按版本管理配置文件,例如: - -- `team-config-v1.yaml` -- `team-config-v1.1.yaml` - -## 跨设备迁移清单 - -1. 导出配置文件 -2. 在新设备导入配置 -3. 重新校验连接状态 -4. 检查主题、导航、资源路径是否符合预期 -5. 进行一次完整创作演练 - -## 什么时候需要重置 - -当你长期调参后“越调越乱”,最稳妥的方式是: - -1. 先备份当前配置 -2. 恢复到基础配置 -3. 只按必要场景逐项开启进阶能力 diff --git a/docs/content/02.user-guide/7.config-switch.md b/docs/content/02.user-guide/7.config-switch.md deleted file mode 100644 index 87daf1c1a..000000000 --- a/docs/content/02.user-guide/7.config-switch.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: 工作模式切换 -description: 在不同创作场景间快速切换配置 -navigation: - icon: i-heroicons-arrows-up-down ---- - -# 工作模式切换 - -如果你在不同场景下有明显不同的工作方式,可以使用配置档案快速切换。 - -## 典型模式 - -### 日更模式 - -- 目标:快速产出 -- 适合:社媒短内容、灵感快写 -- 特点:速度优先、流程简化 - -### 深度创作模式 - -- 目标:质量优先 -- 适合:长文、小说章节、方案定稿 -- 特点:更强调结构和多轮迭代 - -### 出图冲刺模式 - -- 目标:集中生成并沉淀图片素材 -- 适合:活动海报、视觉素材周更 -- 特点:图片相关入口前置、资源回流优先 - -## 建议的档案字段 - -每个档案建议包含: - -- 启用的导航模块 -- 启用的工作区主题 -- 关键连接与稳定性偏好 - -## 切换步骤 - -1. 选择目标档案 -2. 应用后检查核心入口是否符合预期 -3. 用一个小任务做快速验证 - -## 使用建议 - -1. 档案数量控制在 3 个以内 -2. 一个档案只服务一个明确场景 -3. 变更档案后记录用途,避免后续混乱 diff --git a/docs/content/02.user-guide/9.mcp.md b/docs/content/02.user-guide/9.mcp.md index a4c78550a..999d1fa9c 100644 --- a/docs/content/02.user-guide/9.mcp.md +++ b/docs/content/02.user-guide/9.mcp.md @@ -1,53 +1,82 @@ --- title: MCP 工具扩展 -description: 让 AI 调用外部工具与资源(进阶) +description: 管理 MCP 服务器配置,并浏览可用 Tools、Prompts 与 Resources navigation: icon: i-heroicons-puzzle-piece --- # MCP 工具扩展 -MCP 可以让 AI 不只“回答问题”,还可以调用外部工具完成动作。 - ::alert{type="info"} -这是进阶能力。建议先熟悉基础创作流程,再接入 MCP。 +MCP 属于进阶能力,当前仍应按实验功能理解。它不会替代 Lime 的主创作路径,更适合已经明确需要外部工具或资源接入的场景。 :: -## 适合的场景 +当前 Lime 已提供 MCP 服务器管理与运行时浏览面板。你可以集中维护服务器配置,把它同步到常用外部工具,并在 Lime 内验证可用的 Tools、Prompts 和 Resources。 -- 让 AI 读取指定目录素材 -- 连接外部知识源或服务 -- 把重复操作做成可调用工具 +## 当前可做的事 -## 基本使用流程 +- 新增、编辑、删除 MCP 服务器配置 +- 使用预设快速创建常见服务器 +- 从 Claude、Codex、Gemini CLI 导入已有 MCP 配置 +- 将当前配置同步回外部应用 +- 查看服务器运行状态并手动启动、停止 +- 浏览运行中服务器暴露的 Tools、Prompts、Resources -1. 添加 MCP 服务器配置 -2. 启动并确认连接状态 -3. 在工具列表里验证可用工具 -4. 在实际任务里小范围试跑 - -## 一个简单示例 +## 一个最小配置示例 ```json { - "mcpServers": { - "filesystem": { - "command": "npx", - "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/workspace"] - } - } + "command": "npx", + "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/workspace"], + "env": {} } ``` +如果你只是想先验证链路,`filesystem` 是最容易起步的示例。 + +## 推荐使用流程 + +1. 先选择一种来源 + +- 直接新建服务器配置 +- 从 Claude、Codex、Gemini CLI 导入已有配置 + +2. 再决定同步范围 + +- 只在 Lime 内启用 +- 或同步到 Claude、Codex、Gemini CLI 一起使用 + +3. 保存后验证运行状态 + +- 确认服务器能正常启动 +- 确认 Lime 能读取到对应能力列表 + +4. 最后做小范围试跑 + +- 先试一个简单 Tool +- 再验证 Prompt 或 Resource 是否符合预期 + +## 当前常见入口 + +当前面板已经内置一些常见预设,适合快速起步: + +- `Filesystem` +- `GitHub` +- `PostgreSQL` +- `自定义` + +如果团队已有现成配置,优先导入;如果只是单机试验,优先从最小自定义或 `Filesystem` 开始。 + ## 安全边界建议 -1. 只授权必要目录和资源 -2. 敏感环境变量不要硬编码在公开配置里 -3. 新工具先在测试项目验证 +1. 只给服务器开放必要目录、数据库或环境变量 +2. 新接入的 MCP 先在测试目录验证,不要直接连生产数据 +3. 对外同步前,先确认对应应用确实需要这台服务器 +4. 涉及密钥时,避免把敏感值直接写进会提交的公共配置 ## 排错顺序 -1. 看连接状态是否正常 -2. 看工具是否成功注册 -3. 看调用参数是否符合工具定义 -4. 看服务器日志定位具体错误 +1. 先看服务器配置 JSON 是否有效 +2. 再看服务器是否能成功启动 +3. 再看 Tools、Prompts、Resources 是否已被正确发现 +4. 最后再检查具体调用参数、环境变量和外部依赖 diff --git a/docs/content/03.providers/1.overview.md b/docs/content/03.providers/1.overview.md index bfc7f8d67..e8532cfab 100644 --- a/docs/content/03.providers/1.overview.md +++ b/docs/content/03.providers/1.overview.md @@ -1,6 +1,6 @@ --- title: 模型连接概览 -description: 了解不同连接方式,并按你的创作目标选择 +description: 连接文档重建中,当前只保留应用内 Provider 与凭证入口说明 navigation: icon: i-heroicons-squares-2x2 --- @@ -8,62 +8,33 @@ navigation: # 模型连接概览 ::alert{type="info"} -本章节属于进阶内容。普通创作者可先使用默认连接,只有在需要多账号或精细控制时再深入配置。 +Provider 文档正在按 LimeNext V2 current 连接入口重建。 :: -Lime 支持多种模型连接方式,你可以按自己的使用习惯选择。 +旧版按单个 Provider 拆分、并以 `credential_pool:` / `routing:` YAML 为主的配置页已下线,避免继续传播已经偏离 current UI 的旧配置方式。 -## 两类连接方式 +## 当前事实源 -### 自动连接(推荐) +当前模型连接能力以应用内 `Provider 与凭证` 入口为准,主要收敛到以下几类: -适合希望“少配置、快开始”的用户: +- `服务商` + 默认主入口。 + 先补可用 API Key,再读取真实模型目录、做连接验证,并校准默认模型与兼容协议 +- `中转服务` + 对应 Lime Connect。 + 浏览已验证中转商,获取 API Key 后通过 `lime://connect` 深链一键带入凭证池 +- `语音服务` + 单独管理语音相关 Provider +- `OAuth 凭证` + 管理 Kiro、Gemini、Antigravity、Codex、Claude OAuth 等登录型凭证 -- 登录对应客户端后自动识别 -- 日常创作可直接使用 +## 当前建议 -### 手动连接 +1. 默认先从 `服务商` 分类补可用 API Key +2. 只有需要登录型凭证时,再进入 `OAuth 凭证` +3. 需要浏览中转商时,再进入 `中转服务` +4. 不再以旧 YAML 配置文档作为日常配置入口 -适合有明确工程需求的用户: +## 后续说明 -- 手动填写 API Key -- 自定义 Base URL -- 多账号并行管理 - -## 如何选择 - -### 追求稳定创作 - -优先选择你最常用、最稳定的连接方式,保持单一主连接即可。 - -### 追求多模型组合 - -可按任务分配不同连接,例如: - -- 长文与定稿使用质量优先模型 -- 快速草稿与批量任务使用速度优先模型 -- 图片任务使用视觉能力更强的模型 - -### 追求高可用 - -可配置多个连接作为冗余,避免单点失败影响创作。 - -## 配置建议 - -1. 先完成一个主连接并测试可用 -2. 再按场景增加备用连接 -3. 每次新增连接后做一次小任务验证 - -## 下一步 - -按你的连接类型进入对应页面: - -- [Kiro Claude](/providers/kiro-claude) -- [Gemini CLI](/providers/gemini-cli) -- [Qwen](/providers/qwen) -- [Codex](/providers/codex) -- [iFlow](/providers/iflow) -- [OpenAI Custom](/providers/openai-custom) -- [Claude Custom](/providers/claude-custom) -- [Gemini API Key](/providers/gemini-api-key) -- [Vertex AI](/providers/vertex-ai) +后续如果恢复单个 Provider 的对外文档,应直接按 current 表单、模型发现、连接校验与导入流程重写,而不是回收旧 `content/providers/*` 页面。 diff --git a/docs/content/03.providers/10.vertex-ai.md b/docs/content/03.providers/10.vertex-ai.md deleted file mode 100644 index bc742430c..000000000 --- a/docs/content/03.providers/10.vertex-ai.md +++ /dev/null @@ -1,197 +0,0 @@ ---- -title: Vertex AI -description: Google Cloud Vertex AI Provider 配置 -navigation: - icon: i-heroicons-cloud ---- - -# Vertex AI Provider - -::alert{type="info"} -本页属于进阶连接配置。若你已能正常创作,可先跳过。 -:: - -使用 API Key 访问 Google Cloud Vertex AI 服务,支持模型别名映射。 - -## 概述 - -Vertex AI Provider 允许你: -- 使用 API Key 访问 Vertex AI 兼容端点 -- 配置模型别名映射 -- 多账号负载均衡 -- 为每个 Key 单独配置代理 - -## 支持的模型 - -- Gemini 2.0 系列 -- Gemini 1.5 系列 -- 其他 Vertex AI 支持的模型 - -## 配置 - -### 基础配置 - -```yaml -credential_pool: - vertex_api_keys: - - id: "vertex-main" - api_key: "vk-123..." - base_url: "https://example.com/api" - disabled: false -``` - -### 完整配置 - -```yaml -credential_pool: - vertex_api_keys: - - id: "vertex-main" - api_key: "vk-123..." - base_url: "https://example.com/api" - proxy_url: "socks5://proxy:1080" - models: - - name: "gemini-2.0-flash" - alias: "vertex-flash" - - name: "gemini-1.5-pro" - alias: "vertex-pro" - disabled: false -``` - -### 配置项说明 - -| 配置项 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| id | string | ✅ | 凭证唯一标识 | -| api_key | string | ✅ | Vertex AI API Key | -| base_url | string | ❌ | Vertex AI 端点 URL | -| proxy_url | string | ❌ | 单独的代理 URL | -| models | array | ❌ | 模型别名映射列表 | -| disabled | boolean | ❌ | 是否禁用此凭证 | - -## 模型别名 - -### 工作原理 - -模型别名允许你使用自定义名称访问上游模型: - -1. 客户端请求别名(如 `vertex-flash`) -2. Lime 将别名解析为上游模型名(如 `gemini-2.0-flash`) -3. 使用上游模型名发送请求 -4. 响应中保留客户端请求的别名 - -### 配置示例 - -```yaml -models: - - name: "gemini-2.0-flash" # 上游模型名 - alias: "vertex-flash" # 客户端使用的别名 - - name: "gemini-1.5-pro" - alias: "vertex-pro" - - name: "gemini-2.0-flash-lite" - alias: "vertex-lite" -``` - -### 使用场景 - -1. **简化模型名称**:使用简短易记的别名 -2. **版本管理**:通过别名切换模型版本 -3. **兼容性**:保持客户端代码不变,后端切换模型 - -## API Key 认证 - -Vertex AI Provider 使用 `x-goog-api-key` 头进行认证: - -``` -x-goog-api-key: your-api-key -``` - -Lime 会自动将配置的 API Key 添加到请求头中。 - -## 负载均衡 - -### 配置多个凭证 - -```yaml -credential_pool: - vertex_api_keys: - - id: "vertex-1" - api_key: "vk-123..." - base_url: "https://endpoint1.example.com/api" - - id: "vertex-2" - api_key: "vk-456..." - base_url: "https://endpoint2.example.com/api" -``` - -### 工作原理 - -1. 使用 Round-Robin 在凭证之间分配请求 -2. 如果某个凭证失败,自动尝试下一个 -3. 配额超限时自动切换到其他凭证 - -## 使用示例 - -### 使用上游模型名 - -```bash -curl http://127.0.0.1:8999/v1/chat/completions \ - -H "Authorization: Bearer your-api-key" \ - -H "Content-Type: application/json" \ - -d '{ - "model": "gemini-2.0-flash", - "messages": [{"role": "user", "content": "Hello!"}] - }' -``` - -### 使用模型别名 - -```bash -curl http://127.0.0.1:8999/v1/chat/completions \ - -H "Authorization: Bearer your-api-key" \ - -H "Content-Type: application/json" \ - -d '{ - "model": "vertex-flash", - "messages": [{"role": "user", "content": "Hello!"}] - }' -``` - -### 路由配置 - -将 Vertex 模型路由到 Vertex AI Provider: - -```yaml -routing: - rules: - - pattern: "vertex-*" - provider: "vertex" - priority: 1 -``` - -## 与 Gemini API Key 的区别 - -| 特性 | Vertex AI | Gemini API Key | -|------|-----------|----------------| -| 认证方式 | x-goog-api-key | API Key | -| 模型别名 | ✅ | ❌ | -| 模型排除 | ❌ | ✅ | -| 自定义 Base URL | ✅ | ✅ | -| 适用场景 | Vertex 兼容端点 | 官方 Gemini API | - -## 故障排除 - -### API Key 无效 - -1. 确认 Key 格式正确 -2. 检查 Key 是否已被撤销 -3. 确认 Base URL 正确 - -### 模型不可用 - -1. 检查模型名称或别名是否正确 -2. 确认端点支持该模型 -3. 检查别名映射配置 - -### 连接失败 - -1. 检查 Base URL 是否可访问 -2. 确认代理配置正确 -3. 检查网络连接 diff --git a/docs/content/03.providers/2.kiro-claude.md b/docs/content/03.providers/2.kiro-claude.md deleted file mode 100644 index a4e1ac62e..000000000 --- a/docs/content/03.providers/2.kiro-claude.md +++ /dev/null @@ -1,120 +0,0 @@ ---- -title: Kiro Claude -description: 配置 Kiro IDE 的 Claude 凭证 -navigation: - icon: i-heroicons-cpu-chip ---- - -# Kiro Claude - -::alert{type="info"} -本页属于进阶连接配置。若你已能正常创作,可先跳过。 -:: - -Kiro Claude 是 AWS Kiro IDE 提供的 Claude AI 服务凭证。 - -## 凭证位置 - -### 默认路径 - -Kiro 凭证文件位于: - -| 平台 | 路径 | -|------|------| -| macOS | `~/.kiro/credentials.json` | -| Windows | `%USERPROFILE%\.kiro\credentials.json` | - -### 凭证格式 - -```json -{ - "accessToken": "eyJ...", - "refreshToken": "eyJ...", - "expiresAt": "2024-01-01T00:00:00Z" -} -``` - -## 自动刷新机制 - -### Token 生命周期 - -- Access Token 有效期:约 1 小时 -- Refresh Token 有效期:约 30 天 - -### 自动刷新 - -Lime 会自动处理 Token 刷新: - -1. 检测 Access Token 即将过期 -2. 使用 Refresh Token 获取新 Token -3. 更新本地凭证文件 -4. 继续处理请求 - -### 刷新失败处理 - -如果刷新失败: - -1. 标记凭证为"已过期" -2. 尝试使用其他可用凭证 -3. 通知用户重新登录 Kiro - -## 配置步骤 - -### 自动检测 - -1. 确保已安装 Kiro IDE -2. 在 Kiro 中完成登录 -3. 启动 Lime -4. 凭证自动出现在凭证池中 - -### 手动添加 - -如果自动检测失败: - -1. 进入 **凭证池** 页面 -2. 点击 **添加凭证** -3. 选择 **Kiro Claude** -4. 选择凭证文件或手动输入 - -## 支持的模型 - -| 模型 | 说明 | -|------|------| -| claude-sonnet-4-20250514 | Claude Sonnet 4 | -| claude-3-5-sonnet-20241022 | Claude 3.5 Sonnet | -| claude-3-5-haiku-20241022 | Claude 3.5 Haiku | - -## 使用限制 - -### 额度限制 - -Kiro 订阅有使用额度限制,具体取决于订阅计划。 - -### 并发限制 - -建议单个凭证的并发请求数不超过 5。 - -## 故障排除 - -### 凭证未检测到 - -1. 确认 Kiro 已安装并登录 -2. 检查凭证文件是否存在 -3. 点击 **刷新凭证** 重新扫描 - -### Token 过期 - -1. 打开 Kiro IDE -2. 确认登录状态 -3. 如需要,重新登录 -4. 在 Lime 中刷新凭证 - -### 请求失败 - -常见错误: - -| 错误 | 原因 | 解决方案 | -|------|------|----------| -| 401 Unauthorized | Token 无效 | 刷新凭证或重新登录 | -| 429 Too Many Requests | 超出限制 | 等待或使用其他凭证 | -| 503 Service Unavailable | 服务不可用 | 稍后重试 | diff --git a/docs/content/03.providers/3.gemini-cli.md b/docs/content/03.providers/3.gemini-cli.md deleted file mode 100644 index 60c0270fe..000000000 --- a/docs/content/03.providers/3.gemini-cli.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Gemini CLI -description: 配置 Google Gemini CLI 凭证 -navigation: - icon: i-heroicons-sparkles ---- - -# Gemini CLI - -::alert{type="info"} -本页属于进阶连接配置。若你已能正常创作,可先跳过。 -:: - -Gemini CLI 是 Google 提供的命令行 AI 工具,使用 OAuth 认证。 - -## 凭证位置 - -### 默认路径 - -Gemini CLI 凭证文件位于: - -| 平台 | 路径 | -|------|------| -| macOS | `~/.config/gemini-cli/oauth_creds.json` | -| Windows | `%USERPROFILE%\.config\gemini-cli\oauth_creds.json` | -| Linux | `~/.config/gemini-cli/oauth_creds.json` | - -### 凭证格式 - -```json -{ - "client_id": "...", - "client_secret": "...", - "refresh_token": "...", - "token_uri": "https://oauth2.googleapis.com/token" -} -``` - -## 项目设置 - -### Google Cloud 项目 - -Gemini CLI 需要关联 Google Cloud 项目: - -1. 访问 [Google Cloud Console](https://console.cloud.google.com) -2. 创建或选择项目 -3. 启用 Gemini API -4. 配置 OAuth 同意屏幕 - -### 配置项目 ID - -在 Lime 中配置项目: - -```yaml -gemini: - project_id: "your-project-id" - location: "us-central1" -``` - -## 自动刷新机制 - -### Token 刷新 - -Lime 自动处理 OAuth Token 刷新: - -1. 使用 Refresh Token 获取 Access Token -2. Access Token 过期前自动刷新 -3. 无需用户干预 - -### 刷新失败 - -如果刷新失败: - -1. 检查网络连接 -2. 确认 Google 账户状态 -3. 重新运行 `gemini auth login` - -## 配置步骤 - -### 安装 Gemini CLI - -```bash -# 使用 npm 安装 -npm install -g @anthropic-ai/gemini-cli - -# 或使用 pip -pip install gemini-cli -``` - -### 登录认证 - -```bash -gemini auth login -``` - -按提示完成 OAuth 认证流程。 - -### 在 Lime 中配置 - -1. 完成 Gemini CLI 登录 -2. 启动 Lime -3. 凭证自动出现在凭证池中 - -## 支持的模型 - -| 模型 | 说明 | -|------|------| -| gemini-2.0-flash | Gemini 2.0 Flash | -| gemini-1.5-pro | Gemini 1.5 Pro | -| gemini-1.5-flash | Gemini 1.5 Flash | - -## 使用限制 - -### 免费额度 - -Google 提供一定的免费使用额度,超出后需要付费。 - -### 速率限制 - -| 限制类型 | 限制值 | -|----------|--------| -| 每分钟请求数 | 60 | -| 每日请求数 | 1500 | - -## 故障排除 - -### 凭证未检测到 - -1. 确认已运行 `gemini auth login` -2. 检查凭证文件是否存在 -3. 确认文件权限正确 - -### 认证失败 - -```bash -# 重新登录 -gemini auth logout -gemini auth login -``` - -### 项目配置错误 - -确认 Google Cloud 项目: - -1. 已启用 Gemini API -2. 有足够的配额 -3. 账单设置正确 diff --git a/docs/content/03.providers/4.qwen.md b/docs/content/03.providers/4.qwen.md deleted file mode 100644 index 5b863de65..000000000 --- a/docs/content/03.providers/4.qwen.md +++ /dev/null @@ -1,148 +0,0 @@ ---- -title: Qwen (通义千问) -description: 配置阿里云通义千问凭证 -navigation: - icon: i-heroicons-language ---- - -# Qwen (通义千问) - -::alert{type="info"} -本页属于进阶连接配置。若你已能正常创作,可先跳过。 -:: - -Qwen 是阿里云提供的大语言模型服务。 - -## 凭证位置 - -### 默认路径 - -Qwen 凭证文件位于: - -| 平台 | 路径 | -|------|------| -| macOS | `~/.config/qwen/credentials.json` | -| Windows | `%USERPROFILE%\.config\qwen\credentials.json` | -| Linux | `~/.config/qwen/credentials.json` | - -### 凭证格式 - -```json -{ - "access_token": "...", - "refresh_token": "...", - "expires_at": "2024-01-01T00:00:00Z" -} -``` - -## 认证设置 - -### 获取凭证 - -1. 访问 [阿里云控制台](https://www.aliyun.com) -2. 开通通义千问服务 -3. 获取 API 凭证 - -### 使用阿里云 CLI - -```bash -# 安装阿里云 CLI -pip install aliyun-cli - -# 配置凭证 -aliyun configure -``` - -### 手动配置 - -在 Lime 中手动添加: - -1. 进入 **凭证池** 页面 -2. 点击 **添加凭证** -3. 选择 **Qwen** -4. 输入凭证信息 - -## 自动刷新 - -Lime 支持 Qwen Token 的自动刷新: - -1. 检测 Token 即将过期 -2. 使用 Refresh Token 获取新 Token -3. 更新凭证文件 - -## 支持的模型 - -| 模型 | 说明 | -|------|------| -| qwen-turbo | 通义千问 Turbo | -| qwen-plus | 通义千问 Plus | -| qwen-max | 通义千问 Max | -| qwen-long | 通义千问 Long(长文本) | - -## 配置选项 - -### 区域设置 - -```yaml -qwen: - region: "cn-hangzhou" - endpoint: "https://dashscope.aliyuncs.com" -``` - -### 模型映射 - -将 OpenAI 模型名映射到 Qwen: - -```yaml -routes: - - pattern: "gpt-4*" - provider: qwen - model: qwen-max - - pattern: "gpt-3.5*" - provider: qwen - model: qwen-turbo -``` - -## 使用限制 - -### 并发限制 - -| 模型 | 并发数 | -|------|--------| -| qwen-turbo | 10 | -| qwen-plus | 5 | -| qwen-max | 3 | - -### Token 限制 - -| 模型 | 最大 Token | -|------|-----------| -| qwen-turbo | 8K | -| qwen-plus | 32K | -| qwen-max | 32K | -| qwen-long | 1M | - -## 故障排除 - -### 凭证无效 - -1. 检查阿里云账户状态 -2. 确认服务已开通 -3. 重新获取凭证 - -### 请求失败 - -| 错误码 | 原因 | 解决方案 | -|--------|------|----------| -| InvalidApiKey | API Key 无效 | 检查凭证配置 | -| QuotaExhausted | 配额用尽 | 充值或等待重置 | -| RateLimitExceeded | 超出速率限制 | 降低请求频率 | - -### 网络问题 - -如果在中国大陆以外使用,可能需要配置代理: - -```yaml -qwen: - proxy: "http://proxy.example.com:8080" -``` diff --git a/docs/content/03.providers/5.openai-custom.md b/docs/content/03.providers/5.openai-custom.md deleted file mode 100644 index 85e3c1a0b..000000000 --- a/docs/content/03.providers/5.openai-custom.md +++ /dev/null @@ -1,143 +0,0 @@ ---- -title: OpenAI Custom -description: 配置自定义 OpenAI 兼容服务 -navigation: - icon: i-heroicons-cube ---- - -# OpenAI Custom - -::alert{type="info"} -本页属于进阶连接配置。若你已能正常创作,可先跳过。 -:: - -OpenAI Custom 允许你配置任何 OpenAI 兼容的 API 服务。 - -## 适用场景 - -- 使用 OpenAI 官方 API -- 使用 Azure OpenAI -- 使用其他 OpenAI 兼容服务(如 Groq、Together AI) -- 使用本地部署的模型(如 Ollama、vLLM) - -## API Key 配置 - -### 获取 API Key - -**OpenAI 官方:** -1. 访问 [OpenAI Platform](https://platform.openai.com) -2. 进入 API Keys 页面 -3. 创建新的 API Key - -**Azure OpenAI:** -1. 访问 Azure Portal -2. 创建 Azure OpenAI 资源 -3. 获取 API Key 和端点 - -### 在 Lime 中配置 - -1. 进入 **凭证池** 页面 -2. 点击 **添加凭证** -3. 选择 **OpenAI Custom** -4. 填写配置信息: - -| 字段 | 说明 | -|------|------| -| 名称 | 凭证标识名称 | -| API Key | OpenAI API Key | -| Base URL | API 端点(可选) | - -## Base URL 设置 - -### 默认端点 - -不填写 Base URL 时,使用 OpenAI 官方端点: - -``` -https://api.openai.com/v1 -``` - -### 自定义端点 - -| 服务 | Base URL | -|------|----------| -| Azure OpenAI | `https://{resource}.openai.azure.com/openai/deployments/{deployment}` | -| Groq | `https://api.groq.com/openai/v1` | -| Together AI | `https://api.together.xyz/v1` | -| Ollama | `http://localhost:11434/v1` | - -### 配置示例 - -```yaml -providers: - - name: openai-official - type: openai-custom - api_key: "sk-..." - # 使用默认 Base URL - - - name: azure-openai - type: openai-custom - api_key: "..." - base_url: "https://myresource.openai.azure.com/openai/deployments/gpt-4" - - - name: ollama-local - type: openai-custom - api_key: "ollama" # Ollama 不需要真实 key - base_url: "http://localhost:11434/v1" -``` - -## 支持的模型 - -取决于你使用的服务,常见模型: - -| 服务 | 模型 | -|------|------| -| OpenAI | gpt-4, gpt-4-turbo, gpt-3.5-turbo | -| Azure | 取决于部署 | -| Groq | llama-3.1-70b, mixtral-8x7b | -| Ollama | llama3, mistral, codellama | - -## 高级配置 - -### 请求头 - -添加自定义请求头: - -```yaml -openai-custom: - headers: - X-Custom-Header: "value" -``` - -### Azure 特殊配置 - -Azure OpenAI 需要额外配置: - -```yaml -azure-openai: - api_key: "..." - base_url: "https://..." - api_version: "2024-02-15-preview" - headers: - api-key: "..." # Azure 使用 api-key 头 -``` - -## 故障排除 - -### API Key 无效 - -1. 确认 API Key 正确 -2. 检查 Key 是否过期 -3. 确认账户有足够余额 - -### 连接失败 - -1. 检查 Base URL 是否正确 -2. 确认网络可以访问端点 -3. 检查是否需要代理 - -### 模型不存在 - -1. 确认模型名称正确 -2. 检查账户是否有该模型的访问权限 -3. Azure 用户确认部署名称 diff --git a/docs/content/03.providers/6.claude-custom.md b/docs/content/03.providers/6.claude-custom.md deleted file mode 100644 index 02972cb8d..000000000 --- a/docs/content/03.providers/6.claude-custom.md +++ /dev/null @@ -1,176 +0,0 @@ ---- -title: Claude Custom -description: 配置自定义 Claude 兼容服务 -navigation: - icon: i-heroicons-beaker ---- - -# Claude Custom - -::alert{type="info"} -本页属于进阶连接配置。若你已能正常创作,可先跳过。 -:: - -Claude Custom 允许你配置 Anthropic 官方 API 或其他 Claude 兼容服务。 - -## 适用场景 - -- 使用 Anthropic 官方 API -- 使用 AWS Bedrock Claude -- 使用其他 Claude 兼容服务 - -## API Key 配置 - -### 获取 API Key - -**Anthropic 官方:** -1. 访问 [Anthropic Console](https://console.anthropic.com) -2. 进入 API Keys 页面 -3. 创建新的 API Key - -**AWS Bedrock:** -1. 访问 AWS Console -2. 配置 Bedrock 访问权限 -3. 获取 AWS 凭证 - -### 在 Lime 中配置 - -1. 进入 **凭证池** 页面 -2. 点击 **添加凭证** -3. 选择 **Claude Custom** -4. 填写配置信息: - -| 字段 | 说明 | -|------|------| -| 名称 | 凭证标识名称 | -| API Key | Anthropic API Key | -| Base URL | API 端点(可选) | - -## Base URL 设置 - -### 默认端点 - -不填写 Base URL 时,使用 Anthropic 官方端点: - -``` -https://api.anthropic.com -``` - -### 自定义端点 - -| 服务 | Base URL | -|------|----------| -| Anthropic 官方 | `https://api.anthropic.com` | -| AWS Bedrock | 使用 AWS SDK | -| 代理服务 | 自定义 URL | - -### 配置示例 - -```yaml -providers: - - name: anthropic-official - type: claude-custom - api_key: "sk-ant-..." - # 使用默认 Base URL - - - name: claude-proxy - type: claude-custom - api_key: "..." - base_url: "https://my-proxy.example.com" -``` - -## 支持的模型 - -| 模型 | 说明 | -|------|------| -| claude-sonnet-4-20250514 | Claude Sonnet 4 | -| claude-3-5-sonnet-20241022 | Claude 3.5 Sonnet | -| claude-3-5-haiku-20241022 | Claude 3.5 Haiku | -| claude-3-opus-20240229 | Claude 3 Opus | - -## API 版本 - -### 版本配置 - -Anthropic API 需要指定版本: - -```yaml -claude-custom: - api_version: "2023-06-01" -``` - -### 请求头 - -Claude API 使用特定的请求头: - -``` -x-api-key: your-api-key -anthropic-version: 2023-06-01 -``` - -## AWS Bedrock 配置 - -### 使用 AWS 凭证 - -```yaml -bedrock-claude: - type: claude-custom - aws_region: "us-east-1" - aws_access_key: "..." - aws_secret_key: "..." - model_id: "anthropic.claude-3-sonnet-20240229-v1:0" -``` - -### IAM 角色 - -推荐使用 IAM 角色而非 Access Key: - -1. 配置 IAM 角色 -2. 授予 Bedrock 访问权限 -3. Lime 自动使用角色凭证 - -## 高级配置 - -### 自定义请求头 - -```yaml -claude-custom: - headers: - X-Custom-Header: "value" -``` - -### 超时设置 - -```yaml -claude-custom: - timeout: - connect: 10s - request: 180s # Claude 响应可能较慢 -``` - -## 故障排除 - -### API Key 无效 - -1. 确认 API Key 正确 -2. 检查 Key 是否过期 -3. 确认账户状态正常 - -### 模型访问被拒 - -1. 确认账户有该模型的访问权限 -2. 某些模型需要申请访问 -3. 检查使用限制 - -### 速率限制 - -| 错误 | 解决方案 | -|------|----------| -| 429 Too Many Requests | 降低请求频率 | -| rate_limit_error | 等待后重试 | - -### Bedrock 问题 - -1. 确认 AWS 凭证正确 -2. 检查 IAM 权限 -3. 确认区域支持 Claude diff --git a/docs/content/03.providers/7.codex.md b/docs/content/03.providers/7.codex.md deleted file mode 100644 index 5785803f4..000000000 --- a/docs/content/03.providers/7.codex.md +++ /dev/null @@ -1,145 +0,0 @@ ---- -title: Codex -description: OpenAI Codex OAuth Provider 配置 -navigation: - icon: i-heroicons-code-bracket ---- - -# Codex Provider - -::alert{type="info"} -本页属于进阶连接配置。若你已能正常创作,可先跳过。 -:: - -通过 OAuth 认证使用 OpenAI Codex 服务。 - -## 概述 - -Codex Provider 允许你使用 OpenAI Codex 的 OAuth 凭证访问 GPT 模型。 -同时,为了兼容 Codex CLI 的「API Key 登录」用户(`~/.codex/auth.json` 只有 `api_key`),Lime 也支持读取 `api_key` 并作为 Bearer Token 使用(无需刷新)。 - -## 支持的模型 - -- GPT-4 系列 -- GPT-3.5 系列 -- 其他 Codex 支持的模型 - -## 配置 - -### 凭证池配置 - -```yaml -credential_pool: - codex: - - id: "codex-main" - token_file: "codex/oauth.json" - disabled: false - proxy_url: "http://proxy:8080" # 可选 -``` - -### 配置项说明 - -| 配置项 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| id | string | ✅ | 凭证唯一标识 | -| token_file | string | ✅ | Token 文件路径(相对于 auth_dir) | -| disabled | boolean | ❌ | 是否禁用此凭证 | -| proxy_url | string | ❌ | 单独的代理 URL | - -## OAuth 登录 - -### 通过 UI 登录 - -1. 打开 Lime -2. 进入 Provider 管理页面 -3. 找到 Codex 部分 -4. 点击"OAuth 登录"按钮 -5. 在弹出的浏览器中完成认证 -6. 认证成功后自动保存凭证 - -### Token 文件格式 - -#### OAuth 模式(推荐用于 Codex OAuth) - -```json -{ - "access_token": "eyJ...", - "refresh_token": "eyJ...", - "expires_at": "2025-01-01T00:00:00Z", - "token_type": "Bearer" -} -``` - -#### API Key 模式(兼容 Codex CLI) - -```json -{ - "api_key": "sk-xxx", - "api_base_url": "https://api.openai.com" -} -``` - -说明: -- `api_key` / `apiKey`:必填 -- `api_base_url` / `apiBaseUrl`:可选;可填写 `https://api.openai.com` 或带 `/v1` 的地址(例如网关、反代、Azure 兼容地址) - -## Token 刷新 - -Lime 会自动在 Token 过期前刷新: - -- 检测到 Token 即将过期时自动刷新 -- 刷新失败时标记凭证为无效 -- 无效凭证会在 UI 中显示警告 - -## 使用示例 - -### API 请求 - -```bash -curl http://127.0.0.1:8999/v1/chat/completions \ - -H "Authorization: Bearer your-api-key" \ - -H "Content-Type: application/json" \ - -d '{ - "model": "gpt-4", - "messages": [{"role": "user", "content": "Hello!"}] - }' -``` - -### 路由配置 - -将 GPT 模型路由到 Codex: - -```yaml -routing: - rules: - - pattern: "gpt-*" - provider: "codex" - priority: 1 -``` - -## 多账号配置 - -```yaml -credential_pool: - codex: - - id: "codex-1" - token_file: "codex/account1.json" - - id: "codex-2" - token_file: "codex/account2.json" -``` - -Lime 会自动在多个凭证之间负载均衡。 - -## 故障排除 - -### Token 刷新失败 - -1. 检查网络连接 -2. 确认 OAuth 授权未被撤销 -3. 尝试重新登录 - -### 凭证无效 - -1. 删除旧的 Token 文件 -2. 重新进行 OAuth 登录 -3. 检查账号状态 diff --git a/docs/content/03.providers/8.iflow.md b/docs/content/03.providers/8.iflow.md deleted file mode 100644 index c870e1b77..000000000 --- a/docs/content/03.providers/8.iflow.md +++ /dev/null @@ -1,173 +0,0 @@ ---- -title: iFlow -description: iFlow Provider 配置(OAuth 和 Cookie) -navigation: - icon: i-heroicons-arrow-path ---- - -# iFlow Provider - -::alert{type="info"} -本页属于进阶连接配置。若你已能正常创作,可先跳过。 -:: - -iFlow Provider 支持两种认证方式:OAuth 和 Cookie。 - -## 概述 - -iFlow 是一个 AI 服务提供商,Lime 支持通过 OAuth 或 Cookie 方式使用其服务。 - -## 认证方式 - -### OAuth 认证 - -通过 OAuth 协议认证,支持自动刷新 Token。 - -### Cookie 认证 - -通过导入浏览器 Cookie 认证,适用于不支持 OAuth 的场景。 - -## 配置 - -### OAuth 模式 - -```yaml -credential_pool: - iflow: - - id: "iflow-oauth" - token_file: "iflow/oauth.json" - auth_type: "oauth" - disabled: false - proxy_url: "http://proxy:8080" # 可选 -``` - -### Cookie 模式 - -```yaml -credential_pool: - iflow: - - id: "iflow-cookie" - auth_type: "cookie" - cookies: "session_id=abc123; auth_token=xyz789" - disabled: false - proxy_url: "http://proxy:8080" # 可选 -``` - -### 配置项说明 - -| 配置项 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| id | string | ✅ | 凭证唯一标识 | -| auth_type | string | ✅ | 认证类型:`oauth` 或 `cookie` | -| token_file | string | OAuth | Token 文件路径(OAuth 模式必填) | -| cookies | string | Cookie | Cookie 字符串(Cookie 模式必填) | -| disabled | boolean | ❌ | 是否禁用此凭证 | -| proxy_url | string | ❌ | 单独的代理 URL | - -## OAuth 登录 - -### 通过 UI 登录 - -1. 打开 Lime -2. 进入 Provider 管理页面 -3. 找到 iFlow 部分 -4. 点击"OAuth 登录"按钮 -5. 在弹出的浏览器中完成认证 -6. 认证成功后自动保存凭证 - -### Token 文件格式 - -```json -{ - "access_token": "eyJ...", - "refresh_token": "eyJ...", - "expires_at": "2025-01-01T00:00:00Z" -} -``` - -## Cookie 导入 - -### 获取 Cookie - -1. 在浏览器中登录 iFlow -2. 打开开发者工具(F12) -3. 切换到 Network 标签 -4. 刷新页面 -5. 选择任意请求,查看 Request Headers -6. 复制 Cookie 头的值 - -### 通过 UI 导入 - -1. 打开 Lime -2. 进入 Provider 管理页面 -3. 找到 iFlow 部分 -4. 选择"Cookie 导入" -5. 粘贴 Cookie 字符串 -6. 点击"保存" - -### Cookie 格式 - -``` -session_id=abc123; auth_token=xyz789; user_id=12345 -``` - -## 使用示例 - -### API 请求 - -```bash -curl http://127.0.0.1:8999/v1/chat/completions \ - -H "Authorization: Bearer your-api-key" \ - -H "Content-Type: application/json" \ - -d '{ - "model": "iflow-model", - "messages": [{"role": "user", "content": "Hello!"}] - }' -``` - -### 路由配置 - -将 iFlow 模型路由到 iFlow Provider: - -```yaml -routing: - rules: - - pattern: "iflow-*" - provider: "iflow" - priority: 1 -``` - -## 多账号配置 - -```yaml -credential_pool: - iflow: - # OAuth 账号 - - id: "iflow-oauth-1" - token_file: "iflow/account1.json" - auth_type: "oauth" - # Cookie 账号 - - id: "iflow-cookie-1" - auth_type: "cookie" - cookies: "session_id=abc123" -``` - -## 故障排除 - -### OAuth Token 刷新失败 - -1. 检查网络连接 -2. 确认 OAuth 授权未被撤销 -3. 尝试重新登录 - -### Cookie 过期 - -1. 重新从浏览器获取 Cookie -2. 更新配置中的 Cookie 字符串 -3. Cookie 通常有效期较短,建议使用 OAuth - -### 凭证无效 - -1. 检查账号状态 -2. 确认服务可用 -3. 尝试重新认证 diff --git a/docs/content/03.providers/9.gemini-api-key.md b/docs/content/03.providers/9.gemini-api-key.md deleted file mode 100644 index b06e89abf..000000000 --- a/docs/content/03.providers/9.gemini-api-key.md +++ /dev/null @@ -1,203 +0,0 @@ ---- -title: Gemini API Key -description: Gemini API Key 多账号负载均衡配置 -navigation: - icon: i-heroicons-key ---- - -# Gemini API Key Provider - -::alert{type="info"} -本页属于进阶连接配置。若你已能正常创作,可先跳过。 -:: - -使用 API Key 访问 Google Gemini 服务,支持多账号负载均衡和模型排除。 - -## 概述 - -Gemini API Key Provider 允许你: -- 配置多个 API Key 实现负载均衡 -- 为每个 Key 设置排除的模型 -- 自定义 Base URL -- 为每个 Key 单独配置代理 - -## 支持的模型 - -- Gemini 2.5 Pro -- Gemini 2.5 Flash -- Gemini 2.0 系列 -- Gemini 1.5 系列 -- 其他 Gemini API 支持的模型 - -## 配置 - -### 基础配置 - -```yaml -credential_pool: - gemini_api_keys: - - id: "gemini-key-1" - api_key: "AIzaSy..." - disabled: false -``` - -### 完整配置 - -```yaml -credential_pool: - gemini_api_keys: - - id: "gemini-key-1" - api_key: "AIzaSy...01" - base_url: "https://generativelanguage.googleapis.com" - proxy_url: "socks5://proxy1:1080" - excluded_models: - - "gemini-2.5-pro" - - "gemini-2.5-*" - - "*-preview" - disabled: false - - id: "gemini-key-2" - api_key: "AIzaSy...02" - disabled: false -``` - -### 配置项说明 - -| 配置项 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| id | string | ✅ | 凭证唯一标识 | -| api_key | string | ✅ | Gemini API Key | -| base_url | string | ❌ | 自定义 Base URL | -| proxy_url | string | ❌ | 单独的代理 URL | -| excluded_models | array | ❌ | 排除的模型列表 | -| disabled | boolean | ❌ | 是否禁用此凭证 | - -## 模型排除 - -### 排除规则 - -支持以下匹配模式: - -| 模式 | 说明 | 示例 | -|------|------|------| -| 精确匹配 | 完全匹配模型名称 | `gemini-2.5-pro` | -| 前缀匹配 | 以指定前缀开头 | `gemini-2.5-*` | -| 后缀匹配 | 以指定后缀结尾 | `*-preview` | -| 包含匹配 | 包含指定字符串 | `*flash*` | - -### 配置示例 - -```yaml -excluded_models: - - "gemini-2.5-pro" # 精确匹配 - - "gemini-2.5-*" # 匹配 gemini-2.5-flash, gemini-2.5-pro 等 - - "*-preview" # 匹配所有预览版模型 - - "*flash*" # 匹配所有包含 flash 的模型 -``` - -### 使用场景 - -1. **配额限制**:某些 Key 对特定模型有配额限制 -2. **区域限制**:某些 Key 在特定区域无法访问某些模型 -3. **成本控制**:限制高成本模型的使用 - -## 负载均衡 - -### 工作原理 - -1. 收到请求时,检查请求的模型 -2. 过滤掉排除了该模型的 Key -3. 在剩余的 Key 中使用 Round-Robin 选择 -4. 如果选中的 Key 失败,尝试下一个 - -### 配置示例 - -```yaml -credential_pool: - gemini_api_keys: - # Key 1: 用于所有模型 - - id: "gemini-all" - api_key: "AIzaSy...01" - # Key 2: 排除 Pro 模型 - - id: "gemini-flash-only" - api_key: "AIzaSy...02" - excluded_models: - - "gemini-*-pro*" - # Key 3: 仅用于预览模型 - - id: "gemini-preview" - api_key: "AIzaSy...03" - excluded_models: - - "gemini-2.5-pro" - - "gemini-2.5-flash" -``` - -## 自定义 Base URL - -### 使用场景 - -- 使用代理服务 -- 使用私有部署 -- 使用第三方兼容服务 - -### 配置示例 - -```yaml -credential_pool: - gemini_api_keys: - - id: "gemini-proxy" - api_key: "AIzaSy..." - base_url: "https://my-proxy.example.com/gemini" -``` - -## 使用示例 - -### API 请求 - -```bash -curl http://127.0.0.1:8999/v1/chat/completions \ - -H "Authorization: Bearer your-api-key" \ - -H "Content-Type: application/json" \ - -d '{ - "model": "gemini-2.5-flash", - "messages": [{"role": "user", "content": "Hello!"}] - }' -``` - -### 路由配置 - -将 Gemini 模型路由到 Gemini API Key Provider: - -```yaml -routing: - rules: - - pattern: "gemini-*" - provider: "gemini_api_key" - priority: 1 -``` - -## 获取 API Key - -1. 访问 [Google AI Studio](https://aistudio.google.com/) -2. 登录 Google 账号 -3. 点击"Get API Key" -4. 创建新的 API Key -5. 复制并保存 Key - -## 故障排除 - -### API Key 无效 - -1. 确认 Key 格式正确(以 `AIzaSy` 开头) -2. 检查 Key 是否已被撤销 -3. 确认账号状态正常 - -### 模型不可用 - -1. 检查模型名称是否正确 -2. 确认 Key 有权访问该模型 -3. 检查是否被排除规则过滤 - -### 配额超限 - -1. 等待配额重置 -2. 添加更多 API Key -3. 启用配额超限自动切换 diff --git a/docs/content/04.api-reference/1.overview.md b/docs/content/04.api-reference/1.overview.md index e4e0afe35..821ca4e2a 100644 --- a/docs/content/04.api-reference/1.overview.md +++ b/docs/content/04.api-reference/1.overview.md @@ -1,6 +1,6 @@ --- title: API 概览 -description: 面向进阶用户的本地接口能力说明 +description: 当前只保留本地兼容接口入口说明 navigation: icon: i-heroicons-code-bracket --- @@ -8,48 +8,66 @@ navigation: # API 概览 ::alert{type="info"} -本章节面向进阶用户与开发者。普通创作者可直接在应用内使用,无需 API 接入。 +本章节面向进阶用户与开发者。普通创作者直接在应用内使用即可,无需单独接 API。 :: -当你需要把 Lime 接入脚本、自动化流程或第三方工具时,可使用本地 API。 +当前 `content/api-reference` 只保留仍与实现锚点对齐的本地兼容接口说明,不再继续扩写旧管理接口或未挂载的兼容路由叙事。 -## 常见端点类型 +## 当前保留的兼容面 -### 通用对话端点 +### OpenAI 兼容 -用于文本生成、对话续写等任务。 +用于本地对话与模型发现: -### 模型与管理端点 +- `POST /v1/chat/completions` +- `GET /v1/models` -用于读取模型列表、状态信息和部分管理能力。 +[查看 OpenAI API 说明 →](/api-reference/openai-api) -### 扩展端点 +### Claude 兼容 -用于特定平台或集成场景。 +用于 Claude Messages 协议兼容: -## 认证方式 +- `POST /v1/messages` +- `POST /v1/messages/count_tokens` -- `Authorization: Bearer ` -- 或使用兼容格式的密钥头 - -请确保 API Key 仅在可信环境使用。 +[查看 Claude API 说明 →](/api-reference/claude-api) ## 默认地址 -默认本地地址:`http://127.0.0.1:8999` +默认本地地址: -通常建议保持本地监听,不对公网暴露。 +```text +http://127.0.0.1:8999 +``` + +通常建议只在本地监听,不对公网直接暴露。 + +## 认证方式 + +认证头会跟随兼容协议变化: + +- OpenAI 兼容:`Authorization: Bearer ` +- Claude 兼容:`x-api-key: `,并携带 `anthropic-version` + +具体请求示例以各协议子页面为准。 ## 错误排查建议 -- `401`:密钥错误或请求头格式错误 -- `404`:端点路径错误 -- `429`:请求频率过高 -- `5xx`:服务端异常或上游波动 +- `401` + - 密钥错误 + - 认证头格式与协议不匹配 +- `404` + - 路径错误 + - 协议路径写错 +- `429` + - 请求频率过高 + - 上游限流 +- `5xx` + - 本地服务异常 + - 上游模型服务波动 ## 下一步 - [OpenAI API](/api-reference/openai-api) - [Claude API](/api-reference/claude-api) -- [管理 API](/api-reference/management-api) -- [Amp CLI API](/api-reference/amp-cli-api) diff --git a/docs/content/04.api-reference/2.openai-api.md b/docs/content/04.api-reference/2.openai-api.md index b6f5a3206..ea51b8dfb 100644 --- a/docs/content/04.api-reference/2.openai-api.md +++ b/docs/content/04.api-reference/2.openai-api.md @@ -11,7 +11,13 @@ navigation: 本页是开发者进阶文档。普通创作者可直接在应用内使用,无需 API 调用。 :: -Lime 提供完整的 OpenAI Chat Completions API 兼容。 +Lime 当前提供 OpenAI Chat Completions 协议兼容入口,以及 `/v1/models` 模型发现端点。 + +## 当前边界 + +- 当前只覆盖 `/v1/chat/completions` 与 `/v1/models` +- 本页不把其他 OpenAI 风格端点写成已落地能力 +- 具体可用模型仍以 Lime 当前加载到本地运行时的结果为准 ## /v1/chat/completions @@ -27,7 +33,7 @@ Authorization: Bearer your-api-key ```json { - "model": "claude-sonnet-4-20250514", + "model": "your-model-id", "messages": [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Hello!"} @@ -72,7 +78,7 @@ Authorization: Bearer your-api-key "id": "chatcmpl-xxx", "object": "chat.completion", "created": 1234567890, - "model": "claude-sonnet-4-20250514", + "model": "your-model-id", "choices": [ { "index": 0, @@ -100,7 +106,7 @@ curl http://127.0.0.1:8999/v1/chat/completions \ -H "Authorization: Bearer your-api-key" \ -H "Content-Type: application/json" \ -d '{ - "model": "claude-sonnet-4-20250514", + "model": "your-model-id", "messages": [{"role": "user", "content": "Hello!"}], "stream": true }' @@ -132,16 +138,16 @@ Authorization: Bearer your-api-key "object": "list", "data": [ { - "id": "claude-sonnet-4-20250514", + "id": "example-chat-model", "object": "model", "created": 1234567890, - "owned_by": "anthropic" + "owned_by": "provider-a" }, { - "id": "gemini-2.0-flash", + "id": "example-fast-model", "object": "model", "created": 1234567890, - "owned_by": "google" + "owned_by": "provider-b" } ] } @@ -153,7 +159,7 @@ Authorization: Bearer your-api-key ```json { - "model": "claude-sonnet-4-20250514", + "model": "your-model-id", "messages": [{"role": "user", "content": "What's the weather in Tokyo?"}], "tools": [ { @@ -211,7 +217,7 @@ client = openai.OpenAI( ) response = client.chat.completions.create( - model="claude-sonnet-4-20250514", + model="your-model-id", messages=[{"role": "user", "content": "Hello!"}] ) @@ -229,7 +235,7 @@ const client = new OpenAI({ }); const response = await client.chat.completions.create({ - model: 'claude-sonnet-4-20250514', + model: 'your-model-id', messages: [{ role: 'user', content: 'Hello!' }] }); diff --git a/docs/content/04.api-reference/3.claude-api.md b/docs/content/04.api-reference/3.claude-api.md index 94b6cfb17..2453cd5d8 100644 --- a/docs/content/04.api-reference/3.claude-api.md +++ b/docs/content/04.api-reference/3.claude-api.md @@ -11,7 +11,13 @@ navigation: 本页是开发者进阶文档。普通创作者可直接在应用内使用,无需 API 调用。 :: -Lime 提供 Anthropic Claude Messages API 兼容。 +Lime 当前提供 Claude Messages 协议兼容入口。 + +## 当前边界 + +- 当前只覆盖 `/v1/messages` 与 `/v1/messages/count_tokens` +- `/v1/messages/count_tokens` 目前用于兼容需要估算值的客户端,不承诺返回上游精确计费结果 +- 具体可用模型仍以 Lime 当前加载到本地运行时的结果为准 ## /v1/messages @@ -28,7 +34,7 @@ anthropic-version: 2023-06-01 ```json { - "model": "claude-sonnet-4-20250514", + "model": "your-model-id", "max_tokens": 1024, "messages": [ {"role": "user", "content": "Hello!"} @@ -83,7 +89,7 @@ anthropic-version: 2023-06-01 "content": [ {"type": "text", "text": "Hello! How can I help you today?"} ], - "model": "claude-sonnet-4-20250514", + "model": "your-model-id", "stop_reason": "end_turn", "usage": { "input_tokens": 10, @@ -102,7 +108,7 @@ curl http://127.0.0.1:8999/v1/messages \ -H "anthropic-version: 2023-06-01" \ -H "Content-Type: application/json" \ -d '{ - "model": "claude-sonnet-4-20250514", + "model": "your-model-id", "max_tokens": 1024, "messages": [{"role": "user", "content": "Hello!"}], "stream": true @@ -127,6 +133,8 @@ data: {"type":"message_stop"} ## /v1/messages/count_tokens +当前该端点返回估算值,用于兼容需要预估 token 数的客户端。 + ### 请求 ```bash @@ -140,7 +148,7 @@ anthropic-version: 2023-06-01 ```json { - "model": "claude-sonnet-4-20250514", + "model": "your-model-id", "messages": [ {"role": "user", "content": "Hello!"} ] @@ -151,7 +159,7 @@ anthropic-version: 2023-06-01 ```json { - "input_tokens": 10 + "input_tokens": 100 } ``` @@ -161,7 +169,7 @@ anthropic-version: 2023-06-01 ```json { - "model": "claude-sonnet-4-20250514", + "model": "your-model-id", "max_tokens": 1024, "messages": [{"role": "user", "content": "What's the weather in Tokyo?"}], "tools": [ @@ -209,7 +217,7 @@ client = anthropic.Anthropic( ) message = client.messages.create( - model="claude-sonnet-4-20250514", + model="your-model-id", max_tokens=1024, messages=[{"role": "user", "content": "Hello!"}] ) @@ -228,7 +236,7 @@ const client = new Anthropic({ }); const message = await client.messages.create({ - model: 'claude-sonnet-4-20250514', + model: 'your-model-id', max_tokens: 1024, messages: [{ role: 'user', content: 'Hello!' }] }); diff --git a/docs/content/04.api-reference/4.management-api.md b/docs/content/04.api-reference/4.management-api.md deleted file mode 100644 index 8ef4be19e..000000000 --- a/docs/content/04.api-reference/4.management-api.md +++ /dev/null @@ -1,324 +0,0 @@ ---- -title: 管理 API -description: Lime 远程管理 API 端点 -navigation: - icon: i-heroicons-cog-6-tooth ---- - -# 管理 API - -::alert{type="info"} -本页是开发者进阶文档,主要用于自动化管理与运维集成。 -:: - -Lime 提供远程管理 API,用于配置和监控服务。 - -## 认证 - -所有管理 API 请求需要在 `Authorization` 头中提供密钥: - -```bash -Authorization: Bearer your-secret-key -``` - -## 访问控制 - -管理 API 的访问受以下配置控制: - -| 配置项 | 说明 | -|--------|------| -| `secret_key` | 管理密钥,为空时禁用所有管理端点(返回 404) | -| `allow_remote` | 是否允许远程访问,为 false 时仅允许 localhost | - -::alert{type="warning"} -当前版本未启用 TLS,仅支持本地访问,`allow_remote` 必须保持为 `false`。 -:: - -## /v0/management/status - -获取服务器状态信息。 - -### 请求 - -```bash -GET /v0/management/status -Authorization: Bearer your-secret-key -``` - -### 响应 - -```json -{ - "status": "running", - "version": "1.0.0", - "uptime_seconds": 3600, - "tls_enabled": false, - "active_credentials": 5, - "total_requests": 1234, - "providers": { - "kiro": { - "enabled": true, - "credentials_count": 2 - }, - "gemini": { - "enabled": true, - "credentials_count": 1 - } - } -} -``` - -## /v0/management/credentials - -### 获取凭证列表 - -```bash -GET /v0/management/credentials -Authorization: Bearer your-secret-key -``` - -### 响应 - -```json -{ - "credentials": [ - { - "id": "kiro-main", - "provider": "kiro", - "type": "oauth", - "status": "valid", - "expires_at": "2025-01-01T00:00:00Z", - "disabled": false - }, - { - "id": "gemini-key-1", - "provider": "gemini_api_key", - "type": "api_key", - "status": "valid", - "disabled": false, - "excluded_models": ["gemini-2.5-pro"] - } - ] -} -``` - -### 添加凭证 - -```bash -POST /v0/management/credentials -Authorization: Bearer your-secret-key -Content-Type: application/json -``` - -#### 添加 OAuth 凭证 - -```json -{ - "provider": "kiro", - "id": "kiro-new", - "token_file": "kiro/new-token.json" -} -``` - -#### 添加 API Key 凭证 - -```json -{ - "provider": "openai", - "id": "openai-new", - "api_key": "sk-xxx...", - "base_url": "https://api.openai.com/v1" -} -``` - -#### 添加 Gemini API Key - -```json -{ - "provider": "gemini_api_key", - "id": "gemini-key-new", - "api_key": "AIzaSy...", - "base_url": "https://generativelanguage.googleapis.com", - "excluded_models": ["gemini-2.5-pro", "*-preview"] -} -``` - -### 响应 - -```json -{ - "success": true, - "credential_id": "kiro-new" -} -``` - -### 删除凭证 - -```bash -DELETE /v0/management/credentials/{credential_id} -Authorization: Bearer your-secret-key -``` - -### 响应 - -```json -{ - "success": true -} -``` - -## /v0/management/config - -### 获取配置 - -```bash -GET /v0/management/config -Authorization: Bearer your-secret-key -``` - -### 响应 - -```json -{ - "server": { - "host": "127.0.0.1", - "port": 8999, - "tls": { - "enable": false - } - }, - "routing": { - "default_provider": "kiro" - }, - "quota_exceeded": { - "switch_project": true, - "switch_preview_model": true, - "cooldown_seconds": 300 - } -} -``` - -### 更新配置 - -```bash -PUT /v0/management/config -Authorization: Bearer your-secret-key -Content-Type: application/json -``` - -```json -{ - "routing": { - "default_provider": "gemini" - }, - "quota_exceeded": { - "cooldown_seconds": 600 - } -} -``` - -### 响应 - -```json -{ - "success": true, - "restart_required": false -} -``` - -> **注意**: 某些配置更改(如 TLS、端口)需要重启服务器才能生效。 - -## 错误响应 - -### 401 Unauthorized - -密钥无效或缺失: - -```json -{ - "error": { - "message": "Invalid or missing secret key", - "type": "authentication_error", - "code": "invalid_api_key" - } -} -``` - -### 403 Forbidden - -远程访问被禁止: - -```json -{ - "error": { - "message": "Remote access not allowed", - "type": "permission_error", - "code": "remote_access_denied" - } -} -``` - -### 404 Not Found - -管理 API 已禁用(secret_key 为空): - -```json -{ - "error": { - "message": "Management API is disabled", - "type": "not_found_error", - "code": "endpoint_not_found" - } -} -``` - -## 示例代码 - -### cURL - -```bash -# 获取状态 -curl http://127.0.0.1:8999/v0/management/status \ - -H "Authorization: Bearer your-secret-key" - -# 获取凭证列表 -curl http://127.0.0.1:8999/v0/management/credentials \ - -H "Authorization: Bearer your-secret-key" - -# 添加凭证 -curl http://127.0.0.1:8999/v0/management/credentials \ - -H "Authorization: Bearer your-secret-key" \ - -H "Content-Type: application/json" \ - -d '{"provider": "openai", "id": "openai-new", "api_key": "sk-xxx"}' -``` - -### Python - -```python -import requests - -BASE_URL = "http://127.0.0.1:8999" -SECRET_KEY = "your-secret-key" - -headers = { - "Authorization": f"Bearer {SECRET_KEY}", - "Content-Type": "application/json" -} - -# 获取状态 -response = requests.get(f"{BASE_URL}/v0/management/status", headers=headers) -print(response.json()) - -# 添加凭证 -credential = { - "provider": "openai", - "id": "openai-new", - "api_key": "sk-xxx" -} -response = requests.post( - f"{BASE_URL}/v0/management/credentials", - headers=headers, - json=credential -) -print(response.json()) -``` diff --git a/docs/content/04.api-reference/5.amp-cli-api.md b/docs/content/04.api-reference/5.amp-cli-api.md deleted file mode 100644 index 1f54876f5..000000000 --- a/docs/content/04.api-reference/5.amp-cli-api.md +++ /dev/null @@ -1,248 +0,0 @@ ---- -title: Amp CLI API -description: Amp CLI 集成路由端点 -navigation: - icon: i-heroicons-command-line ---- - -# Amp CLI API - -::alert{type="info"} -本页是开发者进阶文档。若你不涉及 Amp CLI 集成,可跳过。 -:: - -Lime 提供 Amp CLI 兼容的路由端点,支持将 Amp CLI 请求路由到本地 OAuth 凭证。 - -## 概述 - -Amp CLI 集成允许你: -- 使用本地 OAuth 凭证处理 Amp CLI 请求 -- 将不可用的模型映射到可用的替代模型 -- 代理 Amp 的认证和账户管理功能 - -## Provider 路由 - -### /api/provider/{provider}/v1/chat/completions - -处理 Amp CLI 的 OpenAI 格式聊天请求。 - -```bash -POST /api/provider/{provider}/v1/chat/completions -Content-Type: application/json -Authorization: Bearer your-api-key -``` - -#### 支持的 Provider - -| Provider | 说明 | -|----------|------| -| `anthropic` | Claude 模型 | -| `openai` | GPT 模型 | -| `google` | Gemini 模型 | - -#### 请求示例 - -```bash -curl http://127.0.0.1:8999/api/provider/anthropic/v1/chat/completions \ - -H "Authorization: Bearer your-api-key" \ - -H "Content-Type: application/json" \ - -d '{ - "model": "claude-sonnet-4", - "messages": [{"role": "user", "content": "Hello!"}], - "stream": true - }' -``` - -### /api/provider/{provider}/v1/messages - -处理 Amp CLI 的 Anthropic Messages 格式请求。 - -```bash -POST /api/provider/{provider}/v1/messages -Content-Type: application/json -x-api-key: your-api-key -anthropic-version: 2023-06-01 -``` - -#### 请求示例 - -```bash -curl http://127.0.0.1:8999/api/provider/anthropic/v1/messages \ - -H "x-api-key: your-api-key" \ - -H "anthropic-version: 2023-06-01" \ - -H "Content-Type: application/json" \ - -d '{ - "model": "claude-sonnet-4", - "max_tokens": 1024, - "messages": [{"role": "user", "content": "Hello!"}] - }' -``` - -## 模型映射 - -当 Amp CLI 请求的模型不可用时,Lime 可以自动映射到可用的替代模型。 - -### 配置 - -```yaml -ampcode: - model_mappings: - - from: "claude-opus-4.5" - to: "claude-sonnet-4" - - from: "gpt-5" - to: "gemini-2.5-pro" - - from: "claude-3-opus-20240229" - to: "claude-3-5-sonnet-20241022" -``` - -### 映射行为 - -1. 收到请求时检查模型名称 -2. 如果模型在映射列表中,替换为目标模型 -3. 使用替换后的模型名称路由请求 -4. 响应中保留原始请求的模型名称 - -## 管理端点代理 - -Lime 可以代理 Amp 的认证和账户管理端点到上游服务器。 - -### /api/auth/* - -代理认证相关请求。 - -```bash -# 登录 -POST /api/auth/login - -# 刷新 Token -POST /api/auth/refresh - -# 登出 -POST /api/auth/logout -``` - -### /api/user/* - -代理用户账户相关请求。 - -```bash -# 获取用户信息 -GET /api/user/profile - -# 获取使用统计 -GET /api/user/usage -``` - -### 配置 - -```yaml -ampcode: - upstream_url: "https://ampcode.com" - restrict_management_to_localhost: false -``` - -| 配置项 | 说明 | -|--------|------| -| `upstream_url` | Amp 上游服务器 URL | -| `restrict_management_to_localhost` | 是否限制管理端点只能从 localhost 访问 | - -## 使用场景 - -### 场景 1:使用本地 OAuth 凭证 - -你有 Kiro 的 Claude 订阅,想用 Amp CLI 但不想额外付费: - -1. 配置 Lime 加载 Kiro OAuth 凭证 -2. 在 Amp CLI 中配置 Lime 作为 API 端点 -3. Amp CLI 请求通过 Lime 路由到 Kiro 凭证 - -### 场景 2:模型替换 - -Amp CLI 请求 Claude Opus 4.5,但你只有 Sonnet 4 的访问权限: - -```yaml -ampcode: - model_mappings: - - from: "claude-opus-4.5" - to: "claude-sonnet-4" -``` - -### 场景 3:多 Provider 负载均衡 - -配置多个凭证,Lime 自动在它们之间负载均衡: - -```yaml -credential_pool: - kiro: - - id: "kiro-1" - token_file: "kiro/token-1.json" - - id: "kiro-2" - token_file: "kiro/token-2.json" -``` - -## Amp CLI 配置 - -在 Amp CLI 中配置 Lime: - -```bash -# 设置 API 端点 -amp config set api.base_url http://127.0.0.1:8999/api/provider - -# 设置 API Key -amp config set api.key your-lime-api-key -``` - -或在配置文件中: - -```yaml -# ~/.amp/config.yaml -api: - base_url: http://127.0.0.1:8999/api/provider - key: your-lime-api-key -``` - -## 错误处理 - -### 模型不可用 - -当请求的模型不可用且没有配置映射时: - -```json -{ - "error": { - "message": "Model 'claude-opus-4.5' is not available", - "type": "invalid_request_error", - "code": "model_not_found" - } -} -``` - -### 上游连接失败 - -当无法连接到 Amp 上游服务器时: - -```json -{ - "error": { - "message": "Failed to connect to upstream server", - "type": "upstream_error", - "code": "connection_failed" - } -} -``` - -### 凭证耗尽 - -当所有凭证都不可用时: - -```json -{ - "error": { - "message": "All credentials exhausted", - "type": "service_unavailable", - "code": "no_credentials_available" - } -} -``` - -响应头会包含 `Retry-After` 指示何时可以重试。 diff --git a/docs/content/05.troubleshooting/1.common-issues.md b/docs/content/05.troubleshooting/1.common-issues.md deleted file mode 100644 index 880ace7e9..000000000 --- a/docs/content/05.troubleshooting/1.common-issues.md +++ /dev/null @@ -1,125 +0,0 @@ ---- -title: 常见问题 -description: 按症状快速定位问题并恢复创作 -navigation: - icon: i-heroicons-question-mark-circle ---- - -# 常见问题 - -本页给你一个最快排查顺序: - -1. 看页面提示 -2. 看当前项目与资源选择是否正确 -3. 看连接状态与网络 -4. 再进入详细排查页 - -## 启动后看不到内容 - -### 症状 - -- 页面空白或内容未刷新 -- 明明生成过,但当前列表看不到 - -### 先检查 - -1. 是否选错了项目 -2. 是否切到了筛选分类(例如只看图片) -3. 是否处于搜索过滤状态 - -### 处理建议 - -- 先切回“全部”分类 -- 清空搜索词 -- 刷新当前页面再确认 - -## 图片没显示或数量不对 - -### 症状 - -- 资源页看不到已生成图片 -- 图片数量和预期不一致 - -### 先检查 - -1. 当前资源库(项目)是否正确 -2. 是否选在“图片”分类 -3. 图片是否已入库(自动或手动补录) - -### 处理建议 - -- 先确认当前项目与资源库选择一致 -- 回看 Claw 中对应图片任务是否已经成功并完成入库 -- 回资源页切换“全部”核对总量 - -## 生成失败或超时 - -### 症状 - -- 请求长时间无响应 -- 返回超时或失败提示 - -### 处理建议 - -1. 降低同一时间的并发任务数 -2. 缩短单次输入长度或拆成批次 -3. 稍后重试,观察是否为瞬时波动 -4. 必要时切换备用连接 - -## 认证或权限错误 - -### 常见提示 - -- `401`:认证失败 -- `403`:权限不足 - -### 处理建议 - -1. 重新确认连接状态 -2. 刷新或重建对应连接 -3. 再做一次小请求测试 - -详见 [连接鉴权问题](/troubleshooting/credential-errors)。 - -## 网络连接不稳定 - -### 常见提示 - -- 网络超时 -- DNS 解析失败 -- TLS/证书错误 - -### 处理建议 - -1. 检查本机网络 -2. 检查代理配置是否正确 -3. 避开高峰时段进行批量任务 - -详见 [网络与连接问题](/troubleshooting/connection-issues)。 - -## Windows 安装后打不开或白屏 - -### 常见症状 - -- 双击应用无反应 -- 启动后白屏 -- 提示缺少运行时或被 SmartScreen 拦截 - -### 处理建议 - -1. 优先重新下载安装 `Lime_*_x64-online-setup.exe` -2. 确认 `%APPDATA%\lime\` 与 `%USERPROFILE%\.lime\` 可写 -3. 如被 SmartScreen 拦截,确认来源可信后再继续 -4. 如果处于离线、内网或受限网络环境,改用 `Lime_*_x64-offline-setup.exe` -5. 如有条件,运行一键收集脚本后再反馈 - -详见 [Windows 启动与安装问题](/troubleshooting/windows-startup-issues)。 - -## 仍然无法解决 - -请整理以下信息后反馈: - -1. 问题发生时间 -2. 页面截图与错误文案 -3. 复现步骤(尽量 3 步内) -4. 当前版本号 diff --git a/docs/content/05.troubleshooting/2.credential-errors.md b/docs/content/05.troubleshooting/2.credential-errors.md deleted file mode 100644 index 217c13c08..000000000 --- a/docs/content/05.troubleshooting/2.credential-errors.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: 连接鉴权问题 -description: 处理连接失效、认证失败与账号状态异常 -navigation: - icon: i-heroicons-key ---- - -# 连接鉴权问题 - -本页用于处理“能打开应用,但调用失败”的问题。 - -## 快速判断 - -如果你看到以下报错,通常属于连接鉴权问题: - -- `401` 认证失败 -- `403` 权限不足 -- 连接状态显示已失效 - -## 3 步排查 - -### 第 1 步:检查连接状态 - -在连接管理页面确认当前连接是否可用。 - -### 第 2 步:刷新或重建连接 - -- 先尝试刷新 -- 刷新失败则重新登录或重新添加连接 - -### 第 3 步:做最小测试 - -使用一条简短请求验证是否恢复。 - -## 常见场景 - -### 场景 1:昨天还能用,今天突然失败 - -高概率是连接过期或上游状态变化。建议先重建该连接。 - -### 场景 2:部分模型可用,部分模型失败 - -可能是模型权限差异或连接配置不匹配。先换一个已知可用模型测试。 - -### 场景 3:导入配置后无法调用 - -导入通常不包含敏感凭证信息,需要重新校验连接。 - -## 进阶检查(可选) - -如果你需要定位更深层原因,可检查: - -- 本地凭证文件是否存在且可读 -- 连接使用的账号是否仍有效 -- 代理或网络环境是否变更 - -## 预防建议 - -1. 保留一个备用连接 -2. 关键活动前做一次连通性测试 -3. 定期清理长期失效连接 diff --git a/docs/content/05.troubleshooting/3.connection-issues.md b/docs/content/05.troubleshooting/3.connection-issues.md deleted file mode 100644 index 4ff8c0628..000000000 --- a/docs/content/05.troubleshooting/3.connection-issues.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: 网络与连接问题 -description: 处理超时、DNS、证书和代理相关问题 -navigation: - icon: i-heroicons-signal ---- - -# 网络与连接问题 - -当你频繁遇到超时、连接失败或证书错误时,按下面顺序排查。 - -## 排查顺序 - -1. 本机网络是否正常 -2. 代理是否配置正确 -3. 请求是否过于集中 -4. 是否为上游短时波动 - -## 常见症状与处理 - -### 连接超时 - -处理建议: - -1. 先减少并发 -2. 拆分任务批次 -3. 适当增加超时 -4. 稍后重试 - -### DNS 解析失败 - -处理建议: - -1. 切换网络后重试 -2. 检查系统 DNS 设置 -3. 清理 DNS 缓存后重试 - -### 证书错误 - -处理建议: - -1. 校准系统时间 -2. 检查网络代理是否拦截 HTTPS -3. 更换网络环境复测 - -## 代理相关 - -如果你使用代理,请重点检查: - -1. 代理地址格式是否正确 -2. 账号密码是否有效 -3. 排除列表是否包含本地地址 - -常见格式示例: - -- `http://proxy.example.com:8080` -- `http://user:password@proxy.example.com:8080` -- `socks5://proxy.example.com:1080` - -## 什么时候判断是上游问题 - -满足以下特征时,通常是上游波动: - -- 同一配置偶发失败、重试可恢复 -- 不同网络环境都出现短时错误 -- 一段时间后无需改配置自动恢复 - -## 仍未恢复怎么办 - -1. 记录失败时间段 -2. 保存错误提示和关键日志 -3. 先切换备用连接保障创作不中断 diff --git a/docs/content/05.troubleshooting/4.windows-startup-issues.md b/docs/content/05.troubleshooting/4.windows-startup-issues.md deleted file mode 100644 index 7603af8c5..000000000 --- a/docs/content/05.troubleshooting/4.windows-startup-issues.md +++ /dev/null @@ -1,128 +0,0 @@ ---- -title: Windows 启动与安装问题 -description: 处理打不开、白屏、缺少运行时与目录权限问题 -navigation: - icon: i-heroicons-computer-desktop ---- - -# Windows 启动与安装问题 - -如果 Windows 用户反馈“打不开”“白屏”“没有任何反应”,请优先按本页顺序排查。 - -## 最快处理顺序 - -1. 先确认安装包类型 -2. 再确认运行时与系统拦截 -3. 再检查本地目录权限 -4. 最后收集日志反馈 - -## 先确认安装包 - -推荐优先使用: - -- `Lime_*_x64-online-setup.exe` - -不建议优先分发: - -- 便携版压缩包 -- 旧的 `.msi` 安装包 - -原因: - -- 在线安装包体积更小,适合大多数 Windows 10/11 用户 -- 如果处于离线、内网或受限网络环境,请改用 `Lime_*_x64-offline-setup.exe` - -## 常见症状与处理 - -### 双击后无反应 - -处理建议: - -1. 确认下载来源可信 -2. 如果被 SmartScreen 拦截,点击“更多信息”后再确认是否继续 -3. 重新运行 Windows setup 安装包覆盖安装 -4. 安装后从开始菜单再次启动 - -### 启动后白屏 - -处理建议: - -1. 优先重装 Windows setup 安装包,补齐 WebView2 Runtime -2. 检查系统是否禁用了 Edge WebView2 Runtime -3. 再确认本地目录是否可写 - -### 提示缺少运行时 - -处理建议: - -1. 不要先手动找旧版运行时 -2. 先重新运行 Windows setup 安装包 -3. 如仍失败,再单独检查 WebView2 Runtime 是否安装完整 - -## 目录权限检查 - -以下目录至少要保证当前用户可读写: - -- `%APPDATA%\lime\` -- `%USERPROFILE%\.lime\` - -这些目录分别用于: - -- 配置与凭证副本 -- 数据库、日志、请求日志和部分运行时状态 - -如果目录不可写,常见表现包括: - -- 启动后立即退出 -- 白屏 -- 功能区能打开但数据无法加载 - -## 日志收集 - -反馈问题前,建议至少收集以下内容: - -- `%USERPROFILE%\.lime\logs\` -- `%USERPROFILE%\.lime\request_logs\` -- 问题出现时间 -- 安装包文件名 -- 页面或弹窗提示截图 - -### 一键收集(推荐给支持/开发环境) - -如果你有仓库脚本环境,可直接运行: - -```powershell -powershell -ExecutionPolicy Bypass -File .\scripts\windows-collect-support-bundle.ps1 -``` - -脚本会: - -- 打包 `%USERPROFILE%\.lime\logs\` 与 `request_logs\` -- 收集 WebView2、PowerShell、目录存在性等环境信息 -- 默认不打包 `config.yaml`、数据库和凭证正文,避免泄露敏感信息 - -执行完成后,会在桌面生成 `Lime-Support-时间戳.zip`。 - -如果应用本身还能打开,也可以在“设置 / API 服务器 / 诊断接口”区域点击“导出支持包”。 - -## 如果页面出现 Windows 启动自检提示 - -新版本会在部分场景下提示以下问题: - -- 应用数据目录不可写 -- 用户目录数据根不可写 -- 数据库不可访问 -- 未检测到 WebView2 Runtime -- 未检测到 PowerShell 或 `cmd.exe` - -建议按提示顺序处理,不要一开始就同时修改多项系统设置。 - -## 仍然无法恢复怎么办 - -请整理以下最小信息后反馈: - -1. Windows 版本 -2. Lime 版本 -3. 使用的安装包文件名 -4. 首次出现时间 -5. 日志目录压缩包 diff --git a/docs/content/06.development/1.architecture.md b/docs/content/06.development/1.architecture.md deleted file mode 100644 index 80725c595..000000000 --- a/docs/content/06.development/1.architecture.md +++ /dev/null @@ -1,229 +0,0 @@ ---- -title: 架构说明 -description: Lime 技术架构 -navigation: - icon: i-heroicons-cube-transparent ---- - -# 架构说明 - -Lime 是基于 Tauri 2.0 构建的跨平台桌面应用。 - -## 技术栈 - -| 层级 | 技术 | -|------|------| -| 前端 | React + TypeScript + Tailwind CSS | -| 后端 | Rust + Tauri 2.0 | -| 构建 | Vite | -| 包管理 | pnpm | - -## Tauri 前后端通信 - -### 架构图 - -``` -┌─────────────────────────────────────────────────────────┐ -│ Frontend (React) │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ -│ │ Dashboard │ │ Settings │ │ Monitoring │ │ -│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ -│ │ │ │ │ -│ └────────────────┼────────────────┘ │ -│ │ │ -│ ┌─────▼─────┐ │ -│ │ Tauri │ │ -│ │ Commands │ │ -│ └─────┬─────┘ │ -└──────────────────────────┼──────────────────────────────┘ - │ IPC -┌──────────────────────────┼──────────────────────────────┐ -│ ┌─────▼─────┐ │ -│ │ Command │ │ -│ │ Handler │ │ -│ └─────┬─────┘ │ -│ │ │ -│ ┌───────────────────────┼───────────────────────┐ │ -│ │ │ │ │ -│ ▼ ▼ ▼ │ -│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ -│ │Provider │ │Credential│ │ Router │ │ -│ │ Manager │ │ Pool │ │ │ │ -│ └────┬────┘ └────┬────┘ └────┬────┘ │ -│ │ │ │ │ -│ └──────────────────┼──────────────────────┘ │ -│ │ │ -│ ┌─────▼─────┐ │ -│ │ API Server│ │ -│ │ (Axum) │ │ -│ └───────────┘ │ -│ Backend (Rust) │ -└───────────────────────────────────────────────────────┘ -``` - -### 通信方式 - -前端通过 Tauri Commands 调用后端: - -```typescript -// 前端调用 -import { invoke } from '@tauri-apps/api/core'; - -const result = await invoke('get_credentials'); -``` - -```rust -// 后端处理 -#[tauri::command] -async fn get_credentials() -> Result, String> { - // 处理逻辑 -} -``` - -## Rust 后端模块 - -### 模块结构 - -``` -src-tauri/src/ -├── main.rs # 入口 -├── lib.rs # 库导出 -├── commands/ # Tauri 命令 -│ ├── mod.rs -│ ├── config_cmd.rs -│ ├── credential_cmd.rs -│ └── server_cmd.rs -├── credential/ # 凭证管理 -│ ├── mod.rs -│ ├── kiro.rs -│ ├── gemini.rs -│ └── qwen.rs -├── provider/ # Provider 实现 -│ ├── mod.rs -│ ├── anthropic.rs -│ ├── openai.rs -│ └── gemini.rs -├── router/ # 请求路由 -│ ├── mod.rs -│ └── rules.rs -├── converter/ # 协议转换 -│ ├── mod.rs -│ ├── openai_to_claude.rs -│ └── claude_to_openai.rs -├── server/ # API Server -│ ├── mod.rs -│ ├── handlers.rs -│ └── middleware.rs -└── config/ # 配置管理 - ├── mod.rs - └── yaml.rs -``` - -### 核心模块 - -#### Credential 模块 - -负责凭证的加载、刷新和管理: - -```rust -pub struct CredentialManager { - credentials: Vec, - refresh_scheduler: RefreshScheduler, -} - -impl CredentialManager { - pub async fn load_credentials(&mut self) -> Result<()>; - pub async fn refresh_token(&mut self, id: &str) -> Result<()>; - pub fn get_available(&self) -> Vec<&Credential>; -} -``` - -#### Provider 模块 - -实现不同 AI 服务的调用: - -```rust -#[async_trait] -pub trait Provider: Send + Sync { - async fn chat_completion(&self, request: ChatRequest) -> Result; - async fn stream_completion(&self, request: ChatRequest) -> Result>; -} -``` - -#### Router 模块 - -根据规则路由请求: - -```rust -pub struct Router { - rules: Vec, - default_provider: String, -} - -impl Router { - pub fn route(&self, model: &str) -> RoutingResult; -} -``` - -#### Converter 模块 - -在不同 API 格式之间转换: - -```rust -pub fn openai_to_claude(request: OpenAIRequest) -> ClaudeRequest; -pub fn claude_to_openai(response: ClaudeResponse) -> OpenAIResponse; -``` - -## 请求处理流程 - -``` -1. 客户端请求 → API Server (Axum) - │ -2. 认证检查 ────────┤ - │ -3. 路由匹配 ────────┤ Router - │ -4. 凭证选择 ────────┤ Credential Pool - │ -5. 协议转换 ────────┤ Converter - │ -6. Provider 调用 ───┤ Provider - │ -7. 响应转换 ────────┤ Converter - │ -8. 返回响应 ────────┘ -``` - -## 数据流 - -### 请求流程 - -1. 前端发起 API 请求 -2. Axum 服务器接收请求 -3. 中间件进行认证和日志 -4. Router 根据模型名称选择 Provider -5. Credential Pool 选择可用凭证 -6. Converter 转换请求格式 -7. Provider 调用实际 AI 服务 -8. Converter 转换响应格式 -9. 返回响应给客户端 - -### 事件流程 - -``` -后端事件 → Tauri Event → 前端监听 → UI 更新 -``` - -```rust -// 后端发送事件 -app.emit("credential-updated", payload)?; -``` - -```typescript -// 前端监听 -import { listen } from '@tauri-apps/api/event'; - -await listen('credential-updated', (event) => { - // 更新 UI -}); -``` diff --git a/docs/content/06.development/2.contributing.md b/docs/content/06.development/2.contributing.md deleted file mode 100644 index db4d6152a..000000000 --- a/docs/content/06.development/2.contributing.md +++ /dev/null @@ -1,200 +0,0 @@ ---- -title: 贡献指南 -description: 如何为 Lime 做贡献 -navigation: - icon: i-heroicons-heart ---- - -# 贡献指南 - -感谢你对 Lime 的关注!本指南帮助你开始贡献。 - -## 开发环境设置 - -### 前置要求 - -| 工具 | 版本 | -| --------- | ------- | -| Node.js | >= 22 | -| pnpm | >= 8 | -| Rust | >= 1.70 | -| Tauri CLI | >= 2.0 | - -### 安装依赖 - -```bash -# 克隆仓库 -git clone https://github.com/aiclientproxy/lime.git -cd lime - -# 安装前端依赖 -pnpm install - -# 安装 Tauri CLI -cargo install tauri-cli -``` - -### 开发模式 - -```bash -# 启动开发服务器 -pnpm tauri dev -``` - -### 构建 - -```bash -# 构建发布版本 -pnpm tauri build -``` - -## 代码规范 - -### TypeScript/React - -- 使用 ESLint 和 Prettier -- 遵循 React Hooks 规范 -- 组件使用函数式写法 - -```bash -# 检查代码 -pnpm lint - -# 格式化代码 -pnpm format -``` - -### Rust - -- 使用 rustfmt 格式化 -- 使用 clippy 检查 -- 遵循 Rust API Guidelines - -```bash -# 格式化 -cargo fmt - -# 检查 -cargo clippy -``` - -### 提交规范 - -使用 Conventional Commits: - -``` -feat: 添加新功能 -fix: 修复 bug -docs: 更新文档 -style: 代码格式调整 -refactor: 代码重构 -test: 添加测试 -chore: 构建/工具变更 -``` - -示例: - -``` -feat(credential): 添加 Qwen 凭证支持 -fix(router): 修复路由规则匹配问题 -docs: 更新安装指南 -``` - -## PR 流程 - -### 1. Fork 仓库 - -在 GitHub 上 Fork 项目到你的账户。 - -### 2. 创建分支 - -```bash -git checkout -b feature/your-feature -``` - -### 3. 开发和测试 - -- 编写代码 -- 添加测试 -- 确保所有测试通过 - -### 4. 提交代码 - -```bash -git add . -git commit -m "feat: your feature description" -git push origin feature/your-feature -``` - -### 5. 创建 PR - -1. 在 GitHub 上创建 Pull Request -2. 填写 PR 描述 -3. 等待 Review - -### PR 检查清单 - -- [ ] 代码通过 lint 检查 -- [ ] 添加了必要的测试 -- [ ] 更新了相关文档 -- [ ] 提交信息符合规范 - -## 项目结构 - -``` -lime/ -├── src/ # 前端源码 -│ ├── components/ # React 组件 -│ ├── pages/ # 页面组件 -│ ├── hooks/ # 自定义 Hooks -│ ├── lib/ # 工具函数 -│ └── styles/ # 样式文件 -├── src-tauri/ # Rust 后端 -│ ├── src/ # 源码 -│ ├── Cargo.toml # 依赖配置 -│ └── tauri.conf.json # Tauri 配置 -├── docs/ # 文档 -└── public/ # 静态资源 -``` - -## 测试 - -### 前端测试 - -```bash -# 运行测试 -pnpm test - -# 运行测试并生成覆盖率 -pnpm test:coverage -``` - -### 后端测试 - -```bash -cd src-tauri -cargo test -``` - -## 问题反馈 - -### 报告 Bug - -1. 搜索是否已有相同问题 -2. 创建新 Issue -3. 提供详细信息: - - 操作系统和版本 - - Lime 版本 - - 复现步骤 - - 错误日志 - -### 功能建议 - -1. 创建 Feature Request Issue -2. 描述功能需求 -3. 说明使用场景 - -## 社区 - -- GitHub Issues: 问题反馈 -- GitHub Discussions: 讨论交流 diff --git a/docs/content/06.development/3.building.md b/docs/content/06.development/3.building.md deleted file mode 100644 index 2f02a7224..000000000 --- a/docs/content/06.development/3.building.md +++ /dev/null @@ -1,283 +0,0 @@ ---- -title: 构建指南 -description: 本地开发和构建发布 -navigation: - icon: i-heroicons-wrench-screwdriver ---- - -# 构建指南 - -本指南介绍如何在本地开发和构建 Lime。 - -## 本地开发 - -::alert{type="warning"} -Lime 桌面端当前仅支持 macOS 与 Windows,本页不再提供 Linux 打包与发布说明。 -:: - -### 环境准备 - -1. **安装 Node.js** - -```bash -# 使用 nvm 安装 -nvm install 22 -nvm use 22 -``` - -Windows 用户请使用 Node.js 官方安装器安装 22.x,并重新打开终端后通过 `node -v` 确认版本。 - -2. **安装 pnpm** - -```bash -npm install -g pnpm -``` - -3. **安装 Rust** - -```bash -# macOS -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - -# Windows -# 下载并运行 rustup-init.exe -``` - -4. **安装 Tauri 依赖** - -**macOS:** - -```bash -xcode-select --install -``` - -**Windows:** - -- 安装 Visual Studio Build Tools -- 安装 WebView2(开发模式必需;对外分发时默认推荐在线小包,离线或受限网络环境再提供离线大包) - -### 启动开发 - -```bash -# 安装依赖 -pnpm install - -# 启动开发模式 -pnpm tauri dev -``` - -开发模式特性: - -- 前端热重载 -- Rust 代码变更自动重新编译 -- 开发者工具可用 - -### 开发配置 - -#### 前端配置 - -`vite.config.ts`: - -```typescript -export default defineConfig({ - plugins: [react()], - server: { - port: 1420, - strictPort: true, - }, -}); -``` - -#### Tauri 配置 - -`src-tauri/tauri.conf.json`: - -```json -{ - "build": { - "devPath": "http://localhost:1420", - "distDir": "../dist" - } -} -``` - -## 构建发布 - -### 构建命令 - -```bash -# 构建当前平台 -pnpm tauri build - -# 构建 debug 版本 -pnpm tauri build --debug -``` - -### 自动更新产物与签名 - -Lime 当前的桌面端升级流程分成两步: - -- 检查更新:客户端直接请求静态清单 `latest.json` -- 安装更新:客户端使用 Tauri updater 校验签名并安装对应平台包 - -`src-tauri/tauri.conf.json` 与 `src-tauri/tauri.conf.headless.json` 已启用 `createUpdaterArtifacts: true`,构建发布包时会额外生成 updater 需要的签名产物与 `latest.json`。 - -本地或 CI 构建发布版本时,至少需要准备以下环境变量: - -```bash -# updater 校验使用的公钥;编译时注入到桌面端 -export LIME_UPDATER_PUBLIC_KEY="..." - -# Tauri 生成 latest.json 和签名文件时使用的私钥 -export TAURI_SIGNING_PRIVATE_KEY="..." -export TAURI_SIGNING_PRIVATE_KEY_PASSWORD="..." -``` - -如果缺少 `LIME_UPDATER_PUBLIC_KEY`,应用仍可读取 `latest.json` 显示新版本信息,但会降级为只能跳转发布页手动下载,无法执行应用内安装。 - -### 构建产物 - -| 平台 | 产物位置 | -| ------- | --------------------------------------- | -| macOS | `src-tauri/target/release/bundle/dmg/` | -| Windows | `src-tauri/target/release/bundle/nsis/` | - -### 跨平台构建 - -#### macOS 构建 - -```bash -# 构建 Apple Silicon -pnpm tauri build --target aarch64-apple-darwin - -# 构建 Intel -pnpm tauri build --target x86_64-apple-darwin - -# 构建 Universal -pnpm tauri build --target universal-apple-darwin -``` - -#### Windows 构建 - -```bash -# 构建 64 位 Windows 在线安装包(推荐,体积更小,安装时按需下载 WebView2) -pnpm tauri build --target x86_64-pc-windows-msvc --config src-tauri/tauri.windows.online.conf.json - -# 构建 64 位 Windows 离线安装包(体积更大,内置离线 WebView2 安装器) -pnpm tauri build --target x86_64-pc-windows-msvc --config src-tauri/tauri.windows.conf.json -``` - -> 建议默认对外分发在线小包;只有内网、离线或受限网络环境,再提供离线大包。 - -## 版本管理 - -### 更新版本号 - -1. 更新 `package.json`: - -```json -{ - "version": "1.0.1" -} -``` - -2. 更新 `src-tauri/Cargo.toml`: - -```toml -[package] -version = "1.0.1" -``` - -3. 更新 `src-tauri/tauri.conf.json`: - -```json -{ - "version": "1.0.1" -} -``` - -### 创建发布 - -```bash -# 创建 tag -git tag v1.0.1 -git push origin v1.0.1 -``` - -## CI/CD - -### GitHub Actions - -项目使用 GitHub Actions 自动构建: - -- Push 到 main 分支触发构建 -- 创建 tag 触发发布 -- Release 工作流会把 `LIME_UPDATER_PUBLIC_KEY`、`TAURI_SIGNING_PRIVATE_KEY`、`TAURI_SIGNING_PRIVATE_KEY_PASSWORD` 注入构建环境,用于生成可校验的 updater 清单与安装包签名 - -### 构建矩阵 - -| 平台 | 架构 | Runner | -| ------- | ----- | ------------ | -| macOS | arm64 | macos-latest | -| macOS | x64 | macos-13 | -| Windows | x64 | windows-2022 | - -## 调试 - -### 前端调试 - -开发模式下按 `F12` 打开开发者工具。 - -### 后端调试 - -```bash -# 启用 Rust 日志 -RUST_LOG=debug pnpm tauri dev -``` - -### 日志位置 - -| 平台 | 路径 | -| ------- | ---------------------- | -| macOS | `~/Library/Logs/Lime/` | -| Windows | `%APPDATA%\Lime\logs\` | - -## 常见问题 - -### 构建失败 - -1. 确保所有依赖已安装 -2. 清理构建缓存: - -```bash -# 清理前端 -rm -rf node_modules dist -pnpm install - -# 清理 Rust -cd src-tauri -cargo clean -``` - -### 签名问题 - -macOS 构建需要代码签名: - -```bash -# 设置签名身份 -export APPLE_SIGNING_IDENTITY="Developer ID Application: ..." -``` - -Windows 构建强烈建议签名: - -```bash -# 设置签名证书 -export TAURI_SIGNING_PRIVATE_KEY="..." -``` - -如果要让桌面端“检查更新后直接安装”可用,还需要同时配置: - -```bash -export LIME_UPDATER_PUBLIC_KEY="..." -export TAURI_SIGNING_PRIVATE_KEY_PASSWORD="..." -``` diff --git a/docs/content/06.development/4.operations.md b/docs/content/06.development/4.operations.md deleted file mode 100644 index 8fd01393b..000000000 --- a/docs/content/06.development/4.operations.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: 上线运维 -description: 生产就绪的最小运维清单 -navigation: - icon: i-heroicons-wrench-screwdriver ---- - -# 上线运行与运维(生产就绪最小版) - -本页面用于“马上上线且长期稳定运行”的最小运维闭环,避免上线后因配置、备份或回滚缺失导致不可恢复的问题。 - -## 上线前检查 - -- 确认服务仅本地监听:`server.host = 127.0.0.1`(当前版本仅支持本地监听) -- 设置强 API Key:不要使用默认值 `proxy_cast` -- 确认日志保留策略:`logging.retention_days` 合理(建议 >= 7 天) -- 确认凭证与配置已正确导入,并完成一次启动 + 健康检查 - -## 运行健康检查 - -- HTTP 健康检查:`GET /health` -- 关键字段应包含 `status=healthy` 与 `version` -- 建议在上线后做一次 API 冒烟请求(如 `/v1/models`) - -## 备份与恢复(必须) - -当前版本需要手动备份以下路径: - -- 配置文件(macOS: `~/Library/Application Support/lime/config.yaml`,Linux: `~/.config/lime/config.yaml`,Windows: `%APPDATA%\\lime\\config.yaml`) -- 凭证池副本目录(导入的凭证文件):macOS `~/Library/Application Support/lime/credentials/`,Linux `~/.local/share/lime/credentials/`,Windows `%APPDATA%\\lime\\credentials\\` -- OAuth 凭证目录:`~/.lime/auth/` -- 数据库文件:`~/.lime/lime.db` -- 日志目录:`~/.lime/logs/`、`~/.lime/request_logs/` - -恢复步骤(顺序建议): - -1. 停止应用 -2. 恢复 `config.yaml` -3. 恢复 `credentials` 目录、`auth` 目录与数据库 `lime.db` -4. 如需保留历史日志,恢复 `logs/` 与 `request_logs/` -5. 启动应用并验证 `/health` 与关键功能 - -## Windows 启动失败排查 - -- 优先确认用户安装的是 `Lime_*_x64-online-setup.exe`;离线、内网或受限网络环境再提供 `Lime_*_x64-offline-setup.exe` -- 首次启动若提示缺少运行时,优先重新运行 Windows setup 安装包;如果在线安装失败,再切换到 offline 安装包 -- 检查 `%APPDATA%\lime\` 与 `%USERPROFILE%\.lime\` 是否可写;数据库、日志与部分运行时状态依赖这两个目录 -- 收集 `%USERPROFILE%\.lime\logs\` 与 `%USERPROFILE%\.lime\request_logs\` 作为一线排障材料 -- 若前端出现 Windows 启动自检提示,按提示项优先检查目录权限、数据库可访问性、WebView2 与 Shell 可用性 - -## 回滚策略 - -- 如果升级失败,恢复备份的 `config.yaml` 与 `lime.db` -- 使用上一版本安装包覆盖安装 -- 完成健康检查与冒烟测试 - -## 发布质量门槛(最小) - -- `cd src-tauri && cargo test` -- `cd src-tauri && cargo clippy` -- `npm test` -- `npm run lint` -- `npm run build` diff --git a/docs/content/06.development/5.plugin-development.md b/docs/content/06.development/5.plugin-development.md deleted file mode 100644 index e60759884..000000000 --- a/docs/content/06.development/5.plugin-development.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: 插件开发(迁移说明) -description: 本章节已迁移至开放平台文档 -navigation: - icon: i-heroicons-arrow-top-right-on-square ---- - -# 插件开发(迁移说明) - -::alert{type="info"} -插件开发文档已迁移,请阅读:[开放平台 - 插件开发指南](/open-platform/plugin-development)。 -:: - -迁移后,开发者文档与用户文档分层更清晰: - -- 开放平台:插件规范、接入流程、生态能力 -- 用户指南:插件安装与使用 diff --git a/docs/content/07.legal/1.disclaimer.md b/docs/content/07.legal/1.disclaimer.md index 1dcaf7ec2..dcec1035f 100644 --- a/docs/content/07.legal/1.disclaimer.md +++ b/docs/content/07.legal/1.disclaimer.md @@ -1,57 +1,65 @@ --- title: 免责声明 -description: 使用条款和法律声明 +description: Lime 使用条款与法律说明 navigation: icon: i-heroicons-scale --- # 免责声明 -## 使用目的 +## 适用范围 -Lime 是一款开源工具,其设计初衷是帮助用户**充分利用已订阅的 AI 服务 Token**,在更多场景中发挥其价值。 +Lime 是一款本地优先的内容闭环 Agent 桌面应用。 +你在使用 Lime 及其接入的模型、插件、MCP 服务、浏览器连接器、Webhook 与其它外部服务时,应自行确保符合所在地法律法规以及对应服务条款。 ::alert{type="warning"} -**重要提示**: 本工具仅限于个人合法使用,严禁用于任何非法盈利目的。 +**重要提示**: 请仅在合法、合规、可授权的前提下使用本产品及其外部连接能力。 :: -## 合法使用范围 +## 你需要自行确认的事项 -本工具的合法使用场景包括但不限于: +使用 Lime 前,请至少确认以下事项: -- ✅ 个人学习和研究 -- ✅ 个人开发项目中使用已订阅的 AI 服务 -- ✅ 在不同开发工具间复用个人订阅额度 -- ✅ 提高个人工作效率 +1. 你有权使用接入的模型账号、API Key、OAuth 凭证、插件包或 MCP 服务 +2. 你有权处理导入到 Lime 的文本、图片、音视频、网页、代码和其它素材 +3. 你已理解目标平台、模型服务商和第三方工具的使用限制 +4. 你不会把本产品用于违法、侵权、欺诈、骚扰、滥用计算资源或规避服务限制等行为 ## 禁止行为 -以下行为严格禁止: +以下行为明确禁止: -- ❌ 将本工具用于商业盈利目的 -- ❌ 转售或分享他人的 AI 服务凭证 -- ❌ 违反 AI 服务提供商的服务条款 -- ❌ 任何形式的非法活动 +- ❌ 使用未经授权的账号、密钥、Cookie、凭证或第三方连接 +- ❌ 上传、处理或传播你无权使用的内容、数据或素材 +- ❌ 将 Lime 用于违法、侵权、诈骗、骚扰、恶意自动化、绕过风控或违反平台条款的场景 +- ❌ 通过插件、Webhook、MCP、连接器或脚本向外泄露敏感信息 +- ❌ 将本产品宣传为对第三方平台、模型服务或连接结果提供官方背书 ## 责任声明 -1. **用户责任**: 用户应确保其使用行为符合所在地区的法律法规,以及相关 AI 服务提供商的服务条款。 +1. **用户责任**:你应对自己的配置、连接、导入内容、生成结果和发布行为负责。 +2. **第三方风险**:模型服务、插件、MCP 服务、Webhook、浏览器连接器与外部服务均由对应提供方独立维护,其可用性、安全性与合规性不由 Lime 保证。 +3. **风险自担**:使用本产品可能带来内容误判、外部服务波动、账号限制、连接失败、数据丢失或其它损失,相关风险由用户自行承担。 +4. **按现状提供**:本产品按“现状”提供,不提供任何明示或暗示担保。 -2. **风险自担**: 使用本工具所产生的任何后果由用户自行承担,包括但不限于账户封禁、服务终止等。 +## 内容与结果说明 -3. **无担保**: 本工具按"现状"提供,不提供任何明示或暗示的担保。 +Lime 生成、改写、整理、抓取、导出或分发的内容,仍需由用户自行复核。 +尤其是以下场景,请在发布或对外使用前做人工确认: -4. **免责**: 开发者不对因使用本工具而导致的任何直接或间接损失承担责任。 +- 涉及事实正确性、日期、引用、来源、版权、隐私、品牌承诺的内容 +- 涉及合同、医疗、法律、财务、监管合规等高风险领域的内容 +- 通过自动化、Webhook、插件或外部服务进一步传播的内容 -## 服务条款遵守 +## 第三方条款遵守 -使用本工具时,请务必遵守以下服务提供商的使用条款: +当你接入第三方模型、平台或服务时,请同时遵守对应条款与政策。常见示例包括但不限于: - [Anthropic 使用政策](https://www.anthropic.com/policies) - [Google AI 服务条款](https://policies.google.com/terms) -- [阿里云服务条款](https://terms.alibabacloud.com/) - [OpenAI 使用政策](https://openai.com/policies) +- [阿里云服务条款](https://terms.alibabacloud.com/) ## 联系我们 -如对本声明有任何疑问,请通过 GitHub Issues 联系我们。 +如对本声明有疑问,请通过 GitHub Issues 或项目维护渠道联系。 diff --git a/docs/content/08.open-platform/1.overview.md b/docs/content/08.open-platform/1.overview.md index 3c8c3571f..48c317dad 100644 --- a/docs/content/08.open-platform/1.overview.md +++ b/docs/content/08.open-platform/1.overview.md @@ -1,41 +1,50 @@ --- -title: 开放平台概览 -description: 面向开发者与生态合作方的扩展能力 +title: 扩展接入概览 +description: 当前只保留插件打包与 Connect 接入说明 navigation: icon: i-heroicons-cube-transparent --- -# 开放平台概览 - -开放平台面向开发者与生态合作方,用于扩展 Lime 的能力边界。 +# 扩展接入概览 ::alert{type="info"} -如果你是普通创作者,可先跳过本章节。 +当前这组“扩展接入”文档只保留仍有实现锚点的高级接入说明,不再把插件市场、生态合作流转或未落地的扩展能力写成既成事实。 :: -## 平台能力 +如果你是普通创作者,可以直接跳过本章节。这里面向的是需要扩展 Lime、分发接入包、或让外部系统与 Lime 建立连接的开发者。 -### 插件系统 +## 当前保留能力 -用于扩展工具、工作流和界面能力。 +### 插件打包与安装 -[了解更多 →](/open-platform/plugins) +当前文档覆盖的是已经落地的插件安装链路: -### Connect 能力 +- 本地文件安装 +- URL 安装 +- `plugin.json` 清单约束 +- UI surface 与二进制字段的基础说明 -用于外部平台与 Lime 的配置联动与生态集成。 +[查看插件打包说明 →](/open-platform/plugin-development) -[了解更多 →](/open-platform/connect) +### Connect 接入 -## 谁适合阅读 +当前文档覆盖的是已经落地的 Connect 能力: -- 需要开发自定义插件的团队 -- 需要对接外部系统的开发者 -- 需要建设生态能力的合作方 +- `lime://connect` 深链写入连接参数 +- relay 注册表校验 +- 用户确认后保存 +- 可选 webhook 回调 + +[查看 Connect 说明 →](/open-platform/connect) + +## 适合阅读的人 + +- 需要打包和分发插件的团队 +- 需要把外部站点或服务接入 Lime 的开发者 +- 需要对接 Connect 深链或回调的集成方 ## 快速入口 -- [插件中心](/open-platform/plugins) -- [插件开发指南](/open-platform/plugin-development) +- [插件打包指南](/open-platform/plugin-development) - [Connect 接入](/open-platform/connect) -- [Connect 集成说明](/open-platform/connect-integration) +- [Connect 回调字段](/open-platform/connect-webhook) diff --git a/docs/content/08.open-platform/2.plugins.md b/docs/content/08.open-platform/2.plugins.md deleted file mode 100644 index 7e0b43834..000000000 --- a/docs/content/08.open-platform/2.plugins.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: 开放平台 - 插件中心 -description: 面向开发者的插件安装、管理与发布能力 -navigation: - icon: i-heroicons-puzzle-piece ---- - -# 开放平台 - 插件中心 - -::alert{type="info"} -本页面向开发者与高级用户。普通创作者可使用用户指南中的插件页。 -:: - -Lime 支持通过插件扩展能力,适用于自定义工具、自动化流程和生态集成。 - -## 你可以做什么 - -- 安装推荐插件或第三方插件包 -- 管理插件启用状态与版本 -- 查看插件加载与执行状态 -- 在工具入口中使用插件能力 - -## 安装方式 - -1. 推荐插件一键安装 -2. 通过 URL 安装 ZIP 包 -3. 通过本地文件安装 ZIP 包 - -## 管理建议 - -1. 先安装高频插件,再逐步扩展 -2. 每次新增插件后做一次功能验证 -3. 定期清理长期不用的插件 - -## 下一步 - -- [插件开发指南](/open-platform/plugin-development) -- [开放平台概览](/open-platform/overview) diff --git a/docs/content/08.open-platform/3.plugin-development.md b/docs/content/08.open-platform/3.plugin-development.md index f27b38975..b79b04eeb 100644 --- a/docs/content/08.open-platform/3.plugin-development.md +++ b/docs/content/08.open-platform/3.plugin-development.md @@ -1,44 +1,125 @@ --- -title: 开放平台 - 插件开发指南 -description: 开发 Lime 插件的规范与最佳实践 +title: 插件打包指南 +description: 当前插件安装链路、清单字段与打包约束 navigation: icon: i-heroicons-code-bracket-square --- -# 开放平台 - 插件开发指南 +# 插件打包指南 ::alert{type="info"} -本页面向开发者。若你不开发插件,可跳过。 +本页只记录当前已经落地的插件安装与清单约束。插件市场、审核流、灰度发布和未稳定的原生扩展能力不在当前承诺范围内。 :: -本文档说明插件类型、打包方式和开发建议,帮助你把能力稳定接入 Lime。 +如果你准备给 Lime 打包插件,当前最重要的事实源是安装链路本身:插件包通过本地文件或 URL 进入 Lime,安装器会校验压缩格式并读取包内清单。 -## 插件类型 +## 当前打包入口 -### 脚本插件 +当前公开可确认的安装入口只有两类: -基于 JavaScript/TypeScript,通过 Hook 扩展行为。 +- 本地文件安装 +- URL 安装 -### 二进制插件 +当前安装器接受这些压缩格式: -通过独立可执行文件提供系统级能力,适合重计算或本地工具集成。 +- `.zip` +- `.tar.gz` +- `.tgz` -## 基础结构 +建议把“插件根目录”直接打进压缩包,并确保包内能明确定位到 `plugin.json`。 -插件以 ZIP 分发,至少包含: +## `plugin.json` 是当前安装清单 -- `plugin.json`:元数据与入口定义 -- 可选配置文件与资源文件 +当前安装器会从压缩包中提取并校验 `plugin.json`。对外发布时,建议始终提供这份文件,并在发布前用当前 Lime 版本做一次真实安装验证。 -## 开发建议 +一个最小示例: -1. 先做最小可用版本 -2. 明确输入输出协议 -3. 做异常与超时处理 -4. 提供清晰的版本兼容说明 +```json +{ + "name": "example_plugin", + "version": "1.0.0", + "plugin_type": "script", + "entry": "config.json", + "hooks": ["on_request"], + "ui": { + "surfaces": ["tools"], + "entry": "dist/index.js", + "title": "Example Plugin" + } +} +``` -## 发布建议 +## 当前清单字段 -1. 版本号语义化管理 -2. 发布前做跨平台验证 -3. 提供回滚策略与变更日志 +### 必填基础字段 + +- `name` + - 不能为空 + - 只允许字母、数字、连字符和下划线 + - 长度不能超过 `64` +- `version` + - 需要满足当前 semver 校验 + - 当前接受 `x.y`、`x.y.z`、`x.y.z-suffix` 这类格式 +- `entry` + - 不能为空 + - 表示插件入口文件路径 + +### 常用可选字段 + +- `description` +- `author` +- `homepage` +- `license` +- `min_lime_version` +- `config_schema` +- `hooks` + +如果声明了 `hooks`,当前只接受由字母、数字、下划线或冒号组成的名称。 + +### `plugin_type` + +当前清单 schema 识别这些类型: + +- `script` +- `binary` +- `native` + +其中当前公开主路径应默认按 `script` 打包;`native` 仍属于预留能力,不建议作为对外稳定发布前提。若使用 `binary`,还需要补充二进制下载与平台映射信息。 + +### `ui` + +如果插件需要在 Lime 内暴露界面,可声明 `ui` 段。当前已存在的字段包括: + +- `surfaces` +- `icon` +- `title` +- `entry` +- `description` +- `default_width` +- `default_height` + +`surfaces` 用于声明 UI 入口位置。当前代码中常见的 surface 标识包括 `tools`、`sidebar`、`main`、`settings`;发布前仍应在目标版本中实际验证展示结果。 + +### `binary` + +如果插件类型为 `binary`,当前清单还支持补充: + +- `binary_name` +- `github_owner` +- `github_repo` +- `platform_binaries` +- `checksum_file` + +这类插件通常还需要分别准备各平台产物,并验证可执行文件权限与下载地址是否可用。 + +## 发布前最少检查 + +建议至少完成以下检查: + +1. 用当前 Lime 版本做一次真实安装 +2. 确认 `plugin.json` 能通过安装器校验 +3. 确认插件能出现在 `已安装插件包`,并在需要时进入 `已加载插件` +4. 如果声明了 `ui`,确认目标 surface 能正常出现 +5. 如果声明了 `min_lime_version`,同步写清最低版本要求 + +当前文档只保证“安装链路与字段约束”的说明,不再把尚未稳定的插件生态流程写成既成事实。 diff --git a/docs/content/08.open-platform/4.connect.md b/docs/content/08.open-platform/4.connect.md index d80cf0cf1..0140d0fa1 100644 --- a/docs/content/08.open-platform/4.connect.md +++ b/docs/content/08.open-platform/4.connect.md @@ -1,32 +1,37 @@ --- -title: 开放平台 - Connect -description: 面向服务提供方的一键配置接入能力 +title: Connect 接入 +description: 面向中转服务提供方的 Lime Deep Link 接入说明 navigation: icon: i-heroicons-link --- -# 开放平台 - Connect +# Connect 接入 ::alert{type="info"} -本页面向生态合作方与平台接入方。普通创作者可跳过。 +本页面面向已进入 Lime Connect 注册表,或准备按当前 Deep Link / webhook 协议接入的中转服务提供方。 :: -Connect 通过 Deep Link 提供“一键配置”能力,帮助外部平台将配置快速带入 Lime。 +Connect 通过 `lime://connect` Deep Link,把外部服务下发的 API Key 一键带入 Lime。 -## 核心价值 +## 当前边界 -- 用户:减少手动配置步骤 -- 服务提供方:降低接入门槛 -- 平台:提升配置成功率 +当前 Connect 文档只覆盖已经落地的运行时边界: -## 一键配置流程 +- `lime://connect` Deep Link 参数 +- 已注册中转商的展示与确认流程 +- 可选的统计回调行为 -1. 用户在外部平台点击一键配置 -2. 浏览器打开 `lime://` 链接 -3. Lime 弹出确认 -4. 用户确认后完成导入 +不再在这里承诺额外的审核、灰度或人工接入流程。 -## 基础协议 +## 基础流程 + +1. 外部服务生成 `lime://connect` 链接 +2. 用户点击链接后,Lime 解析参数 +3. Lime 按 `relay` 查询本地已加载的中转商注册表 +4. 用户确认后,API Key 被保存到 Lime 的当前 Provider 入口 +5. 若该中转商配置了 webhook,Lime 会异步发送结果回调 + +## Deep Link 协议 ```text lime://connect?relay={relay_id}&key={api_key}&name={key_name}&ref={ref_code} @@ -34,12 +39,26 @@ lime://connect?relay={relay_id}&key={api_key}&name={key_name}&ref={ref_code} | 参数 | 必填 | 说明 | |------|------|------| -| `relay` | ✅ | 服务方唯一标识 | -| `key` | ✅ | API Key | -| `name` | ❌ | 显示名称 | -| `ref` | ❌ | 推广或渠道标记 | +| `relay` | ✅ | 中转商唯一标识 | +| `key` | ✅ | 下发给用户的 API Key | +| `name` | ❌ | 在 Lime 中展示的 Key 名称 | +| `ref` | ❌ | 渠道或推广标记,运行时会映射为 `ref_code` | -## 下一步 +## 运行时行为 + +- `relay` 与 `key` 缺失时,Lime 会拒绝该链接 +- 中转商已在注册表中时,Lime 会展示品牌、链接和协议等信息 +- 中转商不在注册表中时,仍会给出未验证提示,但不会自动拥有注册表元数据 +- 如果该中转商配置了 webhook,用户确认、取消或失败时会触发异步回调 + +## 回调与统计 + +Connect 回调是可选能力: + +- 未注册的中转商不会发送回调 +- 注册表中未配置 `webhook.callback_url` 的中转商不会发送回调 +- 回调地址必须使用 `https://` + +详细字段见: -- [Connect 接入指南](/open-platform/connect-integration) - [统计回调(Webhook)](/open-platform/connect-webhook) diff --git a/docs/content/08.open-platform/5.connect-integration.md b/docs/content/08.open-platform/5.connect-integration.md deleted file mode 100644 index e8f15bb9b..000000000 --- a/docs/content/08.open-platform/5.connect-integration.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: 开放平台 - Connect 接入指南 -description: 外部服务接入 Connect 的实施步骤与字段规范 -navigation: - icon: i-heroicons-wrench-screwdriver ---- - -# 开放平台 - Connect 接入指南 - -::alert{type="info"} -本页面向生态合作方技术团队。 -:: - -本文档说明如何把你的服务接入 Connect,并完成一键配置联动。 - -## 接入步骤 - -1. 准备服务方元数据 -2. 按规范生成配置文件 -3. 提交审核或接入申请 -4. 联调 Deep Link -5. 灰度发布并观察回调数据 - -## 配置文件建议 - -建议包含: - -- 唯一标识与展示信息 -- 官网与文档链接 -- API 基础信息 -- 回调地址(可选) - -## 联调重点 - -1. Deep Link 参数完整性 -2. 用户确认流程体验 -3. 异常输入的兜底处理 -4. 回调状态与业务统计一致性 - -## 上线前检查 - -1. 参数合法性校验 -2. 失效 Key 的处理策略 -3. 安全与速率限制策略 -4. 版本兼容说明 diff --git a/docs/content/08.open-platform/6.connect-webhook.md b/docs/content/08.open-platform/6.connect-webhook.md index 12467ba76..e3b7c1585 100644 --- a/docs/content/08.open-platform/6.connect-webhook.md +++ b/docs/content/08.open-platform/6.connect-webhook.md @@ -1,58 +1,110 @@ --- -title: 开放平台 - 统计回调(Webhook) -description: Connect 回调事件格式与接入建议 +title: Connect 统计回调(Webhook) +description: Connect 回调事件字段与发送行为 navigation: icon: i-heroicons-arrow-path-rounded-square --- -# 开放平台 - 统计回调(Webhook) +# Connect 统计回调(Webhook) ::alert{type="info"} -本页面向生态合作方技术团队。 +本页面向已经在 Connect 注册表中配置 webhook 的服务提供方。 :: -Webhook 用于回传配置行为结果,帮助你统计接入效果。 +Connect webhook 用于回传用户在 Lime 中处理 Deep Link 的结果。 -## 回调时机 +## 什么时候会发送 -常见状态: +只有同时满足以下条件时,Lime 才会发送回调: -- `success`:用户确认并配置成功 -- `cancelled`:用户取消 -- `error`:执行失败 +1. `relay` 能在注册表中找到 +2. 该中转商配置了 `webhook.callback_url` +3. `callback_url` 为 `https://` -## 请求示例 +如果任一条件不满足,Lime 会直接跳过,不会阻塞主流程。 -```http -POST https://your-domain.com/lime/callback -Content-Type: application/json +## 状态类型 +- `success` + 用户确认并成功保存 API Key +- `cancelled` + 用户取消添加 +- `error` + 保存流程失败 + +## Payload 字段 + +成功或取消时,Lime 会发送如下 JSON: + +```json { "event": "connect", "status": "success", "relay_id": "your-relay", - "ref": "campaign-2026", - "timestamp": "2026-02-16T10:00:00Z" + "ref_code": "campaign-2026", + "key_prefix": "sk-abc12", + "timestamp": "2026-04-19T10:00:00Z", + "client": { + "version": "x.y.z", + "platform": "macos" + } } ``` -## 字段建议 +错误时会额外包含: -- `event`:事件类型 -- `status`:状态值 -- `relay_id`:服务方标识 -- `ref`:渠道标记 -- `timestamp`:事件时间 +```json +{ + "event": "connect", + "status": "error", + "relay_id": "your-relay", + "key_prefix": "sk-abc12", + "timestamp": "2026-04-19T10:00:00Z", + "client": { + "version": "x.y.z", + "platform": "windows" + }, + "error_code": "SAVE_FAILED", + "error_message": "failed to persist api key" +} +``` -## 安全建议 +字段说明: -1. 仅接受 HTTPS 回调 -2. 校验来源与参数完整性 -3. 对回调做幂等处理 -4. 记录失败重试日志 +- `event` + 固定为 `connect` +- `status` + `success` / `cancelled` / `error` +- `relay_id` + 中转商标识 +- `ref_code` + 可选渠道标记,对应 Deep Link 中的 `ref` +- `key_prefix` + 仅保留前 7 位的脱敏 Key 前缀 +- `timestamp` + UTC 时间 +- `client.version` + Lime 当前版本 +- `client.platform` + `macos` / `windows` / `linux` +- `error_code` + 仅 `error` 时返回 +- `error_message` + 仅 `error` 时返回 -## 监控建议 +## 安全边界 -1. 统计成功率与取消率 -2. 跟踪错误类型占比 -3. 区分渠道来源效果 +- Lime 不为该回调增加额外签名 +- 接收方应自行校验 `https://` 来源、参数完整性与幂等 +- 若需要确认请求是否属于自己下发的 Key,可校验 `key_prefix` + +## 重试行为 + +回调发送为异步行为,默认会按以下节奏重试: + +1. 立即发送 +2. 60 秒后重试 +3. 300 秒后重试 +4. 1800 秒后最后一次重试 + +发送失败不会阻塞用户在 Lime 中的主操作。 diff --git a/docs/content/index.md b/docs/content/index.md index aa83f38eb..59ee49ad4 100644 --- a/docs/content/index.md +++ b/docs/content/index.md @@ -1,53 +1,36 @@ --- -title: Lime 文档中心 -description: 创作类 AI Agent 平台文档,从灵感到发布的一站式指南 +title: Lime 文档站 +description: LimeNext V2 对外文档正在重建,当前只保留少量进阶页与法律说明 navigation: false --- -# Lime 文档中心 +# Lime 文档站重建中 -Lime 是创作类 AI Agent 平台。 -你可以在同一个工作台里完成对话、创作、Claw 素材与图片任务、项目沉淀和资源复用。 +`content/` 已进入 LimeNext V2 重建阶段。 +旧版围绕 `AI Agent / 工作台 / 项目 / 资源库 / Claw` 的入门与导航文档已下线,避免继续传播过时的产品结构与命名。 -## 从这里开始 +## 当前口径 -1. [概述](/introduction/overview):先了解平台能帮你完成什么 -2. [安装指南](/introduction/installation):安装到本地桌面 -3. [快速开始](/introduction/quickstart):3 步走完首次创作 +当前对外文档默认采用以下口径: -## 九类工作区主题 +1. Lime 是“本地优先的内容闭环 Agent 系统” +2. 前台主词固定为 `技能 / 灵感库 / 生成` +3. `生成` 是唯一主执行面 +4. 先讲任务闭环与结果推进,再讲连接、协议和扩展能力 -| 主题 | 常见产出 | -|------|----------| -| 通用对话 | 灵感梳理、问题分析、方案草稿 | -| 社媒内容 | 选题、标题、多平台文案 | -| 图文海报 | 主视觉文案、配图方向、活动海报内容 | -| 歌词曲谱 | 主题歌词、段落续写、风格改编 | -| 知识探索 | 知识卡片、结构化总结、学习资料 | -| 计划规划 | 周计划、项目拆解、执行清单 | -| 办公文档 | 报告、方案、邮件、纪要 | -| 短视频 | 脚本、分镜、口播稿 | -| 小说创作 | 设定、章节、人物对白 | +## 当前保留内容 -## 常用功能入口 +当前仅保留仍与实现锚点对齐、且不会直接误导前台叙事的少量页面: -- [首页与工作台](/user-guide/dashboard) -- [资源库](/user-guide/resources) - [运行时 AGENTS 规则](/user-guide/runtime-agents) -- [图片生成与素材链路](/user-guide/image-generation) -- [设置](/user-guide/settings) +- [MCP 工具扩展](/user-guide/mcp) - [插件中心](/user-guide/plugins) +- [Gateway 公共隧道与飞书 Webhook](/user-guide/gateway-tunnel-webhook) +- [模型连接概览](/providers/overview) +- [API 概览](/api-reference/overview) +- [扩展接入概览](/open-platform/overview) +- [免责声明](/legal/disclaimer) -## 进阶能力(可选) +## 后续说明 -当你需要更深度的模型接入或工程能力时,可继续阅读: - -- [Provider 概述](/providers/overview) -- [API 参考](/api-reference/overview) -- [开放平台](/open-platform/overview) -- [故障排查](/troubleshooting/common-issues) - -## 免责声明 - -请在合法合规前提下使用本产品。 -完整说明见 [免责声明](/legal/disclaimer)。 +后续若继续恢复普通创作者向的对外文档,应直接按 LimeNext V2 当前路线重写,不再回收旧版 `content/` 页面。 diff --git a/docs/exec-plans/claude-code-agent-task-runtime-alignment-plan.md b/docs/exec-plans/claude-code-agent-task-runtime-alignment-plan.md index 65d2a089d..3d3187a17 100644 --- a/docs/exec-plans/claude-code-agent-task-runtime-alignment-plan.md +++ b/docs/exec-plans/claude-code-agent-task-runtime-alignment-plan.md @@ -5,7 +5,7 @@ 目标是把 Lime 的 agent 主链从“线程态 + 工具流 + 诊断信号”升级为对标 Claude Code 的“统一任务运行时”: - 主会话、子 agent、等待输入、完成结算都统一映射为可见任务。 -- 简单问题不再错误抬升为常驻 `MAIN TASK` 面板,只在复杂、长链路、可跟踪任务里显示任务视图。 +- 简单问题不再错误抬升为常驻 `MAIN TASK` 面板,只在复杂、长链路、可跟踪任务里显示当前进展。 - 工具调用按批次聚合,必须产出中间过程结论,而不是只留下工具名。 - `token usage` 与 `prompt cache` 在任务完成态和消息态都保持可见。 - E2E 与 GUI smoke 后续统一以“任务是否创建、推进、完成”为核心断言。 diff --git a/docs/exec-plans/limenext-plan.md b/docs/exec-plans/limenext-plan.md index e94b15cfc..f6441017c 100644 --- a/docs/exec-plans/limenext-plan.md +++ b/docs/exec-plans/limenext-plan.md @@ -92,6 +92,8 @@ LimeNext 当前不是缺一篇愿景文档,而是缺一条能持续推进的 - `AgentChatWorkspace` 当前会按 `sessionId -> sceneapp run` 回查最近运行 - 生成页顶部摘要卡已开始展示 `delivery completion / runtime evidence / governance artifact / observed failure signal` - `AppPageContent` 已修正 `sceneapps` keep-alive 树位,`创作场景 -> 持续流程 -> 创作场景` 往返不会再触发目录页重挂载 + - `useAppNavigation` 已升级为 `requested / committed` 双态导航,`AppSidebar + AppPageContent` 统一按请求态渲染,快速切换时以最后一次点击为准,不再出现主区短暂空白或左侧导航瞬时消失 + - `SceneAppsPage` 当前只允许在激活且拥有当前导航请求时回写 `sceneapps` 参数与 recent visit,keep-alive 的旧页不会再把全局导航抢回去 26. `创作场景 -> 持续流程 / 自动化` 的事实源已经开始统一,而不是继续各讲各的: - `AutomationJobDetailsDialog` 当前会识别 `sceneapp` 派生任务的 metadata,并回查同一条 `descriptor / project pack plan / run summary / scorecard` - 自动化详情里已新增 `创作场景闭环` 摘要块,可直接回到 `创作场景` 准备页或治理复盘页 @@ -119,6 +121,15 @@ LimeNext 当前不是缺一篇愿景文档,而是缺一条能持续推进的 - 生成页当前还可在同一会话里直接触发 `补齐缺失部件 / 发布前检查 / 进入发布整理 / 生成渠道预览稿 / 整理上传稿`,继续复用 `@发布合规 / @发布 / @渠道预览 / @上传` 与当前 turn 提交主链,而不新增新的发布协议 - `AgentChatWorkspace` 与 `SceneAppsPage` 当前共享 `resolveSceneAppRunEntryNavigationTarget + prepareSceneAppRunGovernanceArtifact(s)` current 主链,不再各自维护一份 run entry 恢复逻辑 - 这一步把 `生成` 从“结果页旁边的跳转入口”推进成了第一批真正的统一编排面 +32. `生成主执行面` 已开始直接消费当前会话里的发布后产物,而不再只负责发起发布动作: + - `AgentChatWorkspace` 当前会按 `taskFiles / sessionFiles / artifacts` 聚合最近一份 `发布稿 / 渠道预览稿 / 上传稿`,只消费已带 `contentPostIntent / contentPostLabel` metadata 的 current 发布产物,不把普通 `content-posts/*.md` 误判为投放结果 + - `SceneAppExecutionSummaryCard` 已新增 `最近发布产物` 区块,用户可直接从生成页打开刚刚整理出的发布稿、渠道预览稿和上传稿,不需要再去消息流或侧栏翻文件 + - 打开链继续复用现有工作区文件预览主链:优先打开 `task file / artifact`,没有内存态时再回落到 `session file` 读取,不新增新的 viewer 协议 + - 旧结论里若继续写“生成页当前只会触发发布后动作、还不能消费动作结果”,当前都按已过时理解 +33. `生成主执行面` 已开始补第一层发布态判断,而不再只把 `发布稿 / 渠道预览稿 / 上传稿` 平铺出来: + - `sceneAppExecutionContentPosts` 当前会继续检查同名 `*.cover.json / *.publish-pack.json` 伴随文件,并推导 `可继续发布 / 优先渠道预览 / 优先上传整理 / 待补封面信息、发布包` 这类轻量就绪态 + - `SceneAppExecutionSummaryCard` 的 `最近发布产物` 卡片当前会直接显示就绪标签与伴随材料芯片,用户在生成页就能看出这轮结果更适合继续发布、先看预览还是先补投放材料 + - 这一步仍然只复用现有 `content-posts` 文件命名约定与 session/task/artifact 三路事实源,不新增新的发布状态协议 尚未完成: @@ -132,7 +143,7 @@ LimeNext 当前不是缺一篇愿景文档,而是缺一条能持续推进的 8. 让基础设置包的 schema 继续下沉到 bootstrap / seeded catalog 可消费的目录投影。 9. 把 `composition blueprint` 从文档口径继续收口到可校验、可投影的装配对象。 10. 继续把 `project pack` 的结构化读模型从当前已接通的 `session / evidence + deliveryArtifactRefs` 优先聚合,扩展到更完整的 `artifact validator / request telemetry / evidence summary` 主链。 -11. 把 `project pack` 的治理闭环从当前已接通的“生成主执行面 + 场景目录 + 生成准备 + 治理复盘深链 + 经营评分 + 页面级治理看板 + 自动化详情 + 周会复盘包 / 结构化治理包 + 同聊补件 / 发布前检查 / 进入发布整理 / 渠道预览稿 / 上传稿”继续扩展到更完整的正式投放动作与更强的 evidence/review 闭环。 +11. 把 `project pack` 的治理闭环从当前已接通的“生成主执行面 + 场景目录 + 生成准备 + 治理复盘深链 + 经营评分 + 页面级治理看板 + 自动化详情 + 周会复盘包 / 结构化治理包 + 同聊补件 / 发布前检查 / 进入发布整理 / 渠道预览稿 / 上传稿 + 最近发布产物直接消费 + 发布态轻量判断”继续扩展到更完整的正式投放动作与更强的 evidence/review 闭环。 12. 把装配包从已接通的 `service_skill_catalog + scene_catalog` 继续扩到 `command_catalog` 投影代码。 13. 决定第一版是“客户端内编译 package”还是“服务端下发预编译 projection,客户端只做 gate + fallback”。 14. 把剩余 seeded 来源继续收口,重点转到 `command` 与 automation 相关入口,不再保留新的手写 `local_custom` 补丁。 @@ -171,8 +182,9 @@ LimeNext 的实施总目标固定为: 依赖: -- `docs/roadmap/ribbi/*` -- `docs/roadmap/lime-product-convergence-plan.md` +- `docs/research/ribbi/*` +- `docs/roadmap/limenextv2/product-principles.md` +- `docs/roadmap/limenextv2/implementation-roadmap.md` - `docs/roadmap/lime-service-skill-cloud-config-prd.md` 退出条件: diff --git a/docs/exec-plans/limenext-progress.md b/docs/exec-plans/limenext-progress.md index 84e51a809..4b66df448 100644 --- a/docs/exec-plans/limenext-progress.md +++ b/docs/exec-plans/limenext-progress.md @@ -1,13 +1,1013 @@ # LimeNext 推进日志 -> 注:自 2026-04-17 起,LimeNext current 前台主词固定为 `创作场景 / 灵感库 / 生成 / Project Pack / 复盘`。历史日志里若继续出现 `SceneApp / 场景应用 / 记忆工作台` 等词,默认按当时实现阶段或 compat 旧称理解,不再代表 current 产品口径。 +> 注:自 2026-04-19 起,LimeNext current 前台主词固定为 `技能 / 灵感库 / 生成`。历史日志里若继续出现 `SceneApp / 创作场景 / Project Pack / 复盘 / 记忆工作台 / 任务工作台 / 任务视图` 等词,默认按当时实现阶段或 compat 旧称理解,不再代表 current 产品口径。 > > 补充说明:2026-04-17 中段几次关于“纯标题目录 / 无图场景墙”的尝试,当前都已被后续 `经营信号目录卡片` 方案取代。阅读本日志时,凡旧条目仍写“纯标题目录”,都按已废弃试探理解;current 以最新“目录卡片经营信号回流”条目为准。 +> +> 补充说明(2026-04-18):旧 Ribbi 过渡目录已清理。历史条目若继续出现旧 Ribbi 路径,默认按“当时旧路径、现已由 `docs/research/ribbi/*` 替代”理解。 + +## 2026-04-19 + +### 已完成 + +- 把 `P2:Skill-First 前台` 当前被环境级验证阻塞的 `verify:gui-smoke` 恢复到“能自我避开损坏 cargo target”的状态,避免 GUI 交付链继续被旧 sqlite 半成品缓存卡死: + - 已更新: + - `scripts/verify-gui-smoke.mjs` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - `verify:gui-smoke` 当前新增 sqlite 构建产物自检;若目标 `cargo target` 下存在 `debug/build/libsqlite3-sys-*/out` 但缺少 `bindgen.rs`,脚本不再复用该目录,也不做破坏性删除,而是自动切到同级新的 `*-rebuild--` target + - 默认超时当前也会基于“最终实际使用的 cargo target”重新计算;未显式传 `--timeout-ms` 时,切到 fresh target 后会自动回到冷启动超时,不再沿用旧 warm target 的较短等待 + - 这一步属于 `P2` 的交付支撑修复,不是继续扩前台功能,而是把 current 主线从“代码已收口但 GUI smoke 受旧缓存污染”拉回“脚本可自我避险” + - 当前已确认通过: + - `node --check "scripts/verify-gui-smoke.mjs"` + - `npx eslint "scripts/verify-gui-smoke.mjs"` + - `node scripts/verify-gui-smoke.mjs --app-url "http://127.0.0.1:1421/" --timeout-ms 600000 --cargo-target-dir "/var/folders/87/s6cpr7hd1_v43cs833x4s_900000gn/T/lime-gui-smoke-target"` 已实际打印: + - 发现损坏 sqlite 构建缓存 + - 自动切换到新的 `lime-gui-smoke-target-rebuild-*` 目录 + - 开始用 fresh target 拉起 headless Tauri 编译链 + - 当前剩余阻塞说明: + - 在当前机器上,fresh headless 链继续向前时,`beforeDevCommand` 虽然已按 `http://127.0.0.1:1421/` 等待新前端,但 Vite 实际仍报告 `Port 1420 is already in use`,说明本机已有 dev server / Vite 端口复用链还在影响隔离 smoke + - 另一路复用现有 `1420 + 3030` 环境执行 `npm run verify:gui-smoke -- --timeout-ms 1200000` 时,链路已能稳定走到 `smoke:agent-runtime-tool-surface-page`,但最后仍卡在 `Runtime 能力摘要出现`,最后结果为 `hasWorkbench=true` 且其余摘要标记均为 `false` + - 因此这次已确认“损坏 sqlite target”不再是当前唯一阻塞;剩余问题已收敛为两个独立问题: + - 新链路隔离启动仍受本机现有 Vite/前端端口占用影响 + - 复用现有 dev 环境时,`agent-runtime-tool-surface-page` 仍未看到 runtime 摘要,需要单独检查 `toolInventory / harness panel` 页面态是否与 current 环境一致 + +- 把 `P2:Skill-First 前台` 里最后几条还没进入合同层的 current 前台入口继续收口,避免首页 continuation、技能页最近做法、我的方法库和输入层 installed skill 继续各说各的: + - 已更新: + - `src/components/skills/installedSkillPresentation.ts` + - `src/components/skills/installedSkillPresentation.test.ts` + - `src/components/agent/chat/components/EmptyState.tsx` + - `src/components/agent/chat/components/EmptyState.test.tsx` + - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` + - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` + - `src/components/skills/SkillsWorkspacePage.tsx` + - `src/components/skills/SkillsWorkspacePage.test.tsx` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - `docs/roadmap/limenextv2/skill-first-system.md` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - `installed skill` 当前新增共享的轻量 projection helper,优先复用 `metadata.lime_when_to_use / lime_argument_hint`,兜底到 `description + 对话里继续补充目标与约束 + 带着该方法进入生成主执行面` + - 首页 `继续上次做法` 当前不再只留标题;结果模板与 service skill 都会直接显示 `需要 / 交付` 缩略事实 + - 技能页 `继续常用做法` 当前补齐 `你来给 / 会拿到 / 结果去向`,`我的方法库` 也不再只是 `名字 + 描述 + /key` + - `@ / /` 输入层里的 installed skill 当前也回到同一套轻量 skill 合同,不再保留一条纯 description 链 + - 这一步继续服务 `P2` 的主目标:让首页、技能页和输入层共享的不只是 capability id,而是统一的 current 前台 skill 解释层 + - 当前已确认通过: + - `npm exec vitest run "src/components/skills/installedSkillPresentation.test.ts" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` + - `npx eslint "src/components/skills/installedSkillPresentation.ts" "src/components/skills/installedSkillPresentation.test.ts" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` + - `npm run verify:local` + - 当前阻塞说明: + - `verify:local` 的前端、Vitest 与 `cargo test --manifest-path src-tauri/Cargo.toml` 均已实际通过 + - 但末尾 `verify:gui-smoke` 在独立临时 target 编译阶段失败,错误为 `libsqlite3-sys` 读取临时 `OUT_DIR` 下的 `bindgen.rs` 失败,导致 headless Tauri 在 DevBridge 就绪前退出 + - 因此本轮当前已达到“代码、类型、定向回归、Rust 单测通过”的门槛,但 GUI smoke 仍受环境级编译问题阻塞,需单独处理该 smoke target 的 sqlite/bindgen 构建稳定性 + +- 把 `P2:Skill-First 前台` 的 `service skill` 前台合同投影接回与 `curated_task` 同一套 current 事实源,避免首页、输入层、技能页继续各讲各的: + - 已更新: + - `src/components/agent/chat/service-skills/skillPresentation.ts` + - `src/components/agent/chat/service-skills/skillPresentation.test.ts` + - `src/components/agent/chat/components/EmptyState.tsx` + - `src/components/agent/chat/components/EmptyState.test.tsx` + - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` + - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` + - `src/components/skills/SkillsWorkspacePage.tsx` + - `src/components/skills/SkillsWorkspacePage.test.tsx` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - `docs/roadmap/limenextv2/skill-first-system.md` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - `service skill` 当前新增共享的 capability description helper,统一输出 `promise + 需要 + 交付` + - 首页 `快捷做法` 的缩略 meta、`@` 面板里的 service skill 描述、技能页组内做法卡片,当前都改成围绕同一套合同事实表达 + - 技能页组内卡片当前不再写 `入口`,而是显式展示 `你来给 / 会拿到 / 结果去向`,开始和 `curated_task` 的 skill 合同体验靠拢 + - 这一步继续服务 `P2` 第 2 条目标:让技能页、新建任务页和输入层共享的不只是 skill id,而是统一的 current 前台 skill 解释层 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/service-skills/skillPresentation.test.ts" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` + - `npx eslint "src/components/agent/chat/service-skills/skillPresentation.ts" "src/components/agent/chat/service-skills/skillPresentation.test.ts" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` + - `npm run verify:local` + - 本次 `verify:local` 已实际覆盖 `verify:gui-smoke`,并跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` + +- 把 `P2:Skill-First 前台` 里的 `curated_task` 启动事实与 skill 合同缩略投影继续收口到同一条 current 主链,避免首页、技能页、输入层只是“都能打开”,但仍各讲各的 skill: + - 已更新: + - `src/components/agent/chat/utils/curatedTaskTemplates.ts` + - `src/components/agent/chat/components/EmptyState.tsx` + - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` + - `src/components/skills/SkillsWorkspacePage.tsx` + - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` + - `src/components/skills/SkillsWorkspacePage.test.tsx` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - `docs/roadmap/limenextv2/skill-first-system.md` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - 首页 `结果入口` 的缩略 meta 与 slash 面板里的结果模板描述,当前都改成共享 `buildCuratedTaskCapabilityDescription`;输入层里的结果模板不再只有一句 summary,而会同步暴露 `需要 / 交付` 的 current 缩略事实 + - 技能页桥接 `curated_task` 进入 `生成` 时,当前也会把 `referenceEntries` 一并带进 `initialInputCapability.capabilityRoute`,不再只有 `referenceMemoryIds` + - 到这里为止,首页、slash、技能页三条结果模板入口共享的不只是 `taskId + prompt`,还包括可回放的引用对象事实;首屏恢复与二次编辑 launcher 时,不会再出现某条链只剩 id 的分叉 + - 这一步继续服务 `P2` 第 2 条目标:让技能页、新建任务页和输入层共享同一 skill 事实源,而不是只共享模板目录 + - 当前已确认通过: + - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` + - `npx eslint "src/components/agent/chat/utils/curatedTaskTemplates.ts" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` + - `npm run verify:local` + - `npm run verify:gui-smoke` 已包含在本次 `verify:local` 中,并实际跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` + - 这意味着之前日志里提到的 `site_capability_service` Rust 既有失败,当前已不再是本轮主线的有效阻塞状态 + +- 把 `生成` 后的 Team / Canvas / Inputbar 首层提示继续收口到和 GeneralWorkbench 一致的 current 主执行面,避免刚把工作台改成结果对象视角,team runtime 首层又长回第二套任务命名: + - 已更新: + - `src/components/agent/chat/utils/teamWorkspaceCopy.ts` + - `src/components/agent/chat/components/TeamWorkbenchSummaryPanel.tsx` + - `src/components/agent/chat/components/TeamWorkspaceDock.tsx` + - `src/components/agent/chat/components/ChatSidebar.tsx` + - `src/components/agent/chat/workspace/useWorkspaceCanvasSceneRuntime.tsx` + - `src/components/agent/chat/components/Inputbar/components/InputbarWorkflowStatusPanel.tsx` + - `src/components/agent/chat/components/CanvasWorkbenchLayout.tsx` + - `src/components/agent/chat/components/team-workspace-board/TeamWorkspaceEmptyShellState.tsx` + - `src/components/agent/chat/components/team-workspace-board/TeamWorkspaceCanvasToolbar.tsx` + - `src/components/agent/chat/components/team-workspace-board/TeamWorkspaceCanvasStage.tsx` + - `src/components/agent/chat/components/team-workspace-board/teamWorkspaceBoardPresentationSelectors.ts` + - `src/components/agent/chat/team-workspace-runtime/formationDisplaySelectors.ts` + - `src/components/agent/chat/utils/teamWorkspaceCanvas.ts` + - `src/components/agent/chat/utils/contextualRecommendations.ts` + - `src/components/agent/chat/utils/contextualRecommendations.test.ts` + - `src/components/agent/chat/utils/agentTaskRuntime.test.ts` + - `docs/exec-plans/claude-code-agent-task-runtime-alignment-plan.md` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - Team Summary / Team Dock / Canvas team tab / workflow status 当前统一使用 `生成工作台 / 当前进展`,空态按钮与进入提示也不再把 team runtime 包装成另一套平级“任务视图” + - `可继续稿件 / 可继续版本 / 产出记录 / 执行经过` 这套结果对象语言,当前已经从首页、GeneralWorkbench 继续接到了 Team / Canvas / Inputbar 首层提示 + - 在用户已明确“不做兼容”的前提下,`contextualRecommendations` 当前也已删掉把 `任务工作台` 当成 team runtime 触发词的历史容忍,只保留 current 文案与真实 team 语义 + - 这一步继续服务 `P1:前台口径收口`,让 `生成` 后首层路径不再同时存在两套执行命名;current 事实源现在收敛为 `生成 -> 生成工作台 -> 当前进展` + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/components/TeamWorkspaceDock.test.tsx" "src/components/agent/chat/components/TeamWorkspaceBoard.test.tsx" "src/components/agent/chat/components/TeamWorkbenchSummaryPanel.test.tsx" "src/components/agent/chat/components/CanvasWorkbenchLayout.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/workspace/useWorkspaceCanvasSceneRuntime.test.ts" "src/components/agent/chat/components/team-workspace-board/TeamWorkspaceCanvasSurfaceCopy.test.tsx" "src/components/agent/chat/components/team-workspace-board/TeamWorkspaceTeamOverviewChrome.test.tsx" "src/components/agent/chat/components/team-workspace-board/teamWorkspaceBoardPresentationSelectors.test.ts" "src/components/agent/chat/components/team-workspace-board/useTeamWorkspaceBoardShellProps.test.tsx" "src/components/agent/chat/components/team-workspace-board/teamWorkspaceBoardPropBuilders.test.ts" "src/components/agent/chat/components/team-workspace-board/useTeamWorkspaceBoardCanvasRuntime.test.tsx" "src/components/agent/chat/team-workspace-runtime/formationDisplaySelectors.test.ts" "src/components/agent/chat/utils/contextualRecommendations.test.ts" "src/components/agent/chat/utils/agentTaskRuntime.test.ts"` + - `npm run verify:local` + +- 把仓库其余仍会直接暴露给用户的旧 `任务工作台 / 任务视图` 文案继续收尾一刀,避免主链已换成 current 口径,旁路设置页还把用户拉回旧语境: + - 已更新: + - `src/components/settings-v2/system/automation/index.tsx` + - `src/components/settings-v2/system/automation/index.test.tsx` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - 自动化设置页当前不再暴露 `打开任务工作台`,而是统一改成 `打开自动化工作台` + - workspace-only 描述当前也不再写 `默认进入任务视图`,而是改成 `默认进入当前进展` + - 这一步属于 P1 的旁路收尾:不是继续扩主链,而是防止 current 主词在其他真实前台页面被旧词反向污染 + - 当前已确认通过: + - `npm exec vitest run "src/components/settings-v2/system/automation/index.test.tsx"` + - `npx eslint "src/components/settings-v2/system/automation/index.tsx" "src/components/settings-v2/system/automation/index.test.tsx"` + +- 把 team runtime 里仍像“第二套任务面板系统”的 copy 继续收口到 `当前进展` 语义,避免 `生成工作台` 下面又长出另一套旧前台命名: + - 已更新: + - `src/components/agent/chat/team-workspace-runtime/formationDisplaySelectors.ts` + - `src/components/agent/chat/team-workspace-runtime/formationDisplaySelectors.test.ts` + - `src/components/agent/chat/team-workspace-runtime/boardChromeSelectors.ts` + - `src/components/agent/chat/team-workspace-runtime/boardChromeSelectors.test.ts` + - `src/components/agent/chat/components/team-workspace-board/TeamWorkspaceCanvasToolbar.tsx` + - `src/components/agent/chat/components/team-workspace-board/TeamWorkspaceEmptyShellState.tsx` + - `src/components/agent/chat/components/team-workspace-board/SelectedSessionInlineHeader.tsx` + - `src/components/agent/chat/components/team-workspace-board/teamWorkspaceBoardPresentationSelectors.ts` + - `src/components/agent/chat/components/team-workspace-board/TeamWorkspaceTeamOverviewControls.tsx` + - `src/components/agent/chat/components/team-workspace-board/TeamWorkspaceCanvasSurfaceCopy.test.tsx` + - `src/components/agent/chat/components/team-workspace-board/TeamWorkspaceTeamOverviewChrome.test.tsx` + - `src/components/agent/chat/components/team-workspace-board/teamWorkspaceBoardPresentationSelectors.test.ts` + - `src/components/agent/chat/components/TeamWorkspaceBoard.test.tsx` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - Team runtime 默认空态与画布提示当前不再写 `任务面板 / 任务摘要视图`,而是统一改成 `当前进展面板 / 进展摘要视图` + - canvas toolbar 与紧凑控制条当前不再写 `聚焦任务`,而是统一改成 `聚焦进展` + - lane 数、overview subtitle 与 selected session CTA 当前也不再写 `X 项任务已接入 / 打开任务 / 切换任务`,而是统一改成 `X 条当前进展已接入 / 打开进展 / 切换进展` + - 这一步继续服务 P1:不是否认 team runtime 里真实存在的任务拆分,而是把用户一眼看到的执行对象继续固定回 `当前进展` + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/team-workspace-runtime/formationDisplaySelectors.test.ts" "src/components/agent/chat/team-workspace-runtime/boardChromeSelectors.test.ts" "src/components/agent/chat/components/team-workspace-board/TeamWorkspaceCanvasSurfaceCopy.test.tsx" "src/components/agent/chat/components/team-workspace-board/TeamWorkspaceTeamOverviewChrome.test.tsx" "src/components/agent/chat/components/team-workspace-board/teamWorkspaceBoardPresentationSelectors.test.ts" "src/components/agent/chat/components/team-workspace-board/useTeamWorkspaceBoardCanvasRuntime.test.tsx" "src/components/agent/chat/components/TeamWorkspaceBoard.test.tsx"` + - `npx eslint "src/components/agent/chat/team-workspace-runtime/formationDisplaySelectors.ts" "src/components/agent/chat/team-workspace-runtime/boardChromeSelectors.ts" "src/components/agent/chat/components/team-workspace-board/TeamWorkspaceCanvasToolbar.tsx" "src/components/agent/chat/components/team-workspace-board/TeamWorkspaceEmptyShellState.tsx" "src/components/agent/chat/components/team-workspace-board/SelectedSessionInlineHeader.tsx" "src/components/agent/chat/components/team-workspace-board/teamWorkspaceBoardPresentationSelectors.ts" "src/components/agent/chat/components/team-workspace-board/TeamWorkspaceTeamOverviewControls.tsx" "src/components/agent/chat/team-workspace-runtime/formationDisplaySelectors.test.ts" "src/components/agent/chat/team-workspace-runtime/boardChromeSelectors.test.ts" "src/components/agent/chat/components/team-workspace-board/TeamWorkspaceCanvasSurfaceCopy.test.tsx" "src/components/agent/chat/components/team-workspace-board/TeamWorkspaceTeamOverviewChrome.test.tsx" "src/components/agent/chat/components/team-workspace-board/teamWorkspaceBoardPresentationSelectors.test.ts" "src/components/agent/chat/components/TeamWorkspaceBoard.test.tsx"` + +- 把 `生成现场` 与 topic switch 的边缘提示继续去任务化,避免主流程已经换词,继续入口和错误提示还在回退旧任务系统语境: + - 已更新: + - `src/components/agent/chat/components/ChatSidebar.tsx` + - `src/components/agent/chat/components/ChatSidebar.test.tsx` + - `src/components/agent/chat/workspace/useWorkspaceTopicSwitch.ts` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - task-center continuation 的 fallback 动作当前不再写 `打开任务`,而是改成和 `生成现场` 对齐的 `打开现场` + - topic switch 失败 toast 当前也不再写 `切换任务失败 / 加载任务失败`,而是统一改成 `切换会话失败 / 加载会话失败` + - 这一步继续服务 P1 的边缘收口:哪怕只是在失败或 fallback 场景里,也尽量避免把默认 `生成` 链重新讲成任务系统 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/team-workspace-runtime/boardChromeSelectors.test.ts" "src/components/agent/chat/components/ChatSidebar.test.tsx"` + - `npx eslint "src/components/agent/chat/team-workspace-runtime/boardChromeSelectors.ts" "src/components/agent/chat/team-workspace-runtime/boardChromeSelectors.test.ts" "src/components/agent/chat/components/ChatSidebar.tsx" "src/components/agent/chat/components/ChatSidebar.test.tsx" "src/components/agent/chat/workspace/useWorkspaceTopicSwitch.ts"` + +- 把 `生成` 后工作台里偏工程的对象名继续收口成结果对象视角,避免首页已经在讲“结果去向 / 继续上次做法”,一进入工作台又退回 `任务 / 分支 / 过程记录` 语境: + - 已更新: + - `src/components/agent/chat/components/GeneralWorkbenchSidebarShell.tsx` + - `src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx` + - `src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - `任务工作台` 当前已改成 `生成工作台`,`任务视图` 当前已改成 `当前进展`,把 `生成` 固定为用户理解里的主执行面 + - `相关分支 / 相关版本` 当前已收成 `可继续稿件 / 可继续版本`,让用户优先理解“从哪一稿继续”,而不是先理解工程分支对象 + - `任务记录 / 过程记录` 当前已收成 `产出记录 / 执行经过`,并继续与首页 `结果去向` 的说明保持同一套结果对象语言 + - 这一步继续服务 `P1:首页默认复杂度收口`,但重点已经从首页进一步推进到 `生成` 后第一屏,让用户在执行面里也默认看到“结果 / 下一步 / 继续入口”,而不是后台对象名 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx"` + - `npx eslint "src/components/agent/chat/components/GeneralWorkbenchSidebarShell.tsx" "src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx" "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx"` + - `npm run verify:local` + - `npm run verify:gui-smoke` 已包含在本次 `verify:local` 中,并实际跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` + +- 把 `生成` 后的进展摘要卡补成“结果去向 / 从哪里继续”的轻接线,避免首页提示一消失,用户又不知道结果会去哪: + - 已更新: + - `src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx` + - `src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - 顶部摘要卡当前会继续提示:主稿、任务文件和运行产物会沉淀到下方 `产出记录 / 执行经过` + - 需要继续修改时,用户当前也能直接从 `可继续稿件/版本` 或首页 `继续上次做法` 这两个入口理解“从哪里接着跑” + - 这一步继续服务 `P1:首页默认复杂度收口`,但落点已经从首页延伸到 `生成` 后的结果/工作台首屏,让“结果不会丢、下次从哪里继续”不再只停留在首页一句提示里 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx"` + - `npx eslint "src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx" "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx"` + - `npm run verify:local` + - `npm run verify:gui-smoke` 已包含在本次 `verify:local` 中,并实际跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` + +- 把 `新建任务` 首页剩余非核心块继续收成“有真实收益才露出”的 current 显隐规则: + - 已更新: + - `src/components/agent/chat/components/EmptyState.tsx` + - `src/components/agent/chat/components/EmptyStateSceneAppsPanel.tsx` + - `src/components/agent/chat/components/EmptyState.test.tsx` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - `更多起手方式` 当前不再因为“还有目录页可进”就默认露出;只有当前真有可直接启动的整套做法,或用户确实可以“继续最近做法”时,这块才出现 + - `支撑能力` 当前也不再因为“系统里有技能”就默认露出;只有浏览器接入、站点自动接入型做法,或最近沉淀出的复用方法形成直接收益时,才继续显示摘要层 + - 这一步继续服务 `P1:首页默认复杂度收口`,目标是避免首页在推荐层收完之后,又被“目录入口 / 能力目录”重新长回平台分层感 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx"` + - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyStateSceneAppsPanel.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` + - `npm run verify:local` + - `npm run verify:gui-smoke` 已包含在本次 `verify:local` 中,并实际跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` + +- 把 `新建任务` 首页 `结果模板` 从同权 6 条入口继续收成“首选结果 + 更多结果 + 快捷做法”的强弱分层: + - 已更新: + - `src/components/agent/chat/components/EmptyState.tsx` + - `src/components/agent/chat/components/EmptyState.test.tsx` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - `结果模板` 当前不再把 4 条 curated task 与 2 条 service skill 以同一层级平铺给用户,而是改成: + - `首选结果`:默认先看最常用、最泛用的 2 条结果入口 + - `更多结果`:保留其余结果模板,作为第二层补充选择 + - `快捷做法`:把现成 service skill 收成捷径层,不再与结果模板混成同一层 + - 这一步继续服务 P1 的首页默认复杂度收口,只做首页结果 shelf 的层级优化,不改运行时协议、不改 skill / launcher 主链 + - 首页当前更接近“先给用户一个最该点的结果入口”,而不是“把所有能点的入口平铺出来” + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx"` + - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` + - `npm run verify:local` + - `npm run verify:gui-smoke` 已包含在本次 `verify:local` 中,并实际跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` + +- 把 `新建任务` 首页 `结果入口` 继续补成“知道怎么开始,也知道结果会去哪”的轻闭环提示: + - 已更新: + - `src/components/agent/chat/components/EmptyState.tsx` + - `src/components/agent/chat/components/EmptyStateSceneAppsPanel.tsx` + - `src/components/agent/chat/components/EmptyState.test.tsx` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - `结果入口` 当前已新增轻量 `结果去向` 提示,明确本轮产出会沉淀到当前任务/项目,跑通过的方法会回到 `继续上次做法`,参考与反馈会继续影响下一轮推荐 + - 这一步继续服务 P1 的首页默认复杂度收口:不是再开一个结果面,而是在首页先把“结果不会丢、下次从哪继续”说清楚 + - `更多起手方式` 当前也把说明文案再压短一层,继续保持补位入口,不重新长成解释性大块 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx"` + - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyStateSceneAppsPanel.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` + - `npm run verify:local` + - `npm run verify:gui-smoke` 已包含在本次 `verify:local` 中,并实际跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` + +- 把 `新建任务` 首页原来平级的 `结果模板` + `继续上次做法` 收成同一个 `结果入口` shelf,继续减少首页块级切换感: + - 已更新: + - `src/components/agent/chat/components/EmptyState.tsx` + - `src/components/agent/chat/components/EmptyState.test.tsx` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - 首页 supporting 区当前不再把 `结果模板` 和 `继续上次做法` 渲染成两个平级面板,而是先收成一个总标题为 `结果入口` 的 unified shelf + - `结果入口` 内部当前分成两个 section:上半段负责“先拿什么结果”,下半段负责“最近跑过什么做法”;空态时也在同一个容器里提示,不再额外长出独立空块 + - `更多起手方式` 与 `支撑能力` 当前都退到 `结果入口` 后面,首页默认视觉重心继续稳定在 `目标输入 + 当前项目 + 结果入口` + - 这一步仍属于 P1 的首页默认复杂度收口,只改前台组合层,不改协议、不改后端、不改 `curated_task capability route` + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx"` + - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` + - `npm run verify:local` + - `npm run verify:gui-smoke` 已包含在本次 `verify:local` 中,并实际跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` + +- 把 `新建任务` 首页底部的能力目录感继续收口一刀,改成“默认结果入口 + 按需展开支撑能力”的 current 前台结构: + - 已更新: + - `src/components/agent/chat/components/EmptyState.tsx` + - `src/components/agent/chat/components/EmptyStateHero.tsx` + - `src/components/agent/chat/components/EmptyStateSceneAppsPanel.tsx` + - `src/components/agent/chat/components/EmptyState.test.tsx` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - 首页底部 `我的方法 / 持续流程 / 任务拆分 / 浏览器接入` 4 张大卡当前不再默认常显,而是收成一个轻量 `支撑能力` 摘要层;用户需要时再手动展开 + - `支撑能力` 摘要层当前会保留 `methodSummaryLabel`,并继续提供轻量 `连接浏览器` 快捷入口,避免把能力完全藏死 + - `EmptyStateHero` 当前只会在确实有卡片需要显示时才渲染底部卡片区,不再为空壳占位 + - 原 `创作场景` 区当前进一步降成 `更多起手方式`,明确它只是补位入口;如果用户已经知道想拿什么结果,优先走上方结果模板 + - 这一步仍属于 P1 的首页默认复杂度收口,不改协议、不改后端,只继续压低首页“能力超市 / 平台目录”观感 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx"` + - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyStateHero.tsx" "src/components/agent/chat/components/EmptyStateSceneAppsPanel.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` + - `npm run verify:local` + - `npm run verify:gui-smoke` 已包含在本次 `verify:local` 中,并实际跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` + +- 把 `新建任务` 首页默认复杂度继续收口一刀,减少折叠态运行时噪音,稳住 `目标输入 + 项目 + 结果模板` 主入口: + - 已更新: + - `src/components/agent/chat/components/EmptyStateComposerPanel.tsx` + - `src/components/agent/chat/components/EmptyState.tsx` + - `src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx` + - `src/components/agent/chat/components/EmptyState.test.tsx` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - 首页输入区折叠态当前不再暴露 `当前模型` 轻提示,也不再在未展开时直接露出模型选择器;`Provider / Model / 权限模式 / Team` 继续统一收在 `高级设置` + - 首页 hero 徽标当前不再默认暴露 `执行模式 / 联网搜索` 等运行时状态,减少“系统控制台”观感 + - supporting 区当前改成 `结果模板 -> 继续上次做法 -> 创作场景补位` 的顺序,先让默认视觉重心回到结果入口 + - 这一步属于 P1 的首页默认复杂度收口,不改协议、不改后端,只继续压缩前台默认暴露 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` + - `npm run verify:local` + - `npm run verify:gui-smoke` 已包含在本次 `verify:local` 中,并实际跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` + +- 把 `curated task` featured 推荐从“固定 4 张卡”推进成“静态 base + 当前参考/最近保存信号”的 P3 第二刀,打通 `当前参考 / 保存灵感 -> 下一轮推荐` 回流: + - 已更新: + - `src/components/agent/chat/utils/curatedTaskRecommendationSignals.ts` + - `src/components/agent/chat/utils/curatedTaskRecommendationSignals.test.ts` + - `src/components/agent/chat/utils/curatedTaskTemplates.ts` + - `src/components/agent/chat/components/EmptyState.tsx` + - `src/components/agent/chat/components/EmptyState.test.tsx` + - `src/components/skills/SkillsWorkspacePage.tsx` + - `src/components/skills/SkillsWorkspacePage.test.tsx` + - `src/components/agent/chat/AgentChatWorkspace.tsx` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - `docs/roadmap/limenextv2/skill-first-system.md` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - 首页空态与技能页 `先拿结果` 当前都会围绕 `projectId + 当前 referenceEntries + 最近保存灵感` 重新计算 featured 推荐 + - 推荐信号当前分成两类:`active_reference` 负责表达当前线程/launcher 已带入的参考对象;`saved_inspiration` 负责表达最近保存到灵感库的条目 + - `保存到灵感库` 成功后,当前会立刻记录推荐信号并广播刷新事件;featured 推荐不再依赖 memory 的旧 `updated_at` + - 推荐排序继续保留默认 4 张结果模板的 base 骨架,但强信号可以把 `account-project-review` 等非默认模板抬进前排,并给出“围绕当前参考 / 围绕最近收藏或偏好”等理由提示 + - 到这里为止,P3 已从“灵感带入生成”继续推进到“生成内保存与当前带入,都会影响下一轮结果模板建议” + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/utils/curatedTaskRecommendationSignals.test.ts" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` + - `npx eslint "src/components/agent/chat/utils/curatedTaskRecommendationSignals.ts" "src/components/agent/chat/utils/curatedTaskRecommendationSignals.test.ts" "src/components/agent/chat/utils/curatedTaskTemplates.ts" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx"` + - `npm run typecheck` + - `npm run verify:local` + +- 把 `creation_replay` 从“后台预填对象”推进成 `生成主执行面` 里的 current 前台对象,并打通 `灵感库 -> 生成 -> 结果模板默认引用回流` 这条 P3 第一刀: + - 已更新: + - `src/components/agent/chat/utils/curatedTaskReferenceSelection.ts` + - `src/components/agent/chat/utils/creationReplaySurface.ts` + - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` + - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` + - `src/components/agent/chat/skill-selection/CharacterMention.tsx` + - `src/components/agent/chat/components/Inputbar/components/InputbarComposerSection.tsx` + - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` + - `src/components/agent/chat/components/Inputbar/index.tsx` + - `src/components/agent/chat/workspace/useWorkspaceInputbarSceneRuntime.tsx` + - `src/components/agent/chat/components/EmptyStateComposerPanel.tsx` + - `src/components/agent/chat/components/EmptyState.tsx` + - `src/components/agent/chat/workspace/chatSurfaceProps.ts` + - `src/components/agent/chat/workspace/WorkspaceConversationScene.tsx` + - `src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.tsx` + - `src/components/agent/chat/AgentChatWorkspace.tsx` + - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` + - `src/components/agent/chat/components/EmptyState.test.tsx` + - `src/components/agent/chat/components/Inputbar/index.test.tsx` + - `src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx` + - `src/components/agent/chat/workspace/WorkspaceConversationScene.test.tsx` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - `docs/roadmap/limenextv2/skill-first-system.md` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - `creation_replay` 当前不再只在 scene gate / service skill 里被内部消费;`生成主执行面` 已开始把它显影成“当前带入灵感 / 技能草稿”对象 + - 首页空态输入区当前也会露出同一条轻量提示,避免用户只在 entry banner 里看一次就丢 + - 从灵感库进入 `生成` 时带入的 `memory_entry creation_replay`,当前会自动成为结果模板 launcher 的默认 reference seed + - 这条默认 seed 既会作用于首页结果模板,也会作用于 slash 面板里的结果模板 + - launcher 当前会合并保留 seed entry 与最近灵感列表;即使该条灵感不在最近列表中,也不会被静默丢掉 + - `curated_task capabilityRoute` 当前也已开始保留 `referenceEntries`,保证页面 bootstrap / 首屏恢复 / 再次编辑 launcher 时不只剩 id + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx" "src/components/agent/chat/workspace/WorkspaceConversationScene.test.tsx"` + - `npx eslint "src/components/agent/chat/utils/curatedTaskReferenceSelection.ts" "src/components/agent/chat/utils/creationReplaySurface.ts" "src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/components/Inputbar/components/InputbarComposerSection.tsx" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/index.tsx" "src/components/agent/chat/workspace/useWorkspaceInputbarSceneRuntime.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.tsx" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/workspace/chatSurfaceProps.ts" "src/components/agent/chat/workspace/WorkspaceConversationScene.tsx" "src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx" "src/components/agent/chat/workspace/WorkspaceConversationScene.test.tsx"` + +- 把 `curated task` 的“可选灵感引用”从静态文案补成 current typed contract,打通 `launcher -> route -> request metadata -> 生成` 最小闭环: + - 已更新: + - `src/components/agent/chat/utils/curatedTaskReferenceSelection.ts` + - `src/components/agent/chat/utils/curatedTaskReferenceSelection.test.ts` + - `src/components/agent/chat/utils/curatedTaskTemplates.ts` + - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` + - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` + - `src/components/agent/chat/components/EmptyState.tsx` + - `src/components/agent/chat/skill-selection/CharacterMention.tsx` + - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` + - `src/components/agent/chat/components/Inputbar/hooks/useInputbarSend.ts` + - `src/components/skills/SkillsWorkspacePage.tsx` + - `src/components/agent/chat/components/Inputbar/index.test.tsx` + - `src/components/agent/chat/components/EmptyState.test.tsx` + - `src/components/skills/SkillsWorkspacePage.test.tsx` + - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - `docs/roadmap/limenextv2/skill-first-system.md` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - launcher 当前会从灵感库最近更新中拉取候选项,允许在启动时附带轻量灵感引用 + - 这些引用会一起编进首轮 prompt,不再只是“可选参考”的说明文案 + - `curated_task capabilityRoute` 当前会正式保留 `referenceMemoryIds` + - 发送时会同步写入 `requestMetadata.harness.curated_task` + - 若存在引用,当前会把首条引用写进 `creation_replay`,以便后续主链继续消费 + - 到这里为止,`首页 / 技能页 / slash / 生成内编辑` 四个结果模板入口,当前都已经共享 `catalog + launcher + prompt compile + route + metadata` 这条 current 主链 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/utils/curatedTaskReferenceSelection.test.ts" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` + - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` + - `npx eslint "src/components/agent/chat/utils/curatedTaskReferenceSelection.ts" "src/components/agent/chat/utils/curatedTaskReferenceSelection.test.ts" "src/components/agent/chat/utils/curatedTaskTemplates.ts" "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/hooks/useInputbarSend.ts" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` + - `npm run verify:local` + +- 把 `生成主执行面` 里已经激活的 `curated task`,补成“可重新编辑启动信息”的完整闭环,不再只支持首发 launcher: + - 已更新: + - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` + - `src/components/agent/chat/components/Inputbar/index.tsx` + - `src/components/agent/chat/components/Inputbar/index.test.tsx` + - `src/components/agent/chat/components/EmptyState.tsx` + - `src/components/agent/chat/components/EmptyStateComposerPanel.tsx` + - `src/components/agent/chat/components/EmptyState.test.tsx` + - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` + - `src/components/agent/chat/skill-selection/CuratedTaskBadge.tsx` + - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` + - `src/components/agent/chat/skill-selection/CharacterMention.tsx` + - `src/components/agent/chat/utils/curatedTaskTemplates.ts` + - `docs/exec-plans/limenext-progress.md` + - `docs/roadmap/limenextv2/skill-first-system.md` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - 当前统一结论: + - `curated_task capabilityRoute` 当前会正式保留 `launchInputValues` + - 首页、slash、技能页桥接进 `生成` 后,active `curated_task` badge 都能重新打开同一套 launcher + - 重新编辑时会回填原始启动字段,并基于目录模板重新编译 prompt,不再拿“已经编译过一次的 prompt”继续套娃 + - `Inputbar` 与首页空态当前都共享这条“编辑 -> 回填 -> 更新 route”的 current 主链 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/components/Inputbar/index.test.tsx"` + - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx"` + - `npx eslint "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/index.tsx" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx" "src/components/agent/chat/skill-selection/CuratedTaskBadge.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/utils/curatedTaskTemplates.ts"` + +- 把 slash 输入层里的 `curated task` 结果模板,也正式收口到同一套 `launcher -> curated_task capability -> 生成主执行面` 主链,不再保留“选择即写 base prompt”的输入层例外: + - 已更新: + - `src/components/agent/chat/skill-selection/CharacterMention.tsx` + - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` + - `docs/exec-plans/limenext-progress.md` + - `docs/roadmap/limenextv2/skill-first-system.md` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - 当前统一结论: + - slash 面板里的结果模板当前不再在选择瞬间把模板 prompt 直接塞回输入框 + - 选择后会先打开和首页、技能页同一套轻量 launcher,补齐 1 到 2 个最小启动字段 + - 确认后才会把编译后的 prompt 回填到输入框,并继续挂上 typed `curated_task capability` + - 到这里为止,`首页 / 技能页 / slash 输入层` 三个结果模板入口,当前已经同时共享 `catalog + launcher + capability route` 三层协议 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` + - `npx eslint "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` + +- 把首页 `结果模板` 与 `继续上次做法` 里的结果模板,也正式收口到同一套 `curated task launcher -> 生成主执行面` 主链,不再保留“点卡片即直接写 prompt”的首页例外: + - 已更新: + - `src/components/agent/chat/components/EmptyState.test.tsx` + - `docs/exec-plans/limenext-progress.md` + - `docs/roadmap/limenextv2/skill-first-system.md` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - 当前统一结论: + - 首页 `结果模板`、`继续上次做法` 里的结果模板,以及技能页 `先拿结果`,当前都已对齐到同一个轻量 launcher + - launcher 仍只负责补 1 到 2 个最小启动字段,然后把编译后的 prompt 通过 typed `curated_task capability` 带进 `生成` + - 因此首页不再是 `curated task` 主链里的特例;`skill-first` 前台当前对结果模板只有一条 current 启动协议 + - 文档里关于“首页继续快速起手、不走 launcher”的旧描述,当前也已同步清理 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx"` + - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` + - `npm run verify:local` + +- 把 `curated task` 从“展示 skill 合同”继续推进成“技能页可填写的最小 launcher”,让 `requiredInputs` 不再只是说明文案: + - 已更新: + - `src/components/agent/chat/utils/curatedTaskTemplates.ts` + - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` + - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` + - `src/components/skills/SkillsWorkspacePage.tsx` + - `src/components/skills/SkillsWorkspacePage.test.tsx` + - `src/components/agent/chat/components/Inputbar/index.test.tsx` + - `docs/exec-plans/limenext-progress.md` + - `docs/roadmap/limenextv2/skill-first-system.md` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - 当前统一结论: + - `curated task` 现在除了 `requiredInputs` 文案,还新增了真实可填写的 `requiredInputFields` + - 技能页 `先拿结果` 点击后,不再直接把模板 prompt 裸带进 `生成`,而是先打开轻量 launcher dialog + - 当前每条 curated task 只收 1 到 2 个最小启动字段,避免在技能页复制一整套重型 slot gate + - launcher 会通过 `buildCuratedTaskLaunchPrompt(...)` 把用户填写的启动信息编译进首轮 prompt,再继续走 typed `curated_task capability` + - 这意味着 P2 当前已经从“skill 合同可见”推进到“skill 合同可启动”,而不是继续停留在卡片说明层 + - 当前已确认通过: + - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` + - `npx eslint "src/components/agent/chat/utils/curatedTaskTemplates.ts" "src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` + - `npm run typecheck` + - `npm run governance:legacy-report` + - `npm run verify:local` ## 2026-04-18 ### 已完成 +- 把 `curated task` 从“typed capability 可发送”继续推进成“前台可理解的 skill 合同对象”,补齐 `你来给 / 可选参考 / 会拿到 / 下一步` 四类事实,并同步回首页与技能页: + - 已更新: + - `src/components/agent/chat/utils/curatedTaskTemplates.ts` + - `src/components/agent/chat/components/EmptyState.tsx` + - `src/components/skills/SkillsWorkspacePage.tsx` + - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` + - `src/components/agent/chat/components/EmptyState.test.tsx` + - `src/components/skills/SkillsWorkspacePage.test.tsx` + - `src/components/agent/chat/components/Inputbar/index.test.tsx` + - `docs/exec-plans/limenext-progress.md` + - `docs/roadmap/limenextv2/skill-first-system.md` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - 当前统一结论: + - `curated task` 当前不再只有 `title / summary / prompt` 这类轻量模板字段,而是已补齐: + - `requiredInputs` + - `optionalReferences` + - `outputContract` + - `followUpActions` + - 首页 `结果模板` 当前已开始展示“需要什么输入、会拿到什么交付”的缩略事实,不再只是标题列表 + - 技能页 `先拿结果` 当前已开始展示更完整的 skill 合同视图,用户能在进入 `生成` 之前先理解: + - 自己需要补什么 + - 可选参考能带什么 + - 这条 skill 会产出什么 + - 产出后还能怎么继续 + - 因此 `curated task` 当前已更接近 V2 设定里的正式 skill launcher,而不是仅靠 prompt 命名的“结果模板按钮” + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` + - `npx eslint "src/components/agent/chat/utils/curatedTaskTemplates.ts" "src/components/agent/chat/components/EmptyState.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` + - `npm run typecheck` + - `npm run governance:legacy-report` + - `npm run verify:gui-smoke` + +- 把 `curated task` 从共享 prompt catalog 继续推进成 current typed capability,补齐 `首页 / 技能页 / slash / Inputbar 首屏恢复` 同一条 route: + - 已更新: + - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` + - `src/components/agent/chat/workspace/inputCapabilityRouting.ts` + - `src/components/agent/chat/skill-selection/CuratedTaskBadge.tsx` + - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` + - `src/components/agent/chat/components/EmptyStateComposerPanel.tsx` + - `src/components/agent/chat/components/EmptyState.tsx` + - `src/components/skills/SkillsWorkspacePage.tsx` + - `src/components/agent/chat/skill-selection/CharacterMention.tsx` + - `src/components/AppPageContent.tsx` + - `src/components/agent/chat/components/Inputbar/index.test.tsx` + - `src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx` + - `src/components/agent/chat/components/EmptyState.test.tsx` + - `src/components/skills/SkillsWorkspacePage.test.tsx` + - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` + - `src/components/AppPageContent.test.tsx` + - `docs/exec-plans/limenext-progress.md` + - `docs/roadmap/limenextv2/skill-first-system.md` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - 当前统一结论: + - `curated task` 当前已正式进入 `InputCapabilitySelection / InputCapabilitySendRoute / initialInputCapability` 主链,不再只是 prompt catalog + - 首页点结果模板后,当前不只是把 prompt 写进输入框,也会挂上 `curated_task` active capability;发送时会透传结构化 route + - 技能页 `先拿结果` 当前不再依赖 `initialUserPrompt` 进 `生成`,而是像 installed skill 一样走 typed `initialInputCapability` + - slash 面板里的结果模板当前会同时做两件事:回填用户可见 prompt,并激活 `curated_task` capability + - `Inputbar` 首屏恢复当前已支持 `curated_task`;如果输入为空,会自动预填 route 内 prompt,并展示 badge + - `AppPageContent` 当前也已把 `curated_task` 纳入页面 key 序列化;切换不同模板时不会复用旧工作区实例 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/AppPageContent.test.tsx"` + - `npx eslint "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/agent/chat/workspace/inputCapabilityRouting.ts" "src/components/agent/chat/skill-selection/CuratedTaskBadge.tsx" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/EmptyStateComposerPanel.tsx" "src/components/agent/chat/components/EmptyState.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/AppPageContent.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/AppPageContent.test.tsx"` + - `npm run typecheck` + - `npm run governance:legacy-report` + - `npm run verify:gui-smoke` + +- 把 `结果模板` 从首页私有推荐 util 提升成共享 `curated task catalog`,并同时接回 `新建任务 / 我的方法 / slash 输入层` 三个前台入口: + - 已更新: + - `src/components/agent/chat/utils/curatedTaskTemplates.ts` + - `src/components/agent/chat/components/EmptyState.tsx` + - `src/components/skills/SkillsWorkspacePage.tsx` + - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` + - `src/components/agent/chat/skill-selection/CharacterMention.tsx` + - `src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx` + - `src/components/agent/chat/components/EmptyState.test.tsx` + - `src/components/skills/SkillsWorkspacePage.test.tsx` + - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` + - `docs/exec-plans/limenext-progress.md` + - `docs/roadmap/limenextv2/skill-first-system.md` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - 当前统一结论: + - 首页里的 `结果模板` 不再只是一组 `EmptyState` 私有 prompt 推荐;现在它已经被收成共享 `curated task catalog` + - `我的方法` 页右侧新增了 `先拿结果` 桥接区;因此结果模板不再只存在于首页,技能页也能用同一套 curated task 把用户带回 `生成` + - `@ / /` 输入层当前也会展示同一套 curated task;slash 选择后会把模板 prompt 回填到输入框并记录最近使用,不再只有 runtime scene 能占据 `结果模板` 分组 + - 到这里为止,`首页结果模板 / 技能页桥接入口 / slash 结果模板` 已共用同一份前台事实源;`结果模板` 不再在三个入口里各讲各的话 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` + - `npx eslint "src/components/agent/chat/utils/curatedTaskTemplates.ts" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` + - `npm run typecheck` + +- 把 `AppPageContent` 这一层壳也补回 `initialInputCapability` current 主链,避免技能页直达生成时在页面分发层丢参或错误复用旧工作区实例: + - 已更新: + - `src/components/AppPageContent.tsx` + - `src/components/AppPageContent.test.tsx` + - `docs/exec-plans/limenext-progress.md` + - `docs/roadmap/limenextv2/runtime-architecture.md` + - 当前统一结论: + - `AgentPageParams.initialInputCapability` 当前不再只停留在页面参数类型和 `AgentChatPage` 直接测试里;`AppPageContent` 已正式透传这层 bootstrap 给 `AgentChatPage` + - `AppPageContent` 当前也已把 `initialInputCapability` 纳入 `AgentChatPage` key;因此从技能页或其他入口连续切换不同 installed skill / capability 时,会重建对应工作区实例,而不是偷偷复用上一条 current capability + - 到这里为止,`技能页 -> 页面路由 -> Agent 壳 -> Inputbar 首屏恢复` 这条 current 主链已经闭合,不再只有中间层正确、页面壳层漏参 + - 当前已确认通过: + - `npm exec vitest run "src/components/AppPageContent.test.tsx" "src/components/agent/chat/index.shell-routing.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` + - `npx eslint "src/components/AppPageContent.tsx" "src/components/AppPageContent.test.tsx"` + - `npm run typecheck` + - `npm run governance:legacy-report` + - `npm run verify:gui-smoke` + +- 把 `技能页 / 新建任务页 -> 生成` 的 installed skill 入口也收口到 typed capability bootstrap,不再让“我的方法库”继续停留在被动展示: + - 已更新: + - `src/types/page.ts` + - `src/components/agent/chat/agentChatWorkspaceContract.ts` + - `src/components/agent/chat/workspaceEntry.ts` + - `src/components/agent/chat/index.tsx` + - `src/components/agent/chat/AgentChatWorkspace.tsx` + - `src/components/agent/chat/workspace/useWorkspaceInputbarSceneRuntime.tsx` + - `src/components/agent/chat/components/Inputbar/index.tsx` + - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` + - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` + - `src/components/skills/SkillsWorkspacePage.tsx` + - `src/components/agent/chat/workspaceEntry.test.ts` + - `src/components/agent/chat/index.shell-routing.test.tsx` + - `src/components/agent/chat/components/Inputbar/index.test.tsx` + - `src/components/skills/SkillsWorkspacePage.test.tsx` + - `docs/exec-plans/limenext-progress.md` + - `docs/roadmap/limenextv2/runtime-architecture.md` + - `docs/roadmap/limenextv2/skill-first-system.md` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - 当前统一结论: + - `service skill` 继续通过 `initialPendingServiceSkillLaunch` 进入 `生成` 内 A2UI 补参主链;而 `installed skill` 当前则统一通过 `initialInputCapability` 恢复首屏 active capability + - `Inputbar` 当前可以在首屏根据 typed `capabilityRoute` 恢复 `builtin_command / installed_skill / runtime_scene`,因此从技能页进入 `生成` 不再需要伪造 `/` 文本 + - `我的方法库` 里的已安装 skill 当前已经不再只是目录卡,而是可以像 current curated service skill 一样,直接把用户带进 `生成` 主执行面 + - `AgentChatPage` / `workspaceEntry` 当前也已把 `initialInputCapability` 视为 direct workspace intent;因此新建任务入口不会再把这类请求误判成“空白首页” + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/workspaceEntry.test.ts" "src/components/agent/chat/index.shell-routing.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` + - `npm run typecheck` + - `npx eslint "src/types/page.ts" "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/agent/chat/agentChatWorkspaceContract.ts" "src/components/agent/chat/workspaceEntry.ts" "src/components/agent/chat/index.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/workspace/useWorkspaceInputbarSceneRuntime.tsx" "src/components/agent/chat/components/Inputbar/index.tsx" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/workspaceEntry.test.ts" "src/components/agent/chat/index.shell-routing.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` + - `npm run governance:legacy-report` + - `npm run verify:gui-smoke` + +- 把 `EmptyStateComposerPanel -> CharacterMention` 也收口到统一 capability 选择边界,不再让首页输入壳保留旧 `onSelectSkill` 主语义: + - 已更新: + - `src/components/agent/chat/components/EmptyState.tsx` + - `src/components/agent/chat/components/EmptyStateComposerPanel.tsx` + - `src/components/agent/chat/components/EmptyState.test.tsx` + - `docs/exec-plans/limenext-progress.md` + - `docs/roadmap/limenextv2/runtime-architecture.md` + - 当前统一结论: + - 首页输入壳当前也会像工作区 `Inputbar` 一样,把 `CharacterMention` 选择统一回调为 `onSelectInputCapability` + - 首页当前不只支持已安装 skill 的结构化发送,也支持 builtin command / runtime scene 的激活态显示、清除与结构化 route 透传 + - 因此 `EmptyState` 不再是“发送链统一、输入选择层仍旧语义”的半收口状态;首页 capability 主链当前已从选择、展示到发送保持同一套判断 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx"` + - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx"` + - `npm run typecheck` + +- 把 `Inputbar / EmptyState` 运行时页面里的 `skillSelection` 直构造也回收到共享绑定边界,补齐 governance 收口: + - 已更新: + - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` + - `src/components/agent/chat/components/EmptyState.tsx` + - `src/components/agent/chat/skill-selection/skillSelectionBindings.ts` + - `docs/exec-plans/limenext-progress.md` + - `docs/roadmap/limenextv2/runtime-architecture.md` + - 当前统一结论: + - `Inputbar / EmptyState` 当前不再在运行时代码里 direct `createSkillSelectionProps(...)`,而是统一回到共享 `skillSelectionBindings` 边界 + - 因此 current 主路径的页面层不再一边走 `activeCapability`,一边再偷偷拼一套旧 `skill selection` 运行时模型 + - 这一步补齐了治理守卫要求的 `skill-selection-direct-construction-runtime-usage`,避免后续 AI 继续从页面层长回旧选择协议 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` + - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.tsx" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/skill-selection/skillSelectionBindings.ts"` + - `npm run governance:legacy-report` + - `npm run typecheck` + +- 把 `EmptyState` 首页入口也接回统一 capability 主链,不再把已安装 skill 降级成文本前缀发送: + - 已更新: + - `src/components/agent/chat/components/EmptyState.tsx` + - `src/components/agent/chat/components/EmptyState.test.tsx` + - `src/components/agent/chat/AgentChatWorkspace.tsx` + - `src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.tsx` + - `docs/exec-plans/limenext-progress.md` + - `docs/roadmap/limenextv2/runtime-architecture.md` + - 当前统一结论: + - 首页空态当前不再使用 `useActiveSkill / wrapTextWithSkill` 把已安装 skill 拼成 `/ ...` 文本后再发送,而是改为与 `Inputbar` 同源的 `capabilityRoute + displayContent` + - `handleSendFromEmptyState` 当前已支持把结构化 `sendOptions` 继续交给主发送链;因此首页入口与工作区输入栏不再各说一套发送协议 + - 首页在“先选 installed skill,再切到 service skill / 做法卡 / 服务技能入口”时,当前会主动清掉旧 capability,不再残留过期 skill route + - 到这里为止,`生成` current 主路径里至少两条核心入口已经统一到同一套 capability 语义: + - 工作区 `Inputbar` + - 首页 `EmptyState` + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.test.ts"` + - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.tsx"` + - `npm run typecheck` + - `npm run verify:gui-smoke` + +- 把 `CharacterMention -> Inputbar` 的能力选择事件也收口成单一 current 边界,不再让 builtin / scene / installed skill 在主路径里各走一套接线: + - 已更新: + - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` + - `src/components/agent/chat/skill-selection/CharacterMention.tsx` + - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` + - `src/components/agent/chat/components/Inputbar/components/InputbarComposerSection.tsx` + - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` + - `src/components/agent/chat/components/Inputbar/index.tsx` + - `src/components/agent/chat/components/Inputbar/index.test.tsx` + - `docs/exec-plans/limenext-progress.md` + - `docs/roadmap/limenextv2/runtime-architecture.md` + - 当前统一结论: + - `Inputbar` 当前不再分别向 `CharacterMention` 透传 `onSelectBuiltinCommand / onSelectSceneCommand / onSelectSkill` 三套能力选择回调,而是统一改用 `onSelectInputCapability` + - `CharacterMention` 当前已支持把 `builtin_command / installed_skill / runtime_scene` 统一回调给父层 current 主路径;因此 `InputbarController` 内部的 active capability 不再需要靠三条并行接线去维持 + - `service skill / A2UI` 补参分支仍然保持独立入口;这条例外只服务必填 slot gate,不再影响“生成只有一条 capability 主链”的判断 + - 到这里为止,current 主路径的统一 capability 边界已经同时进入: + - 输入层 active capability 状态 + - 面板到输入栏的选择事件边界 + - 发送链的结构化 route 恢复 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` + - `npx eslint "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/Inputbar/components/InputbarComposerSection.tsx" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/index.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` + - `npm run typecheck` + - `npm run verify:gui-smoke` + +- 把 slash 面板里的已安装技能也接回 `activeCapability`,继续压缩“输入层文本回填”和“发送链结构化路由”之间的缝: + - 已更新: + - `src/components/agent/chat/skill-selection/CharacterMention.tsx` + - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` + - `docs/exec-plans/limenext-progress.md` + - `docs/roadmap/limenextv2/runtime-architecture.md` + - 当前统一结论: + - slash 面板里的 `installed skill` 当前在存在父层 `onSelectSkill` 接管时,不再默认回填 `/` 文本,而是改成与 `runtime_scene` 相同的 active capability 语义 + - 最近使用的 slash skill 当前也会优先把 `replayText` 回填为用户可见正文,再切到 active skill;因此“最近使用”不再偷偷把内部 `/skill-key` 路由文本重新写回输入框 + - 未提供父层接管时,slash installed skill 仍保持原 fallback:继续回填 `/`,所以这刀没有打断独立 `CharacterMention` 的旧使用方式 + - 到这里为止,输入层的 current capability 语义已经对齐到三类主对象: + - `builtin_command` + - `installed_skill` + - `runtime_scene` + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` + - `npx eslint "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` + - `npm run typecheck` + - `npm run verify:gui-smoke` + +- 把 slash 面板里的 runtime scene 选择正式接进 `activeCapability`,让输入层与发送层对 scene 的理解不再分叉: + - 已更新: + - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` + - `src/components/agent/chat/skill-selection/CharacterMention.tsx` + - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` + - `src/components/agent/chat/components/Inputbar/components/RuntimeSceneBadge.tsx` + - `src/components/agent/chat/components/Inputbar/components/InputbarComposerSection.tsx` + - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` + - `src/components/agent/chat/components/Inputbar/index.tsx` + - `src/components/agent/chat/components/Inputbar/index.test.tsx` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - slash 面板里选择 `scene command` 时,如果不是“必填 slot 先交给 A2UI 补参”的场景,当前会像 builtin command 一样切换成 `activeCapability`,而不是继续把 `/scene-key` 前缀回填进输入框 + - runtime scene 当前已拥有和 builtin command / installed skill 对齐的输入层语义: + - 选择后保留用户正文输入 + - 顶部显示可清除 badge + - 发送时由 `capabilityRoute` 恢复内部路由文本 + - 成功后由发送链统一回写 slash recent usage + - 最近使用的 scene 当前也会优先把 `replayText` 回填为用户可见正文,并同时挂上 `runtime_scene` active capability,不再重新把 `/scene-key replayText` 写回输入框 + - 需要 `slot gate / A2UI` 的 scene 当前保持原路径:仍优先交给 `onSelectServiceSkill`,这刀不把 scene 补参 UX 和 active capability 混成一团 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` + - `npx eslint "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/Inputbar/components/RuntimeSceneBadge.tsx" "src/components/agent/chat/components/Inputbar/components/InputbarComposerSection.tsx" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/index.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` + - `npm run typecheck` + - `npm run verify:gui-smoke` + +- 把 `capabilityRoute` 从“发送前的结构化提示”继续推进成发送链内的第一版统一 capability router,并把 runtime scene 也纳入同一入口: + - 已更新: + - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` + - `src/components/agent/chat/workspace/inputCapabilityRouting.ts` + - `src/components/agent/chat/workspace/useWorkspaceSendActions.ts` + - `src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx` + - `docs/exec-plans/limenext-progress.md` + - `docs/roadmap/limenextv2/runtime-architecture.md` + - 当前统一结论: + - `Inputbar` 继续只传 `displayContent + capabilityRoute`,不再回退去预拼 `@前缀`、`/skill-key` 或 scene 文本;真正的内部执行文本恢复点现在固定在 `useWorkspaceSendActions -> inputCapabilityRouting` + - `inputCapabilityRouting` 当前已统一承担三件事:恢复 builtin command / installed skill / runtime scene 的内部执行文本、推导 runtime scene 的结构化 route、产出 slash recent usage 的第一版统一结果 + - 纯文本输入的 `/scene-key ...` 当前也会在发送链内被推导成 `runtime_scene` route,再继续进入 `service_scene_launch` 主链;后续输入层如果直接给 scene route,也能复用同一条恢复逻辑 + - `executeSendPlan` 当前不再在发送后额外补一层“installed skill fallback usage”旁路;slash usage 统一从 plan 内的 `completedSlashUsage` 回写,避免 route 恢复与 usage 记录再次分叉 + - 当发送链因为默认参数补全等原因改写了真正 dispatch 文本时,`displayContent` 当前也会优先保留用户原始可见文案,不再被内部路由前缀污染 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx"` + - `npx eslint "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/agent/chat/workspace/inputCapabilityRouting.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx"` + - `npm run typecheck` + - `npm run verify:gui-smoke` + +- 把输入栏里“已选 capability 只是偷偷改写前缀文本”的旧做法继续收口成显式 dispatch route,并让发送链第一次吃到结构化的 active capability: + - 已更新: + - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` + - `src/components/agent/chat/hooks/handleSendTypes.ts` + - `src/components/agent/chat/components/Inputbar/hooks/useInputbarSend.ts` + - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` + - `src/components/agent/chat/components/Inputbar/index.tsx` + - `src/components/agent/chat/components/Inputbar/index.test.tsx` + - `src/components/agent/chat/workspace/useWorkspaceSendActions.ts` + - `src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - `Inputbar` 当前在发送 active capability 时,不再只把能力压扁成 `@前缀` 或 `/skill-key` 文本;现在会同时透传结构化 `capabilityRoute` + - 已选 builtin command / installed skill 当前都会把原始输入保存在 `displayContent` 里,因此线程里展示给用户看的文案可以继续保持“我真正输入了什么”,而不是被路由前缀污染 + - `useWorkspaceSendActions` 当前已经开始消费这层 route:installed skill 成功发送后,会按显式 `capabilityRoute` 回写 slash 最近使用,不再只能依赖“用户是否手动输入了 `/skill-key ...`”去猜测 + - 这一步把 `active capability -> 发送链` 从“文本技巧”推进成了第一版结构化 current 路由,也给后面继续抽统一 capability router 留出了明确边界 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx"` + - `npx eslint "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/agent/chat/hooks/handleSendTypes.ts" "src/components/agent/chat/components/Inputbar/hooks/useInputbarSend.ts" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/index.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/workspace/useWorkspaceSendActions.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx"` + - `npm run typecheck` + - `npm run verify:gui-smoke` + +- 把 runtime scene 的匹配规则从“面板一套、发送链一套”收口成共享 scene binding helper,并补上完整 current 门槛验证: + - 已更新: + - `src/components/agent/chat/service-skills/runtimeSceneBinding.ts` + - `src/components/agent/chat/service-skills/runtimeSceneBinding.test.ts` + - `src/components/agent/chat/skill-selection/CharacterMention.tsx` + - `src/components/agent/chat/workspace/serviceSkillSceneLaunch.ts` + - `src/components/agent/chat/workspace/serviceSkillSceneLaunch.test.ts` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - `CharacterMention` 当前不再自己维护 scene -> service skill 的匹配规则,slash 面板里“这个 scene 是否应回落成 service skill / A2UI 补参”统一改读 `runtimeSceneBinding` + - `serviceSkillSceneLaunch` 当前也不再单独维护 scene token、alias 与 `linkedSkillId` 的另一套判断;UI 面板和发送链对 `sceneKey / commandPrefix / aliases / linkedSkillId` 的理解已对齐 + - 这一步把 `生成` 主链里最容易漂移的一段 current 事实源先钉住:slash 发现面、scene 发射器和后续 service skill 回落不再各自解释“什么叫同一个场景” + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/service-skills/runtimeSceneBinding.test.ts" "src/components/agent/chat/workspace/serviceSkillSceneLaunch.test.ts" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` + - `npx eslint "src/components/agent/chat/service-skills/runtimeSceneBinding.ts" "src/components/agent/chat/service-skills/runtimeSceneBinding.test.ts" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/workspace/serviceSkillSceneLaunch.ts" "src/components/agent/chat/workspace/serviceSkillSceneLaunch.test.ts"` + - `npm run typecheck` + - `npm run verify:local` + +- 把 runtime capability catalog 从组件私有拼装继续收口成共享模块,并让输入面板与发送链各自读取同一套 current 目录选择器: + - 已更新: + - `src/components/agent/chat/skill-selection/runtimeInputCapabilityCatalog.ts` + - `src/components/agent/chat/skill-selection/runtimeInputCapabilityCatalog.test.tsx` + - `src/components/agent/chat/skill-selection/CharacterMention.tsx` + - `src/components/agent/chat/workspace/useWorkspaceSendActions.ts` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - `CharacterMention` 当前不再自己订阅和组装 runtime skill catalog,而是统一改读 `useRuntimeInputCapabilityCatalog`;因此 `@` / `/` 面板里的 builtin command 与 runtime scene 列表不再是组件内私有事实源 + - `useWorkspaceSendActions` 当前也不再直接扫 `skillCatalog` 自建 mention command 两张 Map,而是改读同模块下的 `useRuntimeMentionCommandCatalog` + - 这一步特意把发送链做成“只拿自己真正需要的 mention 路由映射”,不再为了发送前补全 `@命令` 最近输入而顺手依赖整份 scene 列表;因此 current 主线更接近我们要的 typed capability registry,而不是继续把 UI 搜索目录和发送路由耦在一起 + - 到这里为止,`@ / /` current 主线已经形成三层同源收口:输入分组与激活态共享 capability section builder、scene 回落共享 runtime scene binding、发送链共享 runtime mention catalog + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/skill-selection/runtimeInputCapabilityCatalog.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx"` + - `npx eslint "src/components/agent/chat/skill-selection/runtimeInputCapabilityCatalog.ts" "src/components/agent/chat/skill-selection/runtimeInputCapabilityCatalog.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/workspace/useWorkspaceSendActions.ts"` + - `npm run typecheck` + - `npm run verify:gui-smoke` + +- 把 `生成` 输入层的选择态与分组态往统一 capability registry 收口了一刀,不再让内建命令与已安装 skill 各持一套独立选择状态: + - 已更新: + - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` + - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` + - `src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx` + - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` + - `src/components/agent/chat/components/Inputbar/hooks/useInputbarSend.ts` + - `src/components/agent/chat/components/Inputbar/index.test.tsx` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - `@ / /` 面板当前已开始消费同一份前端 capability section builder:最近使用、内建命令、推荐技能、技能组、快捷操作、结果模板等分组不再散落在 `CharacterMentionPanel` 内部各自维护 + - 输入栏当前的“已选 capability”不再拆成 `activeBuiltinCommand + activeSkill` 两套状态,而是统一收口成单一 active capability;因此“先选内建命令再选 skill”这类链路会以后一次选择为准,不会再残留旧能力覆盖发送文本 + - 这一步仍属于前端 current 路径的第一版 unified capability registry:先收口输入层事实源与激活态,不引入新的后端协议,也不扩第二套执行系统 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` + - `npx eslint "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/hooks/useInputbarSend.ts" "src/components/agent/chat/components/Inputbar/index.test.tsx"` + +- 把 unified capability registry 这一刀补齐到“能完整过当前统一门槛”,并顺手修掉服务技能入口残留旧 capability 的发送链污染: + - 已更新: + - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` + - `src/components/skills/WorkflowProgress.test.tsx` + - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` + - `src/components/agent/chat/components/Inputbar/index.test.tsx` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - `inputCapabilitySections` 里最近使用分组的联合类型已经显式收口,不再因为 `flatMap` 首分支推断过窄,把 `service_skill / scene_command / installed_skill` 误判成非法返回值 + - `WorkflowProgress.test.tsx` 已补齐当前 `WorkflowStepInfo.dependencies` 与 `StepResult.step_name` 契约,`verify:local` 不再被落后的测试夹具卡住 + - 输入栏当前在“先选 `@命令`,再切到服务技能入口”时会主动清掉旧 active capability,不再把前一次 builtin command 前缀偷偷带进后续发送 + - 这一步继续沿着 V2 的同一条主线推进:`@ / /` 不只是 UI 分组统一,还要保证 capability 激活态、服务技能入口和最终发送链属于同一套 current 行为 + - 当前已确认通过: + - `npm run verify:local` + - `npm run typecheck` + - `npm exec vitest run "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/skills/WorkflowProgress.test.tsx"` + - `npx eslint "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/skills/WorkflowProgress.test.tsx"` + - 当前补充说明: + - `npm run verify:local` 是在“服务技能入口清空旧 capability”这一记收尾补丁之前启动的,但该补丁只落在输入栏前端 current 主链;补丁本身已经额外通过定向 `typecheck / vitest / eslint`,因此本轮交付按“统一入口通过 + 收尾补丁定向门槛通过”共同记录 + +- 把 Ribbi 命令研究正式收口成统一事实源,并同步回挂到 LimeNext V2 路线图,避免研究层与规划层再次分叉: + - 已更新: + - `docs/research/ribbi/command-inventory.md` + - `docs/research/ribbi/README.md` + - `docs/research/ribbi/agent-tool-orchestration.md` + - `docs/roadmap/limenextv2/README.md` + - `docs/roadmap/limenextv2/product-principles.md` + - `docs/roadmap/limenextv2/information-architecture.md` + - `docs/roadmap/limenextv2/runtime-architecture.md` + - `docs/roadmap/limenextv2/skill-first-system.md` + - `docs/roadmap/limenextv2/lime-vs-ribbi.md` + - `docs/roadmap/limenextv2/implementation-roadmap.md` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - Ribbi 的命令、agent、tool、sandbox、preview、publish 当前统一以 `docs/research/ribbi/command-inventory.md` 为唯一研究事实源,不再允许在其他文档里散写另一套命令口径 + - LimeNext V2 当前已明确:`生成` 不只是主执行面,还是统一调用面;`@ / /` 只是 `生成` 内的 typed capability registry 交互壳,不再被写成第二套执行系统 + - `技能` 与 `命令层` 当前已被明确拆分:`技能` 负责发现与启动,`命令层` 负责在线程内调用 skill、model agent、sandbox、search/read、media transform、preview/publish 等具体能力 + - 这一步把 V2 从“像 Ribbi 一样做闭环”的抽象描述,推进到了“Ribbi 的命令层如何影响 Lime 前台、IA 和运行时骨架”的可执行规划阶段 + +- 把 `新建任务` 首页里落后的硬编码精选 skill 逻辑收口成共享的 current curated helper,不再单独维护一套首页 skill 事实源: + - 已更新: + - `src/components/agent/chat/service-skills/homeEntrySkills.ts` + - `src/components/agent/chat/service-skills/useServiceSkills.ts` + - `src/components/agent/chat/components/EmptyState.tsx` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - 首页精选 service skill 当前不再依赖硬编码 skill ID,而是复用同一份 service skill 目录、surface scope 与推荐分桶规则 + - 首页若当前运行时目录里没有可展示的 `home` 精选 skill,会用同一条 seeded service skill 事实源补齐精选位,而不是在 `EmptyState` 里手写一套单独对象 + - `useServiceSkills` 与 `新建任务` 首页当前共享同一条“首页可展示 skill”过滤规则;旧的首页精选硬编码实现已移除 + - 这一步把 `技能页 / 新建任务` 的 skill-first 收口往前推进了一刀:至少首页精选 skill 不再是独立维护的旧链 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/service-skills/useServiceSkills.test.tsx"` + - `npx eslint "src/components/agent/chat/service-skills/homeEntrySkills.ts" "src/components/agent/chat/service-skills/useServiceSkills.ts" "src/components/agent/chat/components/EmptyState.tsx"` + - 当前补充说明: + - `npm run typecheck` 这轮未通过,但阻塞点在既有 `src/components/skills/WorkflowProgress.test.tsx` 类型不匹配:`WorkflowStepInfo.dependencies` 与 `StepResult.step_name` 缺失,当前判断不是这次首页 skill 收口改动引入的新问题 + +- 把“上一版无人使用时不背历史包袱”的原则正式写回仓库级约束,避免后续继续给旧实现续命: + - 已更新: + - `AGENTS.md` + - `docs/aiprompts/governance.md` + - `.codex/skills/lime-governance/SKILL.md` + - `.codex/skills/lime-command-boundary/SKILL.md` + - `.codex/skills/lime-quality-workflow/SKILL.md` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - 当用户已明确“上一版无人使用 / 不用兼容 / 旧实现阻碍主线”时,旧实现默认不再继续修补,而是按 `dead` 或带退出条件的 `deprecated` 收口 + - `legacy current reference` 统一只表示历史实现锚点,不再被解释成可以继续往旧页面、旧命令、旧协议上加功能 + - 后续若命中旧实现与 current 规划冲突,默认动作应先删旧实现和封旧路,再继续补主链 + +- 把 `生成主执行面` 的 `最近发布产物` 从“只列出文件”继续补成“带轻量发布态判断”的 current 结果区: + - 已更新: + - `src/components/agent/chat/workspace/sceneAppExecutionContentPosts.ts` + - `src/components/agent/chat/workspace/sceneAppExecutionContentPosts.test.ts` + - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx` + - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx` + - `docs/exec-plans/limenext-plan.md` + - `docs/exec-plans/limenext-progress.md` + - `docs/roadmap/limenext/README.md` + - 当前统一结论: + - `sceneAppExecutionContentPosts` 当前不再只聚合 `发布稿 / 渠道预览稿 / 上传稿` 三张文稿,还会顺手检查同名 `*.cover.json / *.publish-pack.json` 伴随文件 + - `生成` 页执行摘要卡里的 `最近发布产物` 现在会直接显示 `可继续发布 / 优先渠道预览 / 优先上传整理 / 待补封面信息、发布包` 等轻量就绪态,并把 `封面信息 / 发布包` 作为 companion 芯片带出来 + - 这一步仍只消费现有 `content-posts` 文件命名约定与 metadata,不新增新的发布状态协议;旧日志里若继续写“最近发布产物当前只是三个文件入口”,都按已过时理解 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/workspace/sceneAppExecutionContentPosts.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx"` + - `npx eslint "src/components/agent/chat/workspace/sceneAppExecutionContentPosts.ts" "src/components/agent/chat/workspace/sceneAppExecutionContentPosts.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx"` + - `npm run typecheck` + +- 把 `生成主执行面` 从“能发起发布后动作”继续补成“也能直接消费这些动作产物”: + - 已更新: + - `src/components/agent/chat/workspace/sceneAppExecutionContentPosts.ts` + - `src/components/agent/chat/workspace/sceneAppExecutionContentPosts.test.ts` + - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx` + - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx` + - `src/components/agent/chat/AgentChatWorkspace.tsx` + - `docs/exec-plans/limenext-plan.md` + - `docs/exec-plans/limenext-progress.md` + - `docs/roadmap/limenext/README.md` + - 当前统一结论: + - `生成` 页执行摘要卡当前已新增 `最近发布产物` 区块,会直接聚合当前会话里的 `发布稿 / 渠道预览稿 / 上传稿` + - 聚合逻辑当前只消费带 `contentPostIntent / contentPostLabel` metadata 的 current 发布产物,不会把普通 `content-posts/*.md` 误判成投放结果 + - 打开链继续复用现有工作区预览主链:优先打开当前内存里的 `task file / artifact`,没有时再回落到 `session file` 读取;因此这一步没有新增新的 viewer 或发布协议 + - 旧日志里若继续写“生成页当前只能触发发布动作、不能直接消费发布稿结果”,当前都按已被本条替代的过时阶段理解 + - 当前已确认通过: + - `npm exec vitest run "src/components/agent/chat/workspace/sceneAppExecutionContentPosts.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx"` + - `npx eslint "src/components/agent/chat/workspace/sceneAppExecutionContentPosts.ts" "src/components/agent/chat/workspace/sceneAppExecutionContentPosts.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx"` + - `npm run typecheck` + - GUI 校验补充说明: + - `npm run verify:gui-smoke` 这轮未通过,阻塞在启动期环境探测:脚本先误判 `http://127.0.0.1:1420/` 存在可复用前端壳,但 180 秒内实际无法连通该地址,随后 headless Tauri 在 `DevBridge` 就绪前提前退出(`exitCode=1`) + - 同轮补查 `1420 / 3030` 端口时都无法直接连接,说明这次失败属于本地 GUI smoke 环境启动问题,而不是“最近发布产物”这一条业务链本身在断 + +- 把 `创作场景 -> 持续流程 -> 创作场景` 的快速切换从局部 pending 修补收口成全局导航事务: + - 已更新: + - `src/hooks/useAppNavigation.ts` + - `src/hooks/useAppNavigation.test.tsx` + - `src/App.tsx` + - `src/components/AppSidebar.tsx` + - `src/components/AppPageContent.tsx` + - `src/components/AppPageContent.test.tsx` + - `src/components/sceneapps/SceneAppsPage.tsx` + - `src/components/sceneapps/useSceneAppsPageRuntime.ts` + - `src/components/sceneapps/SceneAppsPage.test.tsx` + - `docs/exec-plans/limenext-plan.md` + - `docs/exec-plans/limenext-progress.md` + - 当前统一结论: + - 全局导航当前固定为 `requestedPage / requestedPageParams` 与 `currentPage / pageParams` 双态;侧栏高亮与主内容区优先按最新请求态渲染,快速连点时以最后一次点击为准 + - `SceneAppsPage` 保留 keep-alive,但旧页失去导航所有权后不再回写 `sceneapps` 参数、也不再写 recent visit,因此不会再把页面抢回 `创作场景` + - `创作场景 -> 持续流程 -> 创作场景` 的快切链路当前已从“局部 pending 态互相覆盖”收口到“单一全局导航事实源”,不再出现闪动、空白或左侧导航短暂消失 + - 当前已确认通过: + - `npm exec vitest run "src/hooks/useAppNavigation.test.tsx" "src/components/AppSidebar.test.tsx" "src/components/AppPageContent.test.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx"` + - `npm run verify:local` + - `npm run verify:gui-smoke` + - 当前补充说明: + - 额外盘点了仓库里其余 `onNavigate(...)` 调用点;当前未发现第二条与 `SceneApps keep-alive + 非激活态异步回写` 同型的导航抢写链路 + - 2026-04-18 追加复跑最新工作树的 `npm run verify:gui-smoke` 时,headless Tauri 启动阶段一直未等到 `DevBridge` 健康检查就绪,最终按 `bridge:health` 超时退出;当前判断这次阻塞发生在环境 / 启动期,不是导航链路的定向回归,因为同轮导航 Vitest 仍是 `58/58` 通过 + - 如果后续再出现同类闪回,下一步应优先继续排查是否还有页面在非激活态 effect 中自动回写全局导航 + - 把 `生成主执行面` 的 `同聊推进` 从“发布前整理”继续扩到现有 `渠道预览 / 上传稿` 主链: - 已更新: - `src/lib/sceneapp/executionPromptActions.ts` @@ -290,7 +1290,7 @@ - `docs/roadmap/limenext/context-layer.md` - `docs/roadmap/limenext/sceneapp-business-flows.md` - `docs/roadmap/limenext/sceneapp-fullstack-implementation-plan.md` - - `docs/roadmap/ribbi/product-positioning-and-ia.md` + - 旧 Ribbi 对位文档已清理;相关判断现统一收口到 `docs/research/ribbi/*` 与 `docs/roadmap/limenextv2/*` - 当前统一结论: - 侧边栏与前台 current 主词现在固定为 `新建任务 / 生成 / 我的方法 / 创作场景 / 消息渠道 / 资料库 / 灵感库` - `agentEntry=claw` 继续保留为内部实现 route,但前台已统一按 `生成` 理解 diff --git a/docs/exec-plans/upstream-runtime-alignment-plan.md b/docs/exec-plans/upstream-runtime-alignment-plan.md index 7cbe17f8b..258009984 100644 --- a/docs/exec-plans/upstream-runtime-alignment-plan.md +++ b/docs/exec-plans/upstream-runtime-alignment-plan.md @@ -67,7 +67,7 @@ Lime 当前不是“能力不够”,而是“主链不够单一”。 | 文档群 | 归属主链 | 角色 | | --- | --- | --- | -| `docs/roadmap/lime-aster-codex-alignment-roadmap.md`、`docs/roadmap/lime-aster-codex-state-model-implementation-plan.md` | `Query Loop`、`State / History / Telemetry` | Aster/Codex 历史专项档案,不再承担仓库级总排期或 current 实施入口职责 | +| `docs/roadmap/lime-aster-codex-alignment-roadmap.md` | `Query Loop`、`State / History / Telemetry` | Aster/Codex umbrella 历史专项档案,已吸收原状态模型与执行效率子专题,不再承担仓库级总排期或 current 实施入口职责 | | `docs/roadmap/reliability/*` | `State / History / Telemetry` | Reliability control plane 专项 | | `docs/tech/harness/*`、`docs/roadmap/harness-engine/*` | `State / History / Telemetry`、`Memory / Compaction` | Evidence / replay / review / observability / cleanup 专项 | | `docs/develop/execution-tracker-technical-plan.md`、`docs/develop/execution-tracker-p1-p2-roadmap.md`、`docs/develop/scheduler-task-governance-p1.md` | `Task / Agent / Coordinator` | 长时执行与治理专项 | @@ -182,15 +182,15 @@ Lime 当前不是“能力不够”,而是“主链不够单一”。 - 已完成第一刀:`docs/aiprompts/state-history-telemetry.md` 已成为 State / History / Telemetry current 入口 - 已完成第二刀:`agent_sessions / agent_messages -> SessionDetail -> AgentRuntimeThreadReadModel -> RequestLog 关联键 -> handoff/evidence/replay/analysis/review -> history-record/trend/cleanup/dashboard -> HarnessStatusPanel / AgentThreadReliabilityPanel` 已明确为 current 主链 -- 已完成第三刀:`docs/roadmap/lime-aster-codex-state-model-implementation-plan.md`、`docs/roadmap/reliability/*` 与 `telemetry_cmd.rs` 已明确退回 compat;cleanup 报表里残留的 `requestTelemetry:unlinked` 旧语义已明确为 deprecated +- 已完成第三刀:原 `state-model` 历史子专题、`docs/roadmap/reliability/*` 与 `telemetry_cmd.rs` 已明确退回 compat;cleanup 报表里残留的 `requestTelemetry:unlinked` 旧语义已明确为 deprecated - 已完成第四刀:`docs/README.md`、`docs/aiprompts/README.md`、`docs/aiprompts/overview.md`、`AGENTS.md` 已同步回挂新入口,仓库导航不再继续把状态模型专题计划、reliability 计划或原始 request log 控制台误当成 current 主链 - 已完成第五刀:`docs/roadmap/reliability/README.md` 已补成 compat 目录入口;cleanup 核心脚本已把旧 `requestTelemetry:unlinked` 样本折叠为 `known_gap`,避免旧历史语义继续充当现役状态类别 - 已完成第六刀:`docs/roadmap/reliability/*.md` 全部补上 compat 提示,正文开头先回挂 `state-history-telemetry.md`;`telemetry_cmd.rs` 也已明确只暴露原始 `RequestLog` 与聚合统计,不再和 thread read / evidence 主链抢解释权 - 已完成第七刀:`docs/roadmap/reliability/*.md` 顶部重复的上位文档列表已压成统一 `README + current 主链 + PR 对应映射` 导航,专项正文不再继续堆叠第二套入口说明 - 已完成第八刀:整组 `docs/roadmap/reliability/*` 已进一步压缩为 compat 历史摘要档案,只保留落地结果、current 映射与延后增强项;重复的目标/问题/范围/实施清单正文已回退到仓库历史 -- 已完成第九刀:`docs/roadmap/lime-aster-codex-state-model-implementation-plan.md` 已进一步压缩为 compat 历史摘要档案,`alignment-roadmap` 顶部导航也已改回 `query-loop / state-history-telemetry / upstream-runtime-alignment-plan` 这组 current 入口 -- 已完成第十刀:`docs/roadmap/lime-aster-codex-alignment-roadmap.md` 已进一步压缩为 compat 历史摘要档案,只保留阶段映射、历史判断与 current 回看入口 -- 已完成第十一刀:`docs/roadmap/lime-conversation-execution-efficiency-roadmap.md` 已进一步压缩为 compat 历史摘要档案,`docs/roadmap/artifacts/*` 对运行时边界的引用也已统一改回 `query-loop / task-agent-taxonomy / state-history-telemetry / upstream-runtime-alignment-plan` +- 已完成第九刀:原 `state-model` 历史摘要已完成压缩并最终并入 `docs/roadmap/lime-aster-codex-alignment-roadmap.md`,current 入口固定回到 `query-loop / state-history-telemetry / upstream-runtime-alignment-plan` +- 已完成第十刀:`docs/roadmap/lime-aster-codex-alignment-roadmap.md` 已固定为 compat umbrella 历史档案,只保留阶段映射、状态模型与执行效率的核心判断 +- 已完成第十一刀:原 `conversation-execution-efficiency` 历史摘要已并入 `alignment-roadmap`,`docs/roadmap/artifacts/*` 对运行时边界的引用也已统一改回 `query-loop / task-agent-taxonomy / state-history-telemetry / upstream-runtime-alignment-plan` - `M5` 退出判断:已满足“session / thread / turn / request / evidence / history 的读模型叙事收口”的出口条件,后续只允许在 current 边界上继续长能力 ## 7. 当前默认判断 diff --git a/docs/exec-plans/upstream-runtime-alignment-progress.md b/docs/exec-plans/upstream-runtime-alignment-progress.md index 9d955eff9..2487f08a9 100644 --- a/docs/exec-plans/upstream-runtime-alignment-progress.md +++ b/docs/exec-plans/upstream-runtime-alignment-progress.md @@ -274,7 +274,7 @@ - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" hooks::tests:: --lib -- --nocapture` - 建立 State / History / Telemetry current 文档 [state-history-telemetry.md](../aiprompts/state-history-telemetry.md),把 `session / thread / turn / request / evidence / history` 收口成单一状态地图 - 将 `agent_sessions / agent_messages -> SessionDetail -> AgentRuntimeThreadReadModel -> RequestLog 关联键 -> handoff/evidence/replay/analysis/review -> history-record/trend/cleanup/dashboard -> HarnessStatusPanel / AgentThreadReliabilityPanel` 明确归到 state/history/telemetry current 主链 -- 将 [lime-aster-codex-state-model-implementation-plan.md](../roadmap/lime-aster-codex-state-model-implementation-plan.md)、`docs/roadmap/reliability/*` 与 [telemetry_cmd.rs](../../src-tauri/src/commands/telemetry_cmd.rs) 明确归到 compat,并把 cleanup 报表里残留的 `requestTelemetry:unlinked` 旧语义标记为 deprecated +- 将原 `state-model` 历史子专题、`docs/roadmap/reliability/*` 与 [telemetry_cmd.rs](../../src-tauri/src/commands/telemetry_cmd.rs) 明确归到 compat,并把 cleanup 报表里残留的 `requestTelemetry:unlinked` 旧语义标记为 deprecated - 将 state/history/telemetry 入口同步回 [docs/README.md](../README.md)、[docs/aiprompts/README.md](../aiprompts/README.md)、[docs/aiprompts/overview.md](../aiprompts/overview.md) 与 [AGENTS.md](../../AGENTS.md),仓库导航不再继续把旧状态模型方案或 reliability 计划当成 current 主线 - 再次执行 `npm run harness:doc-freshness` 并通过(`clean`) - 新增 [docs/roadmap/reliability/README.md](../roadmap/reliability/README.md),把 reliability 目录补成明确的 compat 入口,不再让分阶段计划文件继续承担 current 导航职责 @@ -282,10 +282,10 @@ - 在 `docs/roadmap/reliability/*.md` 全部补上 compat 提示,正文开头统一先回挂 [state-history-telemetry.md](../aiprompts/state-history-telemetry.md),避免专项正文继续被误读成 current 主入口 - 在 `docs/roadmap/reliability/*.md` 进一步压缩顶部导航:把重复的上位文档长列表统一收口为 `README + current 主链 + PR 对应映射`,减少专项正文重复解释 - 将整组 `docs/roadmap/reliability/*` 进一步压缩为 compat 历史摘要档案:只保留落地结果、current 映射与延后增强项,重复的目标/问题/范围/实施清单正文统一回退到仓库历史 -- 将 [lime-aster-codex-state-model-implementation-plan.md](../roadmap/lime-aster-codex-state-model-implementation-plan.md) 进一步压缩为 compat 历史摘要档案:只保留状态边界判断、current 映射与延后增强项,不再把它当 current 实施入口 +- 将原状态模型历史子专题进一步压缩并最终并入 [lime-aster-codex-alignment-roadmap.md](../roadmap/lime-aster-codex-alignment-roadmap.md):只保留状态边界判断、current 映射与延后增强项,不再保留独立顶层路线图 - 在 [lime-aster-codex-alignment-roadmap.md](../roadmap/lime-aster-codex-alignment-roadmap.md) 收紧顶部导航:当前入口统一回挂到 [query-loop.md](../aiprompts/query-loop.md)、[state-history-telemetry.md](../aiprompts/state-history-telemetry.md) 与 [upstream-runtime-alignment-plan.md](./upstream-runtime-alignment-plan.md) - 将 [lime-aster-codex-alignment-roadmap.md](../roadmap/lime-aster-codex-alignment-roadmap.md) 进一步压缩为 compat 历史摘要档案:只保留阶段映射、历史判断与 current 回看入口,不再继续承载长篇阶段任务与验证流水 -- 将 [lime-conversation-execution-efficiency-roadmap.md](../roadmap/lime-conversation-execution-efficiency-roadmap.md) 进一步压缩为 compat 历史摘要档案:只保留历史主题、current 映射与延后方向,不再继续承载运行时边界总入口职责 +- 将原对话执行效率历史子专题进一步压缩并并入 [lime-aster-codex-alignment-roadmap.md](../roadmap/lime-aster-codex-alignment-roadmap.md):只保留历史主题、current 映射与延后方向,不再保留独立顶层路线图 - 将 `docs/roadmap/artifacts/*` 中仍把旧执行效率路线图当 current 运行时依据的说明,统一改回 `query-loop / task-agent-taxonomy / state-history-telemetry / upstream-runtime-alignment-plan` - 在 [telemetry_cmd.rs](../../src-tauri/src/commands/telemetry_cmd.rs) 收紧命令注释:这些命令只暴露原始 `RequestLog` 与聚合统计,不负责定义 session/thread current 状态真相 - 继续对齐 team / task tool surface: @@ -340,7 +340,7 @@ - `M1` Query Loop 收口:已完成第二十五刀实现,并继续收口 `TurnInputEnvelope -> SessionConfig` 的 turn context snapshot 分叉、`action_runtime` 辅助恢复链的 turn context 旁路,以及 `compact_session` 控制回合的最小上下文边界;当前主路径已压成 `execute_aster_chat_request -> execute_runtime_turn_pipeline -> entry/ingress/submit_preparation/session_scope_execute`,turn context 的 output schema / auto_compact / request metadata 也已进一步收紧到共享 snapshot helper - `M2` Task / Agent taxonomy 收口:已完成 current taxonomy 文档、索引回挂与分类判断;当前长时执行入口统一按 `agent turn / subagent turn / automation job` 解释,`ExecutionTracker` 只作为统一执行摘要层,`SchedulerService` 只作为 compat 触发壳 - `M3` Remote runtime 收口:已完成 current remote 文档、索引回挂与分类判断;当前远程入口统一按 `消息渠道 runtime + 浏览器连接器 / ChromeBridge` 解释,`DevBridge` 与 `OpenClaw` 只作为 compat 支撑,`telegram_remote_cmd` 只作为 deprecated 单通道入口 -- `M5` State / History / Telemetry 收口:已完成 current 状态地图、索引回挂与分类判断;当前状态链统一按 `SessionDetail -> AgentRuntimeThreadReadModel -> RequestLog 关联键 -> export/history` 解释,旧状态模型方案、reliability 计划、Aster/Codex 联合路线图、旧执行效率路线图与原始 request log 浏览面只作为 compat 附属层,其中 `docs/roadmap/reliability/*`、[lime-aster-codex-state-model-implementation-plan.md](../roadmap/lime-aster-codex-state-model-implementation-plan.md)、[lime-aster-codex-alignment-roadmap.md](../roadmap/lime-aster-codex-alignment-roadmap.md) 与 [lime-conversation-execution-efficiency-roadmap.md](../roadmap/lime-conversation-execution-efficiency-roadmap.md) 已进一步压成历史摘要档案 +- `M5` State / History / Telemetry 收口:已完成 current 状态地图、索引回挂与分类判断;当前状态链统一按 `SessionDetail -> AgentRuntimeThreadReadModel -> RequestLog 关联键 -> export/history` 解释,旧状态模型方案、reliability 计划、Aster/Codex 联合路线图与原始 request log 浏览面只作为 compat 附属层,其中 `docs/roadmap/reliability/*` 与 [lime-aster-codex-alignment-roadmap.md](../roadmap/lime-aster-codex-alignment-roadmap.md) 已进一步压成 umbrella 历史摘要档案 - `M1` 退出判断:已满足“不再需要横跳多份文档才能解释 Lime 主循环”的出口条件,后续默认不再继续微切 `runtime_turn.rs` - `M2` 退出判断:已满足“所有长时执行入口都能归到唯一 taxonomy”的出口条件,后续不再继续把 execution tracker、scheduler、subagent、automation 当作多条平级主线分别排期 - `M3` 退出判断:已满足“remote 不再是多个并列产品旁路”的出口条件,后续只允许在 `gateway_channel_*` 与 `browser connector / ChromeBridge` current ingress 上继续长能力 @@ -349,5 +349,5 @@ ### 下一刀 -- `docs/roadmap/reliability/*`、[lime-aster-codex-state-model-implementation-plan.md](../roadmap/lime-aster-codex-state-model-implementation-plan.md)、[lime-aster-codex-alignment-roadmap.md](../roadmap/lime-aster-codex-alignment-roadmap.md) 与 [lime-conversation-execution-efficiency-roadmap.md](../roadmap/lime-conversation-execution-efficiency-roadmap.md) 的 compat 历史档案化已完成;当前又收口了 `TurnInputEnvelope -> SessionConfig` 的 turn context 分叉、`action_runtime` 辅助恢复链旁路,并显式化了 `compact_session` 控制回合的最小上下文边界;剩余散落在 `persona_cmd` / `theme_context_cmd` 的一次性临时会话配置也已收回专用 helper,零入口旧发送壳已删除,Tauri 命令层 raw execution 也已经固定为 3 处并补了源码扫描守卫。下一刀转向继续盘点 `src-tauri/src` 非命令层与 README/示例面是否还残留会误导实现者的原始执行旁路叙事 +- `docs/roadmap/reliability/*` 与 [lime-aster-codex-alignment-roadmap.md](../roadmap/lime-aster-codex-alignment-roadmap.md) 的 compat 历史档案化已完成;其中原 `state-model` 与 `conversation-execution-efficiency` 子专题已经并入 `alignment-roadmap`。当前又收口了 `TurnInputEnvelope -> SessionConfig` 的 turn context 分叉、`action_runtime` 辅助恢复链旁路,并显式化了 `compact_session` 控制回合的最小上下文边界;剩余散落在 `persona_cmd` / `theme_context_cmd` 的一次性临时会话配置也已收回专用 helper,零入口旧发送壳已删除,Tauri 命令层 raw execution 也已经固定为 3 处并补了源码扫描守卫。下一刀转向继续盘点 `src-tauri/src` 非命令层与 README/示例面是否还残留会误导实现者的原始执行旁路叙事 - 后续若出现 `runtime_turn` 行为回退,再回到 `M1` current 主路径做定点修复,而不是继续常态化微切 diff --git a/docs/images/logo-v6.svg b/docs/images/logo-v6.svg new file mode 100644 index 000000000..601da2250 --- /dev/null +++ b/docs/images/logo-v6.svg @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/oem/logo.md b/docs/oem/logo.md index 75a0cb6bc..e7ef364e9 100644 --- a/docs/oem/logo.md +++ b/docs/oem/logo.md @@ -1,5 +1,9 @@ # OEM Logo 快速替换指南 +> 状态:current oem derivative +> 更新:2026-04-19 +> 上游事实源:brand.md、slogan.md + 本文用于未来 OEM / 代理商定制时,快速把 Lime 的品牌图替换为代理商品牌图,并尽量让 AI 一次完成主要资产更新。 目标不是讲设计理论,而是提供一条可执行、可复用、低沟通成本的流程。 @@ -129,8 +133,10 @@ oem-logo-splash.png 另外把启动页改成只保留 logo、slogan、进度动画。 新的 slogan 是: “青柠一下,灵感即来” -副标是: -“从一句想法,到成稿、成图、成片、成事” +产品副标是: +“把一个内容任务推进为可交付结果” +可选说明行是: +“技能起手,灵感入库,生成推进” ``` 如果需要统一引用当前确认的品牌方案,优先查看: diff --git a/docs/prd/connect-test.html b/docs/prd/connect-test.html deleted file mode 100644 index d62df0627..000000000 --- a/docs/prd/connect-test.html +++ /dev/null @@ -1,534 +0,0 @@ - - - - - - ProxyCast Connect 测试页面 - - - -
-

🔗 ProxyCast Connect 测试

-

模拟中转商后台的一键配置功能 & Webhook 回调测试

- -
- - - -
- - - - - -
-
-

Webhook 回调测试

-

模拟 ProxyCast 发送的统计回调请求

- -
-
- - -
-
- - -
-
- -
-
- - -
-
- - -
-
- -
- - -
- -
- - - -
- - - -
-
请求日志:
-
-
- [--:--:--] - INFO - 等待发送回调请求... -
-
-
- -
-
💡 验证说明
-
- 由于 ProxyCast 是开源软件,不使用签名验证。
- 中转商应通过检查 key_prefix 是否为自己下发的 Key 来验证请求。 -
-
-
- -
-

回调字段说明

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
字段说明
status - success - cancelled - error -
relay_id中转商 ID
key_prefixKey 前缀(脱敏,仅前 7 位)- 用于验证
ref推广码(可选)
client客户端信息 {version, platform}
-
-
- - -
-
-

Deep Link 协议

-
-

协议格式

-
proxycast://connect?relay={relay_id}&key={api_key}&name={key_name}&ref={ref_code}
-
- - - - - - - - - - - - - - - - - - - - - -
relay必填中转商 ID
key必填API Key
name可选Key 显示名称
ref可选推广码
-
-
💡 测试前提
-
- 1. 确保 ProxyCast 应用已安装并运行
- 2. 确保 Deep Link 协议已正确注册
- 3. 如果点击无反应,检查浏览器是否阻止了协议跳转 -
-
-
- - -
-
- -
- - - - - diff --git a/docs/prd/credential-provider-plugin-architecture.md b/docs/prd/credential-provider-plugin-architecture.md deleted file mode 100644 index 45802adc8..000000000 --- a/docs/prd/credential-provider-plugin-architecture.md +++ /dev/null @@ -1,2009 +0,0 @@ -# ProxyCast 凭证提供商插件化架构 PRD - -> 版本: 1.0.0 -> 日期: 2026-01-03 -> 状态: Draft - ---- - -## 一、背景与目标 - -### 1.1 背景 - -当前 ProxyCast 支持 11 种 Provider 类型,但存在以下问题: - -1. **硬编码耦合**:Provider 类型通过 `ProviderType` 枚举硬编码,新增 Provider 需要修改核心代码 -2. **协议转换分散**:`converter/` 和 `translator/` 两套转换逻辑并存 -3. **风控逻辑耦合**:Kiro、Antigravity 等的特殊风控逻辑散落在各处 -4. **难以独立更新**:某个 Provider(如 Kiro)因风控变化需要更新时,影响整体 - -### 1.2 目标 - -将 **OAuth 凭证系统**重构为插件化架构,**API Key 系统保持现有设计不变**: - -1. **OAuth 凭证插件化**:Kiro、Codex、Gemini OAuth、Qwen、Antigravity、iFlow 等各自独立 -2. **API Key 系统不变**:现有 `api_key_providers` + `api_keys` 表结构保持不变,60+ 系统预设继续使用 -3. **独立更新**:某个 OAuth Provider 风控变化时,只需更新对应插件 -4. **复用现有插件系统**:基于现有的 `Plugin` trait 扩展 - -### 1.3 插件化范围 - -| 系统 | 是否插件化 | 原因 | -|------|-----------|------| -| **OAuth 凭证** | ✅ 是 | Kiro 风控复杂、Token 刷新、不同凭证格式 | -| **API Key** | ❌ 否 | 统一结构、配置简单、用户可自定义、已有 60+ 预设 | - ---- - -## 二、现有架构分析 - -### 2.1 凭证管理模块 - -``` -src-tauri/src/credential/ -├── types.rs # Credential, CredentialData, CredentialStatus -├── pool.rs # CredentialPool (DashMap 实现) -├── balancer.rs # LoadBalancer (轮询/最少使用/随机) -├── health.rs # HealthChecker (3次失败标记不健康) -├── quota.rs # QuotaManager (配额超限检测) -└── sync.rs # 数据库同步 -``` - -**现有凭证数据结构**: -```rust -pub enum CredentialData { - OAuth { access_token, refresh_token, expires_at }, - ApiKey { key, base_url }, -} -``` - -### 2.2 Provider 类型(现有问题:硬编码枚举) - -**问题**:现有设计使用硬编码枚举,新增 Provider 必须修改核心代码 - -```rust -// ❌ 现有设计:硬编码枚举 -pub enum ProviderType { - Kiro, Gemini, Qwen, OpenAI, Claude, Antigravity, - Vertex, GeminiApiKey, Codex, ClaudeOAuth, IFlow, - // 新增 Provider?必须修改这个枚举! -} - -pub enum CredentialData { - KiroOAuth { ... }, GeminiOAuth { ... }, ... - // 新增凭证类型?必须修改这个枚举! -} -``` - -**目标**:删除硬编码枚举,改为动态注册 - -```rust -// ✅ 目标设计:动态注册 -// 不再有 ProviderType 枚举 -// 不再有 CredentialData 枚举 -// 新增 Provider 只需实现 trait 并注册 -``` - -### 2.3 现有凭证类型(需要迁移到插件) - -| Provider | 凭证类型 | 配置字段 | -|----------|---------|---------| -| Kiro | OAuth | creds_file_path | -| Gemini | OAuth | creds_file_path, project_id | -| Qwen | OAuth | creds_file_path | -| Antigravity | OAuth | creds_file_path, project_id | -| OpenAI | API Key | api_key, base_url | -| Claude | API Key | api_key, base_url | -| Vertex | API Key | api_key, base_url, model_aliases | -| GeminiApiKey | API Key | api_key, base_url, excluded_models | -| Codex | OAuth | creds_file_path, api_base_url | -| ClaudeOAuth | OAuth | creds_file_path | -| IFlow | OAuth/Cookie | creds_file_path | - -**迁移后**:每个 Provider 插件自己定义凭证配置 Schema - -### 2.4 协议转换 - -**现有协议类型**: - -| 协议 | 用途 | -|------|------| -| OpenAI | 标准 Chat Completions API | -| Anthropic | Claude Messages API(Claude Code 使用此协议)| -| CodeWhisperer | AWS Kiro IDE(底层是 Claude)| -| Gemini | Google Gemini API | -| Antigravity | Google 内部(支持 Claude 和 Gemini 模型)| - -#### 2.4.1 双向转换架构 - -ProxyCast 作为 **API 代理**,核心职责是协议转换: - -``` -┌─────────────────────────────────────────────────────────────────────────┐ -│ 协议转换流程 │ -├─────────────────────────────────────────────────────────────────────────┤ -│ │ -│ 客户端请求 (Anthropic 协议 /v1/messages) │ -│ │ │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ 输入转换层 (Request Translator) │ │ -│ │ │ │ -│ │ Anthropic → CodeWhisperer (translator/kiro/anthropic/request) │ │ -│ │ Anthropic → Antigravity (converter/anthropic_to_antigravity)│ │ -│ │ Anthropic → Anthropic (Claude OAuth, 直通) │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ Provider 后端调用 │ │ -│ │ │ │ -│ │ Kiro: AWS CodeWhisperer API (返回 AWS Event Stream) │ │ -│ │ Antigravity: Gemini CLI API (返回 Antigravity 响应) │ │ -│ │ Claude OAuth: Anthropic API (返回 Anthropic SSE, 直通) │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ 输出转换层 (Response Translator) │ │ -│ │ │ │ -│ │ AWS Event Stream → Anthropic SSE │ │ -│ │ (translator/kiro/anthropic/response.rs) │ │ -│ │ │ │ -│ │ Antigravity → Anthropic SSE (claude-* 模型) │ │ -│ │ Antigravity → Gemini 协议 (gemini-* 模型) │ │ -│ │ │ │ -│ │ Anthropic SSE → Anthropic SSE (Claude OAuth, 直通) │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -│ │ │ -│ ▼ │ -│ Anthropic 协议响应 (给 Claude Code 等客户端) │ -│ │ -└─────────────────────────────────────────────────────────────────────────┘ -``` - -#### 2.4.2 转换规则(按底层模型决定) - -**核心原则**:输出协议由 **Provider 后端的底层模型** 决定,而非客户端输入格式 - -| Provider | 底层模型 | 后端协议 | 输出协议 | -|----------|---------|---------|---------| -| Kiro | Claude | CodeWhisperer (AWS Stream) | **Anthropic** (Claude API) | -| Antigravity (claude-*) | Claude | Antigravity | **Anthropic** (Claude API) | -| Antigravity (gemini-*) | Gemini | Antigravity | **Gemini** | -| Claude OAuth | Claude | Anthropic | **Anthropic** (直通) | -| Codex | GPT | OpenAI | **OpenAI** (直通) | -| Qwen | 通义千问 | OpenAI 兼容 | **OpenAI** | -| iFlow | - | OpenAI 兼容 | **OpenAI** | -| Gemini OAuth | Gemini | Gemini | **Gemini** | - -**转换链路示例**: - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ Kiro Provider(底层 Claude) │ -├─────────────────────────────────────────────────────────────────────┤ -│ │ -│ Anthropic 协议请求 (/v1/messages) │ -│ │ │ -│ ▼ │ -│ 输入转换: Anthropic → CodeWhisperer 请求 │ -│ │ (translator/kiro/anthropic/request.rs) │ -│ ▼ │ -│ Kiro 后端调用 (返回 AWS Event Stream) │ -│ │ │ -│ ▼ │ -│ 输出转换: AWS Stream → Anthropic SSE │ -│ │ (translator/kiro/anthropic/response.rs) │ -│ ▼ │ -│ Anthropic 协议响应 (给 Claude Code 等客户端) │ -│ │ -└─────────────────────────────────────────────────────────────────────┘ -``` - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ Antigravity Provider(动态协议) │ -├─────────────────────────────────────────────────────────────────────┤ -│ │ -│ Anthropic 协议请求 (model: claude-opus-4.5) │ -│ │ │ -│ ▼ │ -│ 输入转换: Anthropic → Antigravity 请求 │ -│ │ │ -│ ▼ │ -│ 匹配规则: claude-* → 底层 Claude │ -│ │ │ -│ ▼ │ -│ 输出转换: Antigravity → Anthropic SSE │ -│ │ -│ ───────────────────────────────────────────────────────────────── │ -│ │ -│ Anthropic 协议请求 (model: gemini-2.0-flash) │ -│ │ │ -│ ▼ │ -│ 输入转换: Anthropic → Antigravity 请求 │ -│ │ │ -│ ▼ │ -│ 匹配规则: gemini-* → 底层 Gemini │ -│ │ │ -│ ▼ │ -│ 输出转换: Antigravity → Gemini 协议响应 │ -│ │ -└─────────────────────────────────────────────────────────────────────┘ -``` - -**常见使用场景**: - -| 客户端 | Provider | 底层模型 | 输出协议 | -|--------|----------|---------|---------| -| **ProxyCast 内置 Agent** | Kiro | Claude | Anthropic (Claude API) | -| **ProxyCast 内置 Agent** | Antigravity (claude-*) | Claude | Anthropic (Claude API) | -| **ProxyCast 内置 Agent** | Claude OAuth | Claude | Anthropic (Claude API) | -| Claude Code | Kiro | Claude | Anthropic (Claude API) | -| Claude Code | Antigravity (claude-*) | Claude | Anthropic (Claude API) | -| Claude Code | Claude OAuth | Claude | Anthropic (Claude API) | -| Gemini 客户端 | Antigravity (gemini-*) | Gemini | Gemini | -| OpenAI 兼容客户端 | Codex | GPT | OpenAI | -| OpenAI 兼容客户端 | Qwen/iFlow | 通义千问等 | OpenAI | - -#### 2.4.3 ProxyCast API Server 架构 - -ProxyCast 提供 **API Server**,统一服务内部和外部客户端: - -``` -┌─────────────────────────────────────────────────────────────────────────┐ -│ ProxyCast API Server │ -│ │ -│ 端口: 8999 | 支持多种协议格式 | API Key 认证 │ -│ 地址: 127.0.0.1:8999 (本地) | 198.18.0.1:8999 (局域网) │ -├─────────────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ 客户端接入 │ │ -│ │ │ │ -│ │ 内部客户端: │ │ -│ │ ├── ProxyCast 内置 AI Agent(技能、话题、工具调用) │ │ -│ │ │ │ -│ │ 外部客户端: │ │ -│ │ ├── Claude Code (Anthropic 协议) │ │ -│ │ ├── Cursor (OpenAI 协议) │ │ -│ │ ├── Continue (OpenAI 协议) │ │ -│ │ └── 任意支持 OpenAI/Anthropic API 的应用 │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -│ │ │ -│ │ OpenAI / Anthropic / Gemini 等协议请求 │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ 服务器控制 │ │ -│ │ │ │ -│ │ 默认 Provider: [Kiro] [Gemini] [Qwen] [Antigravity] [OpenAI] [Claude]│ -│ │ 当前可用凭证: P2 (绿色表示健康) │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ 代理层处理 │ │ -│ │ │ │ -│ │ 1. API Key 验证 │ │ -│ │ 2. Provider 路由(根据默认设置或请求指定) │ │ -│ │ 3. OAuth 凭证获取 │ │ -│ │ 4. 协议转换(Anthropic → CodeWhisperer 等) │ │ -│ │ 5. 后端调用 │ │ -│ │ 6. 响应转换 │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -│ │ │ -│ ▼ │ -│ Kiro / Antigravity / Claude OAuth / Codex 等后端 │ -│ │ -└─────────────────────────────────────────────────────────────────────────┘ -``` - -**API Server 配置**: - -| 配置项 | 说明 | -|--------|------| -| 端口 | 默认 8999,可配置 | -| API Key | 访问密钥(如 Proxycast-key11)| -| 默认 Provider | 用户可选择默认路由的 Provider | - -**支持的输入/输出协议**: - -| 协议 | 端点 | 说明 | -|------|------|------| -| OpenAI | `/v1/chat/completions` | 标准 OpenAI Chat Completions API | -| Anthropic | `/v1/messages` | Claude Messages API | -| Gemini | `/v1/gemini/*` | Google Gemini API | -| OpenAI Responses | `/v1/responses` | OpenAI Responses API (流式) | -| 其他兼容协议 | - | 支持扩展更多协议 | - -**内置 AI Agent 特点**: - -| 功能 | 说明 | -|------|------| -| 模型选择 | 用户可选择任意已配置的模型(如 claude-opus-4-5-20251101)| -| 技能系统 | 支持自定义 Skills,扩展 Agent 能力 | -| 工具调用 | 支持 MCP、联网搜索、文件附件等 | -| 对话管理 | 话题列表、历史记录 | - -**统一调用流程**(内部/外部客户端一致): - -``` -客户端发送请求 (内置 Agent 或外部 Claude Code/Cursor) - │ - ▼ -API Server 接收 (端口 8999) - │ - ├── 验证 API Key - ├── 识别协议格式 (OpenAI / Anthropic / Gemini / OpenAI Responses 等) - │ - ▼ -根据默认 Provider 或请求参数路由 - │ - ▼ -OAuth Provider 处理 - ├── 获取凭证 - ├── 协议转换 (如 Anthropic → CodeWhisperer) - └── 调用后端 - │ - ▼ -响应转换 (如 AWS Stream → Anthropic SSE) - │ - ▼ -返回给客户端 -``` - -#### 2.4.4 StreamEvent 统一事件 - -中间表示层,解耦输入输出: - -```rust -pub enum StreamEvent { - MessageStart { id: String, model: String }, - ContentBlockStart { index: u32, block_type: ContentBlockType }, - TextDelta { text: String }, - ToolUseStart { id: String, name: String }, - ToolUseInputDelta { id: String, partial_json: String }, - ToolUseStop { id: String }, - ContentBlockStop { index: u32 }, - MessageStop { stop_reason: StopReason }, - Usage { input_tokens: u32, output_tokens: u32 }, - Error { error_type: String, message: String }, - Ping, -} -``` - -#### 2.4.5 现有代码位置 - -| 功能 | 文件路径 | -|------|---------| -| Anthropic → Kiro 请求 | `translator/kiro/anthropic/request.rs` | -| Kiro → Anthropic 响应 | `translator/kiro/anthropic/response.rs` | -| OpenAI → Kiro 请求 | `translator/kiro/openai/request.rs` | -| Kiro → OpenAI 响应 | `translator/kiro/openai/response.rs` | -| OpenAI → Antigravity | `converter/openai_to_antigravity.rs` | -| AWS 流解析 | `stream/parsers/aws_event_stream.rs` | -| Anthropic SSE 生成 | `stream/generators/anthropic_sse.rs` | -| OpenAI SSE 生成 | `stream/generators/openai_sse.rs` | - -#### 2.4.6 插件化后的协议转换 - -**目标**:每个 Provider 插件负责自己的双向转换 - -```rust -#[async_trait] -pub trait OAuthProviderPlugin: Send + Sync { - // ... 其他方法 ... - - /// 输入转换:将客户端请求转换为 Provider 特有格式 - async fn transform_request(&self, req: &mut ChatRequest) -> Result; - - /// 输出转换:将 Provider 响应转换为 StreamEvent - fn parse_response_chunk(&self, chunk: &[u8]) -> Result>; - - /// 目标输出协议(决定使用哪个 SSE Generator) - fn output_protocol(&self) -> OutputProtocol; // Anthropic | OpenAI -} - -pub enum OutputProtocol { - Anthropic, // Claude Code 使用 - OpenAI, // OpenAI 兼容客户端使用 -} -``` - -### 2.5 现有插件系统 - -```rust -#[async_trait] -pub trait Plugin: Send + Sync { - fn name(&self) -> &str; - fn version(&self) -> &str; - fn manifest(&self) -> &PluginManifest; - - async fn init(&mut self, config: &PluginConfig) -> Result<(), PluginError>; - async fn on_request(&self, ctx: &mut PluginContext, request: &mut Value) -> Result; - async fn on_response(&self, ctx: &mut PluginContext, response: &mut Value) -> Result; - async fn on_error(&self, ctx: &mut PluginContext, error: &str) -> Result; - async fn shutdown(&mut self) -> Result<(), PluginError>; -} -``` - -### 2.6 处理管道 - -``` -Auth → Injection → Routing → PluginPre → Provider → PluginPost → Telemetry -``` - ---- - -## 三、目标架构设计 - -### 3.1 核心设计原则 - -1. **插件职责明确**:每个 Provider 插件负责 凭证管理 + 协议转换 + 风控适配 -2. **转换成标准协议**:所有插件输出标准协议(Anthropic/OpenAI/Gemini) -3. **认证类型固定**:AuthType 作为枚举,不插件化 -4. **复用现有基础设施**:复用 credential/pool.rs, balancer.rs, health.rs - -### 3.2 完全动态化架构 - -**核心原则**:没有任何硬编码枚举,所有类型都通过注册表动态管理 - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ CredentialProviderRegistry(动态) │ -│ │ -│ 新增 Provider?只需实现 trait 并注册,无需修改核心代码 │ -│ │ -│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ -│ │ kiro │ │anthropic │ │ openai │ │ qwen │ │ iflow │ │ -│ │ Provider │ │ Provider │ │ Provider │ │ Provider │ │ Provider │ │ -│ │ │ │ │ │ │ │ │ │ │ │ -│ │ OAuth │ │ ApiKey │ │ ApiKey │ │ OAuth │ │ OAuth │ │ -│ │ 风控适配 │ │ 原生 │ │ 原生 │ │ 兼容 │ │ Cookie │ │ -│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ -│ │ │ │ │ │ │ -│ 目标协议: 目标协议: 目标协议: 目标协议: 目标协议: │ -│ "anthropic" "anthropic" "openai" "qwen" "openai" │ -│ │ │ │ │ │ │ -│ └────────────┴────────────┴────────────┴────────────┘ │ -│ │ │ -│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ -│ │ gemini │ │ vertex │ │ codex │ │antigravity│ ...更多 │ -│ │ Provider │ │ Provider │ │ Provider │ │ Provider │ │ -│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ -└─────────────────────────────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────────────┐ -│ StandardProtocolRegistry(动态) │ -│ │ -│ 新增协议?只需实现 ProtocolHandler trait 并注册 │ -│ │ -│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ -│ │anthropic │ │ openai │ │ gemini │ │ qwen │ │ doubao │ │ -│ │ Handler │ │ Handler │ │ Handler │ │ Handler │ │ Handler │ │ -│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ -│ │ -│ ┌──────────┐ ┌──────────┐ │ -│ │ wenxin │ │ ... │ ← 可继续扩展中国厂商协议 │ -│ │ Handler │ │ │ │ -│ └──────────┘ └──────────┘ │ -└─────────────────────────────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────────────┐ -│ 输出适配层 │ -│ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │ -│ │ Anthropic API │ │ OpenAI API │ │ Claude Code │ │ -│ │ Output │ │ Output │ │ Protocol │ │ -│ └────────────────┘ └────────────────┘ └────────────────┘ │ -└─────────────────────────────────────────────────────────────────────┘ -``` - -### 转换流程示例 - -``` -用户请求 (model: claude-opus-4.5) - │ - ▼ -CredentialProviderRegistry.find_by_model("claude-opus-4.5") - │ - ▼ -KiroProvider (匹配 claude-* 模型) - ├─ acquire_credential() → 获取 OAuth 凭证 - ├─ transform_request() → CodeWhisperer 格式 - ├─ apply_risk_control() → Machine ID、特殊头部 - └─ target_protocol() → "anthropic" - │ - ▼ -StandardProtocolRegistry.get("anthropic") - │ - ▼ -AnthropicProtocolHandler - ├─ format_request() → Anthropic Messages API 格式 - └─ parse_response() → 统一响应格式 - │ - ▼ -输出适配层 (根据客户端选择) - ├─ Anthropic API Output - ├─ OpenAI API Output - └─ Claude Code Protocol Output -``` - -### 3.3 CredentialProviderPlugin Trait - -```rust -/// 凭证提供商插件 - 核心 Trait -/// -/// 设计原则: -/// - 不依赖任何硬编码枚举 -/// - 新增 Provider 只需实现此 trait 并注册 -/// - 凭证配置由插件自己定义 Schema -/// - 一个插件可支持多种认证方式(OAuth、API Key、第三方中转) -#[async_trait] -pub trait CredentialProviderPlugin: Send + Sync { - // ========== 基础信息 ========== - - /// 插件唯一标识(代替 ProviderType 枚举) - fn id(&self) -> &str; - - /// 显示名称 - fn display_name(&self) -> &str; - - /// 插件版本 - fn version(&self) -> &str; - - /// 插件描述 - fn description(&self) -> &str { "" } - - /// 默认目标标准协议 - fn target_protocol(&self) -> &str; - - /// 根据模型动态返回目标协议(用于 Antigravity 等多协议 Provider) - fn target_protocol_for_model(&self, model: &str) -> &str { - self.target_protocol() // 默认返回固定协议 - } - - // ========== 多认证方式支持 ========== - - /// 支持的认证方式(一个插件可支持多种) - /// 例如 Anthropic 同时支持 OAuth、API Key、第三方中转 - fn supported_auth_types(&self) -> Vec; - - /// 根据认证方式返回对应的凭证配置 Schema - fn credential_schema_for_auth(&self, auth_type: &str) -> serde_json::Value; - - /// 解析凭证配置(从 JSON 解析成插件内部结构) - fn parse_credential_config(&self, auth_type: &str, config: serde_json::Value) -> Result>; - - /// 创建凭证(从用户输入创建) - async fn create_credential(&self, auth_type: &str, config: serde_json::Value) -> Result; - - // ========== 模型能力 ========== - - /// 模型家族定义(用于 Mini/Pro/Max 分层) - fn model_families(&self) -> Vec; - - /// 获取支持的模型列表 - async fn list_models(&self) -> Result>; - - /// 检查是否支持某个模型 - fn supports_model(&self, model: &str) -> bool; - - // ========== 凭证管理 ========== - - /// 获取可用凭证 - async fn acquire_credential(&self, model: &str) -> Result; - - /// 释放凭证 - async fn release_credential(&self, credential_id: &str, result: UsageResult); - - /// 验证凭证有效性 - async fn validate_credential(&self, credential_id: &str) -> Result; - - /// 刷新 Token(OAuth 类型) - async fn refresh_token(&self, credential_id: &str) -> Result; - - // ========== 协议转换 ========== - - /// 将输入请求转换成标准协议 - async fn transform_request(&self, req: &mut ChatRequest) -> Result<()>; - - /// 将响应转换回来(如果需要) - async fn transform_response(&self, resp: &mut ChatResponse) -> Result<()>; - - // ========== 风控适配 ========== - - /// 应用特有的风控逻辑 - async fn apply_risk_control(&self, req: &mut ChatRequest, credential_id: &str) -> Result<()>; - - /// 解析特有的错误码 - fn parse_error(&self, status: u16, body: &str) -> Option; - - // ========== 插件配置(非凭证配置)========== - - /// 插件配置 Schema(用于 UI 动态生成表单) - fn plugin_config_schema(&self) -> serde_json::Value { serde_json::json!({}) } - - /// 更新插件配置 - async fn update_plugin_config(&mut self, config: serde_json::Value) -> Result<()> { Ok(()) } - - // ========== 生命周期 ========== - - /// 初始化插件 - async fn init(&mut self) -> Result<()>; - - /// 关闭插件 - async fn shutdown(&mut self) -> Result<()>; -} - -/// 认证方式信息 -pub struct AuthTypeInfo { - /// 认证方式 ID - pub id: String, // "oauth", "api_key", "third_party" - /// 显示名称 - pub display_name: String, // "OAuth 登录", "官方 API Key", "第三方中转" - /// 描述 - pub description: String, // "使用官方 OAuth 授权" - /// UI 分组(显示在哪个 Tab) - pub category: CredentialCategory, -} - -/// 凭证配置 trait(代替 CredentialData 枚举) -/// 每个插件自己定义凭证配置结构 -pub trait CredentialConfig: Send + Sync + Any { - fn as_any(&self) -> &dyn Any; - fn credential_type(&self) -> &str; // "oauth", "api_key", "third_party" -} -``` - -### 3.4 标准协议(动态注册) - -```rust -// ❌ 不再硬编码枚举 -// pub enum StandardProtocol { Anthropic, OpenAI, Gemini } - -// ✅ 改为字符串标识 + 注册表 -pub struct StandardProtocol(pub String); - -impl StandardProtocol { - // 内置常量(方便使用,但不限制扩展) - pub const ANTHROPIC: &'static str = "anthropic"; - pub const OPENAI: &'static str = "openai"; - pub const GEMINI: &'static str = "gemini"; - pub const QWEN: &'static str = "qwen"; // 通义千问 - pub const DOUBAO: &'static str = "doubao"; // 字节豆包 - pub const WENXIN: &'static str = "wenxin"; // 百度文心 - // ... 可继续扩展 -} - -/// 标准协议注册表 -pub struct StandardProtocolRegistry { - protocols: HashMap>, -} - -impl StandardProtocolRegistry { - pub fn new() -> Self { - let mut registry = Self::default(); - - // 内置协议处理器 - registry.register("anthropic", Arc::new(AnthropicProtocolHandler::new())); - registry.register("openai", Arc::new(OpenAIProtocolHandler::new())); - registry.register("gemini", Arc::new(GeminiProtocolHandler::new())); - - // 中国厂商(目前大多兼容 OpenAI) - registry.register("qwen", Arc::new(OpenAICompatHandler::new("qwen"))); - registry.register("doubao", Arc::new(OpenAICompatHandler::new("doubao"))); - - registry - } - - /// 注册新协议(支持运行时扩展) - pub fn register(&mut self, id: &str, handler: Arc); - - /// 获取协议处理器 - pub fn get(&self, id: &str) -> Option>; - - /// 列出所有已注册协议 - pub fn list(&self) -> Vec; -} - -/// 协议处理器 trait -#[async_trait] -pub trait ProtocolHandler: Send + Sync { - /// 协议 ID - fn id(&self) -> &str; - - /// 显示名称 - fn display_name(&self) -> &str; - - /// 请求格式化(转换成该协议的请求格式) - fn format_request(&self, req: &ChatRequest) -> Result; - - /// 响应解析 - fn parse_response(&self, resp: &serde_json::Value) -> Result; - - /// 流式响应解析 - fn parse_stream_chunk(&self, chunk: &[u8]) -> Result>; - - /// 错误解析 - fn parse_error(&self, status: u16, body: &str) -> ProviderError; -} -``` - -### 3.5 现有系统代码分析 - -#### 3.5.1 现有硬编码枚举(需要消除) - -**ProviderType 枚举(11种)** - `src-tauri/src/lib.rs:71-91`: -```rust -pub enum ProviderType { - Kiro, // AWS 凭证同步 - Gemini, // Google Gemini OAuth - Qwen, // 阿里通义千问 OAuth - OpenAI, // OpenAI API Key - Claude, // Anthropic API Key - Antigravity, // Gemini 3 Pro - Vertex, // Google Vertex AI - GeminiApiKey,// Gemini API Key - Codex, // OpenAI OAuth - ClaudeOAuth, // Anthropic OAuth - IFlow, // IFlow -} -``` - -**ApiProviderType 枚举(10种)** - `src-tauri/src/database/dao/api_key_provider.rs`: -```rust -pub enum ApiProviderType { - Openai, OpenaiResponse, Anthropic, Gemini, - AzureOpenai, Vertexai, AwsBedrock, Ollama, - NewApi, Gateway, -} -``` - -**问题**:两套枚举并存,新增 Provider 需要修改多处代码。 - -#### 3.5.2 现有凭证数据结构(过于简单) - -**CredentialData** - `src-tauri/src/credential/types.rs:73-88`: -```rust -pub enum CredentialData { - OAuth { - access_token: String, - refresh_token: Option, - expires_at: Option>, - }, - ApiKey { - key: String, - base_url: Option, - }, -} -``` - -**问题**:只有 2 种类型,无法支持: -- AWS 凭证(Access Key + Secret Key + Region) -- Azure 凭证(Endpoint + API Version + Deployment) -- 复杂配置(订阅类型、限流、额度等) - -#### 3.5.3 现有数据库表结构 - -**表 1: provider_pool_credentials**(新凭证池): -```sql -uuid, provider_type, credential_data (JSON), -name, is_healthy, is_disabled, -check_health, check_model_name, not_supported_models, -usage_count, error_count, last_used, last_error_time, -cached_access_token, cached_refresh_token, token_expiry_time, -source, proxy_url, created_at, updated_at -``` - -**表 2: api_key_providers**(旧 API Key 系统): -```sql -id, name, type, api_host, is_system, group_name, -enabled, sort_order, api_version, project, location, region -``` - -#### 3.5.4 现有 UI 结构 - -``` -ProviderPoolPage -├── Tab: OAuth(卡片布局) -│ └── CredentialCard × N -├── Tab: API Key(左右分栏) -│ ├── 左栏: ProviderList(60+ 系统预设) -│ └── 右栏: ProviderSetting + ApiKeyList -└── Tab: Config - └── VertexAI / Amp 配置 -``` - -#### 3.5.5 OAuth Provider 插件架构(参考 MachineIdTool) - -**核心设计理念**: - -- **每个插件实现自己的 UI** - 包括凭证管理、配置界面、状态展示等 -- **ProxyCast 作为入口和注册管理中心** - 提供插件容器、协议路由、注册表管理 -- **插件完全自治** - UI、业务逻辑、风控策略都在插件内部实现 - -**插件架构设计**:OAuth Provider 采用与 MachineIdTool 一致的独立项目形式 - -``` -┌─────────────────────────────────────────────────────────────────────────┐ -│ OAuth Provider 插件架构 │ -├─────────────────────────────────────────────────────────────────────────┤ -│ │ -│ 每个 OAuth Provider 是独立的项目/仓库: │ -│ │ -│ github.com/aiclientproxy/kiro-provider/ │ -│ ├── plugin/ │ -│ │ ├── plugin.json # 插件元数据 │ -│ │ └── config.json # 插件配置 │ -│ ├── src-tauri/src/ │ -│ │ ├── lib.rs # 插件入口 │ -│ │ ├── commands.rs # Tauri 命令 │ -│ │ ├── service.rs # 核心服务逻辑 │ -│ │ └── models.rs # 数据模型 │ -│ └── src/ # 【必须】插件前端 UI │ -│ ├── components/ # UI 组件 │ -│ │ ├── CredentialList.tsx # 凭证列表 │ -│ │ ├── CredentialForm.tsx # 凭证添加/编辑表单 │ -│ │ ├── SettingsPanel.tsx # 插件设置面板 │ -│ │ └── StatusCard.tsx # 状态卡片 │ -│ ├── hooks/ # 插件专用 hooks │ -│ └── index.tsx # 插件 UI 入口 │ -│ │ -└─────────────────────────────────────────────────────────────────────────┘ -``` - -**ProxyCast 与插件的职责划分**: - -``` -┌─────────────────────────────────────────────────────────────────────────┐ -│ 职责划分 │ -├─────────────────────────────────────────────────────────────────────────┤ -│ │ -│ ProxyCast 主应用(入口 + 注册中心): │ -│ ├── 插件容器 (Plugin Host) │ -│ │ ├── 加载插件 UI 组件 │ -│ │ ├── 提供插件挂载点 (mounting points) │ -│ │ └── 插件生命周期管理 │ -│ ├── 注册管理中心 │ -│ │ ├── OAuthProviderRegistry (插件注册表) │ -│ │ ├── 插件发现与安装 │ -│ │ └── 插件启用/禁用控制 │ -│ ├── 协议路由层 │ -│ │ ├── 请求路由到对应插件 │ -│ │ └── 响应协议转换 │ -│ └── 公共基础设施 │ -│ ├── 数据库连接 │ -│ ├── HTTP 客户端 │ -│ └── 加密存储 │ -│ │ -│ ───────────────────────────────────────────────────────────────────── │ -│ │ -│ 插件(自治单元): │ -│ ├── 【必须】自己的 UI │ -│ │ ├── 凭证管理界面 │ -│ │ ├── 配置界面 │ -│ │ └── 状态展示 │ -│ ├── 业务逻辑 │ -│ │ ├── Token 刷新 │ -│ │ ├── 凭证验证 │ -│ │ └── 协议转换 │ -│ └── 风控策略 │ -│ ├── Machine ID 管理 │ -│ ├── 限流检测 │ -│ └── 冷却期控制 │ -│ │ -└─────────────────────────────────────────────────────────────────────────┘ -``` - -**plugin.json 结构(参考 MachineIdTool)**: - -```json -{ - "name": "kiro-provider", - "version": "1.0.0", - "description": "Kiro (AWS CodeWhisperer) OAuth Provider - 支持 Claude 模型", - "author": "ProxyCast Team", - "homepage": "https://github.com/aiclientproxy/kiro-provider", - "license": "MIT", - - "plugin_type": "oauth_provider", - "entry": "kiro-provider-cli", - "min_proxycast_version": "1.0.0", - - "provider": { - "id": "kiro", - "display_name": "Kiro (CodeWhisperer)", - "target_protocol": "anthropic", - "supported_models": ["claude-*"], - "auth_type": "oauth", - "credential_schema": { - "type": "object", - "required": ["creds_file_path"], - "properties": { - "creds_file_path": { - "type": "string", - "title": "凭证文件路径", - "description": "AWS SSO 凭证文件" - } - } - } - }, - - "binary": { - "binary_name": "kiro-provider-cli", - "github_owner": "aiclientproxy", - "github_repo": "kiro-provider", - "platform_binaries": { - "macos-arm64": "kiro-provider-aarch64-apple-darwin", - "macos-x64": "kiro-provider-x86_64-apple-darwin", - "linux-x64": "kiro-provider-x86_64-unknown-linux-gnu", - "windows-x64": "kiro-provider-x86_64-pc-windows-msvc.exe" - }, - "checksum_file": "checksums.txt" - }, - - "ui": { - "surfaces": ["oauth_providers"], - "icon": "Cloud", - "title": "Kiro Provider" - } -} -``` - -**config.json 结构**: - -```json -{ - "enabled": true, - "timeout_ms": 30000, - "settings": { - "risk_control": { - "machine_id_rotation": true, - "version_spoofing": true - } - } -} -``` - -**OAuth Provider 插件列表(每个独立仓库)**: - -| 插件名 | 仓库 | plugin_type | 复杂度 | -|--------|------|-------------|--------| -| kiro-provider | aiclientproxy/kiro-provider | oauth_provider | 🔴 高 | -| antigravity-provider | aiclientproxy/antigravity-provider | oauth_provider | 🔴 高 | -| claude-oauth-provider | aiclientproxy/claude-oauth-provider | oauth_provider | 🟡 中 | -| codex-provider | aiclientproxy/codex-provider | oauth_provider | 🟡 中 | -| gemini-oauth-provider | aiclientproxy/gemini-oauth-provider | oauth_provider | 🟡 中 | -| qwen-provider | aiclientproxy/qwen-provider | oauth_provider | 🟢 低 | -| iflow-provider | aiclientproxy/iflow-provider | oauth_provider | 🟢 低 | - -#### 3.5.6 ProxyCast 插件宿主架构 - -**核心理念**:ProxyCast 只提供入口和容器,具体 UI 由各插件自己实现 - -**ProxyCast 主应用 UI 结构**: - -``` -ProviderPoolPage -├── Tab: OAuth 插件 -│ ├── 插件导航栏(顶部) -│ │ ├── [+ 安装插件] 按钮 -│ │ └── 已安装插件列表 -│ │ ├── 🔌 Kiro Provider ● 已启用 [打开] -│ │ ├── 🔌 Antigravity ● 已启用 [打开] -│ │ ├── 🔌 Claude OAuth ○ 已禁用 [打开] -│ │ └── ... -│ │ -│ └── 插件 UI 挂载区域(主体) -│ └── -│ │ -│ └── 【由插件自己渲染的 UI】 -│ ├── 凭证管理界面 -│ ├── 配置面板 -│ └── 状态展示 -│ -├── Tab: API Key(保持不变) -│ -└── Tab: Config(保持不变) -``` - -**插件 UI 加载机制**: - -``` -┌─────────────────────────────────────────────────────────────────────────┐ -│ 插件 UI 加载流程 │ -├─────────────────────────────────────────────────────────────────────────┤ -│ │ -│ 1. ProxyCast 启动 │ -│ │ │ -│ ▼ │ -│ 2. 扫描 ~/.proxycast/plugins/ 目录 │ -│ │ │ -│ ▼ │ -│ 3. 读取每个插件的 plugin.json │ -│ ├── 获取 ui.entry 字段(如 "dist/index.js") │ -│ └── 获取 ui.surfaces 字段(如 ["oauth_providers"]) │ -│ │ │ -│ ▼ │ -│ 4. 注册到 PluginUIRegistry │ -│ │ │ -│ ▼ │ -│ 5. 用户点击某个插件时 │ -│ │ │ -│ ▼ │ -│ 6. PluginContainer 动态加载插件 UI │ -│ ├── 加载插件的 JavaScript/CSS │ -│ ├── 创建 iframe 或 Web Component 容器 │ -│ └── 传入 ProxyCast SDK (数据库访问、HTTP 客户端等) │ -│ │ │ -│ ▼ │ -│ 7. 插件 UI 渲染在容器中 │ -│ │ -└─────────────────────────────────────────────────────────────────────────┘ -``` - -**plugin.json UI 配置扩展**: - -```json -{ - "ui": { - "surfaces": ["oauth_providers"], - "icon": "Cloud", - "title": "Kiro Provider", - "entry": "dist/index.js", // 插件 UI 入口文件 - "styles": "dist/styles.css", // 插件样式文件 - "default_width": 800, - "default_height": 600, - "permissions": [ // 插件需要的权限 - "database:read", - "database:write", - "http:request", - "crypto:encrypt" - ] - } -} -``` - -**ProxyCast SDK(供插件使用)**: - -```typescript -// ProxyCast 提供给插件的 SDK -interface ProxyCastPluginSDK { - // 数据库操作 - database: { - query(sql: string, params?: any[]): Promise; - execute(sql: string, params?: any[]): Promise; - }; - - // HTTP 客户端 - http: { - request(url: string, options?: RequestOptions): Promise; - }; - - // 加密存储 - crypto: { - encrypt(data: string): Promise; - decrypt(data: string): Promise; - }; - - // 通知 - notification: { - success(message: string): void; - error(message: string): void; - info(message: string): void; - }; - - // 插件间通信 - events: { - emit(event: string, data: any): void; - on(event: string, callback: (data: any) => void): void; - }; -} -``` - -**插件 UI 示例(Kiro Provider)**: - -```tsx -// kiro-provider/src/index.tsx -import { ProxyCastPluginSDK } from '@proxycast/plugin-sdk'; - -interface PluginProps { - sdk: ProxyCastPluginSDK; - pluginId: string; -} - -export default function KiroProviderUI({ sdk, pluginId }: PluginProps) { - const [credentials, setCredentials] = useState([]); - - useEffect(() => { - // 使用 ProxyCast SDK 查询数据 - sdk.database.query( - 'SELECT * FROM plugin_credentials WHERE plugin_id = ?', - [pluginId] - ).then(setCredentials); - }, []); - - return ( -
- - - -
- ); -} -``` - -**ProxyCast 提供的公共功能**(非 UI): - -| 功能 | ProxyCast 提供 | 插件实现 | -|------|--------------|---------| -| 插件安装/卸载 | ✅ | - | -| 插件启用/禁用 | ✅ | - | -| 插件更新检查 | ✅ | - | -| UI 容器/挂载点 | ✅ | - | -| 凭证管理 UI | - | ✅ 各插件自己实现 | -| 配置界面 | - | ✅ 各插件自己实现 | -| 状态展示 | - | ✅ 各插件自己实现 | -| Token 刷新逻辑 | - | ✅ 各插件自己实现 | -| 风控策略 | - | ✅ 各插件自己实现 | - -**插件管理功能(ProxyCast 实现)**: - -| 功能 | 说明 | -|------|------| -| 安装插件 | 从 GitHub Release 下载或本地文件安装 | -| 检查更新 | 比较 GitHub Release 版本,提示更新 | -| 启用/禁用 | 修改 config.json 的 enabled 字段 | -| 卸载插件 | 删除插件文件和凭证数据(需确认)| -| 权限管理 | 控制插件可访问的 SDK 能力 | - -**插件安装流程**: - -``` -1. 用户点击 [+ 安装插件] - │ - ▼ -2. 选择安装方式 - ├── 从 GitHub: 输入仓库地址 (aiclientproxy/kiro-provider) - ├── 从文件: 选择 plugin.json - └── 内置列表: 选择预置插件 - │ - ▼ -3. 下载插件 - ├── 解析 plugin.json - ├── 根据平台下载对应二进制 - ├── 下载 UI 资源 (dist/index.js, dist/styles.css) - ├── 校验 checksum - └── 安装到 ~/.proxycast/plugins/{plugin-name}/ - │ - ▼ -4. 注册插件 - ├── 加载到 OAuthProviderRegistry (后端) - ├── 加载到 PluginUIRegistry (前端) - ├── 创建 config.json - └── 显示在插件列表 - │ - ▼ -5. 用户点击插件 - └── 加载插件自己的 UI -``` - -#### 3.5.7 插件化改造目标 - -``` -┌─────────────────────────────────────────────────────────────────────────┐ -│ 现有硬编码架构 → 插件化架构 │ -├─────────────────────────────────────────────────────────────────────────┤ -│ ProviderType 枚举 (11种) → CredentialProviderRegistry (动态注册) │ -│ ApiProviderType 枚举 (10种) → 合并到 CredentialProviderPlugin │ -│ CredentialData 枚举 (2种) → 插件自定义 CredentialConfig trait │ -│ 硬编码配置字段 → 插件返回 JSON Schema │ -├─────────────────────────────────────────────────────────────────────────┤ -│ 新增 Provider: │ -│ - 现有: 修改 2 个枚举 + 多处 match │ -│ - 插件化: 实现 trait + 注册,核心代码不变 │ -└─────────────────────────────────────────────────────────────────────────┘ -``` - -#### 3.5.8 插件化凭证配置设计 - -**核心理念**:凭证配置由插件自己定义,通过 JSON Schema 动态生成前端表单 - -```rust -/// 插件返回 JSON Schema,前端动态渲染表单 -pub trait CredentialProviderPlugin { - /// 返回凭证配置的 JSON Schema - fn credential_schema(&self) -> serde_json::Value; - - /// 验证并解析凭证配置 - fn parse_credential(&self, config: serde_json::Value) -> Result>; -} -``` - -**示例:现有 ProviderType 迁移为插件** - -| 现有类型 | 插件 ID | 凭证类型 | JSON Schema 定义的字段 | -|---------|--------|---------|----------------------| -| Kiro | `kiro` | OAuth | `creds_file_path` | -| ClaudeOAuth | `claude_oauth` | OAuth | `creds_file_path` | -| Claude | `claude_api` | ApiKey | `key`, `base_url` | -| OpenAI | `openai_api` | ApiKey | `key`, `base_url` | -| Codex | `codex` | OAuth | `creds_file_path`, `api_base_url` | -| Gemini | `gemini_oauth` | OAuth | `creds_file_path`, `project_id` | -| GeminiApiKey | `gemini_api` | ApiKey | `key`, `base_url`, `excluded_models` | -| Vertex | `vertex` | ApiKey | `key`, `base_url`, `project`, `location` | -| Antigravity | `antigravity` | OAuth | `creds_file_path`, `project_id` | -| Qwen | `qwen` | OAuth | `creds_file_path` | -| IFlow | `iflow` | OAuth/Cookie | `creds_file_path` | - -**示例:现有 ApiProviderType 迁移为插件** - -| 现有类型 | 插件 ID | JSON Schema 定义的字段 | -|---------|--------|----------------------| -| AzureOpenai | `azure_openai` | `api_host`, `api_key`, `api_version` | -| AwsBedrock | `aws_bedrock` | `api_key`, `region` | -| Vertexai | `vertexai` | `api_key`, `project`, `location` | - -#### 3.5.9 插件实现示例 - -**Kiro Provider(OAuth + 风控)**: - -```rust -pub struct KiroProvider { - credential_pool: CredentialPool, - machine_id_cache: HashMap, -} - -impl CredentialProviderPlugin for KiroProvider { - fn id(&self) -> &str { "kiro" } - fn display_name(&self) -> &str { "Kiro (AWS CodeWhisperer)" } - fn target_protocol(&self) -> &str { "anthropic" } - fn ui_category(&self) -> CredentialCategory { CredentialCategory::OAuth } - - fn credential_schema(&self) -> serde_json::Value { - serde_json::json!({ - "type": "object", - "required": ["creds_file_path"], - "properties": { - "creds_file_path": { - "type": "string", - "title": "凭证文件路径", - "description": "AWS SSO 凭证文件" - } - } - }) - } - - fn model_families(&self) -> Vec { - vec![ - ModelFamily { name: "opus", pattern: "claude-opus-*" }, - ModelFamily { name: "sonnet", pattern: "claude-sonnet-*" }, - ModelFamily { name: "haiku", pattern: "claude-*-haiku" }, - ] - } - - async fn apply_risk_control(&self, req: &mut ChatRequest, cred_id: &str) -> Result<()> { - // Kiro 特有风控:Machine ID、系统信息、版本号 - let machine_id = self.get_or_generate_machine_id(cred_id); - req.headers.insert("X-Amz-Machine-Id", machine_id); - req.headers.insert("X-Amz-Os", get_os_info()); - req.headers.insert("X-Kiro-Version", KIRO_VERSION); - Ok(()) - } -} -``` - -**Azure OpenAI Provider(API Key + 特殊配置)**: - -```rust -impl CredentialProviderPlugin for AzureOpenAIProvider { - fn id(&self) -> &str { "azure_openai" } - fn display_name(&self) -> &str { "Azure OpenAI" } - fn target_protocol(&self) -> &str { "openai" } - fn ui_category(&self) -> CredentialCategory { CredentialCategory::ApiKey } - - fn credential_schema(&self) -> serde_json::Value { - serde_json::json!({ - "type": "object", - "required": ["api_host", "api_key", "api_version"], - "properties": { - "api_host": { - "type": "string", - "title": "Azure Endpoint", - "description": "https://your-resource.openai.azure.com" - }, - "api_key": { "type": "string", "title": "API Key" }, - "api_version": { - "type": "string", - "title": "API 版本", - "default": "2024-02-01" - } - } - }) - } - - async fn acquire_credential(&self, model: &str) -> Result { - let cred = self.credential_pool.acquire().await?; - let config: AzureConfig = serde_json::from_value(cred.config)?; - - // Azure 特殊的 URL 构建 - let url = format!( - "{}/openai/deployments/{}/chat/completions?api-version={}", - config.api_host, model, config.api_version - ); - - Ok(AcquiredCredential { - id: cred.id, - base_url: url, - headers: vec![("api-key", config.api_key)], - }) - } -} -``` - -### 3.6 凭证分组(用于 UI) - -```rust -/// 凭证分组(用于 UI Tab 展示) -/// 保留枚举,因为 UI Tab 结构相对稳定 -#[derive(Clone, Copy, Debug)] -pub enum CredentialCategory { - OAuth, // OAuth 凭证 Tab - ApiKey, // API Key Tab - Other, // 其他配置 Tab(第三方中转、Cookie 等) -} -``` - -### 3.7 认证类型 - -```rust -/// 认证类型(内置常见类型,但不限制扩展) -#[derive(Clone, Debug)] -pub enum AuthType { - /// API Key 认证 - ApiKey { - header_name: String, // "Authorization", "x-api-key" - prefix: Option, // "Bearer ", "sk-" - }, - /// OAuth 2.0 - OAuth { - token_url: String, - client_id: Option, - client_secret: Option, - }, - /// Cookie 认证 - Cookie { - cookie_name: String, - }, - /// 自定义头部 - CustomHeaders(HashMap), - /// 无认证 - None, -} -``` - -### 3.8 插件注册表 - -```rust -pub struct CredentialProviderRegistry { - providers: HashMap>, - model_index: HashMap, // model -> provider_id - plugins_dir: PathBuf, // ~/.proxycast/plugins/ -} - -impl CredentialProviderRegistry { - pub fn new(plugins_dir: PathBuf) -> Self { - Self { - providers: HashMap::new(), - model_index: HashMap::new(), - plugins_dir, - } - } - - /// 从外部目录加载所有插件 - pub async fn load_plugins(&mut self) -> Result<()> { - // 扫描 ~/.proxycast/plugins/ 目录 - for entry in fs::read_dir(&self.plugins_dir)? { - let plugin_dir = entry?.path(); - if plugin_dir.is_dir() { - self.load_plugin(&plugin_dir).await?; - } - } - Ok(()) - } - - /// 加载单个插件 - async fn load_plugin(&mut self, plugin_dir: &Path) -> Result<()> { - // 1. 读取 plugin.json - let manifest_path = plugin_dir.join("plugin.json"); - let manifest: PluginManifest = serde_json::from_str( - &fs::read_to_string(&manifest_path)? - )?; - - // 2. 检查 plugin_type 是否为 oauth_provider - if manifest.plugin_type != "oauth_provider" { - return Ok(()); // 跳过非 OAuth Provider 插件 - } - - // 3. 加载插件二进制 - let binary_path = plugin_dir.join("bin").join(&manifest.binary.binary_name); - let plugin = ExternalOAuthPlugin::new(binary_path, manifest)?; - - // 4. 注册到注册表 - self.register(Arc::new(plugin)); - Ok(()) - } - - /// 注册插件 - pub fn register(&mut self, provider: Arc); - - /// 根据模型查找 Provider - pub fn find_by_model(&self, model: &str) -> Option>; - - /// 获取所有已启用的 Provider - pub fn get_enabled(&self) -> Vec>; - - /// 获取某个 Provider - pub fn get(&self, id: &str) -> Option>; - - /// 安装新插件(从 GitHub 或本地文件) - pub async fn install_plugin(&mut self, source: PluginSource) -> Result<()>; - - /// 卸载插件 - pub async fn uninstall_plugin(&mut self, plugin_id: &str) -> Result<()>; - - /// 检查插件更新 - pub async fn check_updates(&self) -> Result>; -} - -/// 外部 OAuth 插件(通过二进制调用) -pub struct ExternalOAuthPlugin { - manifest: PluginManifest, - binary_path: PathBuf, - config: PluginConfig, -} - -impl CredentialProviderPlugin for ExternalOAuthPlugin { - // 通过调用外部二进制实现 trait 方法 - // 使用 JSON-RPC 或 stdin/stdout 通信 -} -``` - ---- - -## 四、OAuth 凭证插件迁移清单 - -### 4.1 需要插件化的 ProviderType(仅 OAuth) - -根据现有代码 `src-tauri/src/lib.rs`,需要迁移 **8 个 OAuth 类型**: - -| 现有枚举值 | 插件 ID | 认证方式 | 目标协议 | 复杂度 | -|-----------|--------|---------|---------|--------| -| `Kiro` | `kiro` | OAuth (creds_file) | anthropic | 🔴 高 | -| `Antigravity` | `antigravity` | OAuth (creds_file, project_id) | 动态* | 🔴 高 | -| `ClaudeOAuth` | `claude_oauth` | OAuth (creds_file) | anthropic | 🟡 中 | -| `Codex` | `codex` | OAuth (creds_file) | openai | 🟡 中 | -| `Gemini` | `gemini_oauth` | OAuth (creds_file, project_id) | gemini | 🟡 中 | -| `Qwen` | `qwen` | OAuth (creds_file) | openai | 🟢 低 | -| `IFlow` | `iflow` | OAuth/Cookie | openai | 🟢 低 | - -> *Antigravity 根据模型动态选择协议:`claude-*` → anthropic, 其他 → gemini - -### 4.2 不需要插件化的类型(保持现有) - -**API Key 类型 - 继续使用现有 `api_key_providers` 系统**: - -| 现有枚举值 | 处理方式 | 原因 | -|-----------|---------|------| -| `Claude` | 保持现有 | 简单 API Key,已有系统支持 | -| `OpenAI` | 保持现有 | 简单 API Key,已有系统支持 | -| `GeminiApiKey` | 保持现有 | 简单 API Key,已有系统支持 | -| `Vertex` | 保持现有 | 已有配置字段 (project, location) | - -**ApiProviderType - 完全不变**: -- 60+ 系统预设 Provider 继续使用 -- 用户自定义 Provider 功能继续使用 -- `api_key_providers` + `api_keys` 表结构不变 - -### 4.3 复杂度分析 - -**🔴 高复杂度**: -- `kiro`: Machine ID 生成、系统指纹、版本号伪装、特殊头部 -- `antigravity`: 动态协议选择、模型别名映射、Safety Settings - -**🟡 中复杂度**: -- `claude_oauth`, `codex`, `gemini_oauth`: Token 刷新、凭证文件解析 - -**🟢 低复杂度**: -- `qwen`, `iflow`: 标准 OAuth 流程 - ---- - -## 五、迁移方案 - -### 5.1 OAuth 凭证代码映射 - -**迁移策略**:将现有代码迁移到独立的 GitHub 仓库 - -| 现有模块 | 迁移目标(独立仓库) | 说明 | -|---------|---------------------|------| -| `providers/kiro.rs` | `aiclientproxy/kiro-provider` | 提取风控逻辑 + UI | -| `providers/claude_oauth.rs` | `aiclientproxy/claude-oauth-provider` | Token 刷新 + UI | -| `providers/codex.rs` | `aiclientproxy/codex-provider` | OpenAI OAuth + UI | -| `providers/gemini.rs` | `aiclientproxy/gemini-oauth-provider` | Google OAuth + UI | -| `providers/antigravity.rs` | `aiclientproxy/antigravity-provider` | 动态协议 + UI | -| `providers/qwen.rs` | `aiclientproxy/qwen-provider` | + UI | -| `providers/iflow.rs` | `aiclientproxy/iflow-provider` | + UI | -| `converter/openai_to_cw.rs` | `kiro-provider` 内部 | 协议转换逻辑 | -| `translator/kiro/*` | `kiro-provider` 内部 | 请求/响应转换 | - -**每个独立仓库包含**: -- 后端 Rust 代码(凭证管理、协议转换、风控) -- 前端 React UI(凭证列表、配置表单、状态展示) -- plugin.json 元数据 -- GitHub Actions 自动构建发布 - -### 5.2 保持不变的模块 - -| 现有模块 | 处理方式 | 原因 | -|---------|---------|------| -| `database/dao/api_key_provider.rs` | **不变** | API Key 系统继续使用 | -| `database/system_providers.rs` | **不变** | 60+ 系统预设 | -| `providers/openai_custom.rs` | **不变** | API Key 方式 | -| `credential/pool.rs` | **复用** | 作为插件内部实现 | -| `credential/balancer.rs` | **复用** | | -| `credential/health.rs` | **复用** | | - -### 5.3 目录结构 - -**ProxyCast 主项目结构**(入口 + 注册中心): - -``` -src-tauri/src/ -├── credential/ -│ ├── mod.rs -│ ├── types.rs # 保留,通用类型 -│ ├── pool.rs # 保留,复用(供插件使用) -│ ├── balancer.rs # 保留,复用 -│ ├── health.rs # 保留,复用 -│ ├── quota.rs # 保留,复用 -│ │ -│ ├── plugin.rs # OAuthProviderPlugin trait (新增) -│ └── registry.rs # OAuthProviderRegistry (新增,管理外部插件) -│ -├── plugin/ -│ ├── mod.rs -│ ├── loader.rs # 插件加载器(从外部目录加载) -│ ├── host.rs # 插件宿主(生命周期管理) -│ └── sdk.rs # ProxyCast SDK(供插件调用) -│ -├── database/ -│ └── dao/ -│ └── api_key_provider.rs # 保持不变!60+ 系统预设 -│ -├── converter/ # 保留 -│ └── ... -│ -└── providers/ # 渐进式清理 - └── ... # OAuth 相关代码迁移到独立插件项目 -``` - -**前端目录结构**(插件容器): - -``` -src/ -├── components/ -│ └── plugin/ -│ ├── PluginContainer.tsx # 插件 UI 容器 -│ ├── PluginLoader.tsx # 插件 JS/CSS 加载 -│ └── PluginRegistry.tsx # 前端插件注册表 -│ -└── pages/ - └── ProviderPool/ - └── OAuthPluginTab.tsx # OAuth 插件列表 + 挂载点 -``` - -**外部插件安装目录**: - -``` -~/.proxycast/plugins/ -├── kiro-provider/ # 独立插件项目 -│ ├── plugin.json # 插件元数据 -│ ├── config.json # 插件配置 -│ ├── bin/ -│ │ └── kiro-provider-cli # 后端二进制 -│ └── dist/ -│ ├── index.js # 插件 UI 入口 -│ └── styles.css # 插件样式 -│ -├── antigravity-provider/ -│ └── ... -│ -├── claude-oauth-provider/ -│ └── ... -│ -└── ... (其他 OAuth Provider 插件) -``` - -**插件项目结构**(独立仓库,参考 MachineIdTool): - -``` -github.com/aiclientproxy/kiro-provider/ -├── plugin/ -│ ├── plugin.json # 插件元数据 -│ └── config.json # 默认配置 -├── src-tauri/src/ # 后端 Rust 代码 -│ ├── lib.rs -│ ├── commands.rs -│ ├── service.rs -│ └── models.rs -├── src/ # 前端 UI (React) -│ ├── components/ -│ │ ├── CredentialList.tsx -│ │ ├── CredentialForm.tsx -│ │ └── SettingsPanel.tsx -│ └── index.tsx -└── .github/ - └── workflows/ - └── release.yml # 自动构建发布 -``` - -### 5.4 数据库迁移 - -**新增表**: -```sql --- 插件配置表 -CREATE TABLE credential_provider_plugins ( - id TEXT PRIMARY KEY, -- "kiro", "anthropic", etc. - display_name TEXT NOT NULL, - version TEXT NOT NULL, - enabled INTEGER DEFAULT 1, - config TEXT, -- JSON 配置 - created_at INTEGER NOT NULL, - updated_at INTEGER NOT NULL -); - --- 插件凭证关联表(替代现有的 provider_pool_credentials) -CREATE TABLE plugin_credentials ( - id TEXT PRIMARY KEY, - plugin_id TEXT NOT NULL, - credential_data TEXT NOT NULL, -- 加密的凭证数据 - status TEXT DEFAULT 'active', -- active/cooldown/unhealthy/disabled - stats TEXT, -- JSON 统计数据 - created_at INTEGER NOT NULL, - updated_at INTEGER NOT NULL, - FOREIGN KEY (plugin_id) REFERENCES credential_provider_plugins(id) -); -``` - ---- - -## 六、请求处理流程 - -### 6.1 新流程 - -``` -客户端请求 - │ - ▼ -┌─────────────────────────────────────┐ -│ 1. 路由解析 │ -│ - 识别目标 Provider │ -│ - 识别输入协议 │ -└─────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────┐ -│ 2. 插件注册表查找 │ -│ CredentialProviderRegistry │ -│ .find_by_model(model) │ -└─────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────┐ -│ 3. Provider 插件处理 │ -│ ┌─────────────────────────────┐ │ -│ │ acquire_credential() │ │ -│ │ transform_request() │ │ -│ │ apply_risk_control() │ │ -│ └─────────────────────────────┘ │ -└─────────────────────────────────────┘ - │ - ▼ (标准协议: Anthropic/OpenAI/Gemini) - │ -┌─────────────────────────────────────┐ -│ 4. 输出适配(如需要) │ -│ - Anthropic API Output │ -│ - Claude Code Protocol Output │ -└─────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────┐ -│ 5. HTTP 请求发送 │ -└─────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────┐ -│ 6. 响应处理 │ -│ - transform_response() │ -│ - release_credential() │ -│ - 错误处理和重试 │ -└─────────────────────────────────────┘ -``` - -### 6.2 处理管道集成 - -```rust -// 修改 ProviderStep,使用插件注册表 -impl ProviderStep { - async fn execute(&self, ctx: &mut RequestContext, payload: &mut Value) -> Result<()> { - // 1. 获取目标 Provider 插件 - let provider = self.registry - .find_by_model(&ctx.model) - .ok_or(Error::NoProviderFound)?; - - // 2. 获取凭证 - let credential = provider.acquire_credential(&ctx.model).await?; - - // 3. 转换请求 - provider.transform_request(payload).await?; - - // 4. 应用风控 - provider.apply_risk_control(payload, &credential).await?; - - // 5. 发送请求 - let result = self.http_client.send(payload, &credential).await; - - // 6. 处理结果 - match &result { - Ok(resp) => { - provider.transform_response(resp).await?; - provider.release_credential(&credential.id, UsageResult::Success).await; - } - Err(e) => { - let error = provider.parse_error(e.status, &e.body); - provider.release_credential(&credential.id, UsageResult::Error(error)).await; - } - } - - result - } -} -``` - ---- - -## 七、与现有插件系统集成 - -### 7.1 关系设计 - -``` -┌─────────────────────────────────────────────────────────────┐ -│ PluginManager │ -│ (管理通用插件: 请求修改、响应修改、监控等) │ -└─────────────────────────────────────────────────────────────┘ - │ - │ 并行 - │ -┌─────────────────────────────────────────────────────────────┐ -│ CredentialProviderRegistry │ -│ (管理凭证 Provider 插件: Kiro, Anthropic, OpenAI 等) │ -└─────────────────────────────────────────────────────────────┘ -``` - -### 7.2 共享能力 - -- **PluginContext**:共享请求上下文 -- **超时隔离**:复用 PluginManager 的超时机制 -- **UI 系统**:CredentialProviderPlugin 可选实现 PluginUI trait - -```rust -// 可选:实现 PluginUI 以提供配置界面 -impl PluginUI for KiroProvider { - fn get_surfaces(&self) -> Vec { - vec![ - SurfaceDefinition { - id: "kiro_credentials", - title: "Kiro 凭证管理", - components: self.build_credential_list_ui(), - } - ] - } -} -``` - ---- - -## 八、实施计划 - -### Phase 1: ProxyCast 插件宿主架构 - -**目标**:在 ProxyCast 中实现插件宿主和 SDK - -**后端任务**: -1. 定义 `CredentialProviderPlugin` trait -2. 实现 `CredentialProviderRegistry`(从外部目录加载) -3. 实现 `PluginLoader`(加载插件二进制) -4. 实现 `ProxyCast SDK`(供插件调用的接口) -5. 创建数据库迁移脚本 - -**前端任务**: -1. 实现 `PluginContainer` 组件(加载插件 UI) -2. 实现 `PluginLoader`(动态加载 JS/CSS) -3. 实现 `OAuthPluginTab`(插件列表 + 挂载点) -4. 定义 `@proxycast/plugin-sdk` TypeScript 接口 - -**产出**: -- `src-tauri/src/credential/plugin.rs` -- `src-tauri/src/credential/registry.rs` -- `src-tauri/src/plugin/loader.rs` -- `src-tauri/src/plugin/sdk.rs` -- `src/components/plugin/PluginContainer.tsx` -- `src/components/plugin/PluginLoader.tsx` - -### Phase 2: 核心 OAuth Provider 独立仓库 - -**目标**:创建最复杂的 OAuth Provider 独立项目 - -**优先级**: -1. **kiro-provider** - 最复杂,有风控逻辑、Machine ID、版本伪装 -2. **antigravity-provider** - 动态协议选择(claude-* → Anthropic,gemini-* → Gemini) - -**每个仓库任务**: -1. 创建 GitHub 仓库 `aiclientproxy/kiro-provider` -2. 搭建项目结构(plugin.json、src-tauri/、src/) -3. 迁移后端代码(凭证管理、协议转换、风控) -4. 实现前端 UI(凭证列表、配置表单、状态展示) -5. 配置 GitHub Actions 自动构建发布 -6. 单元测试 + 集成测试 - -### Phase 3: 其他 OAuth Provider 独立仓库 - -**目标**:创建剩余 5 个 OAuth Provider 独立项目 - -**仓库列表**: -1. `aiclientproxy/claude-oauth-provider` - Anthropic OAuth + UI -2. `aiclientproxy/codex-provider` - OpenAI OAuth + UI -3. `aiclientproxy/gemini-oauth-provider` - Google OAuth + UI -4. `aiclientproxy/qwen-provider` - 阿里云 OAuth + UI -5. `aiclientproxy/iflow-provider` - iFlow OAuth/Cookie + UI - -### Phase 4: 协议转换层完善 - -**目标**:确保所有输入/输出协议组合正常工作 - -**任务**: -1. 完善 `StreamEvent` 统一事件层 -2. 实现 `OpenAI SSE Generator` - 输出 OpenAI 格式 -3. 实现 `Anthropic SSE Generator` - 输出 Anthropic 格式 -4. 支持按端点自动选择输出协议 -5. 集成到处理管道 - -### Phase 5: 插件管理功能 - -**目标**:实现插件安装、更新、卸载功能 - -**任务**: -1. 实现从 GitHub Release 安装插件 -2. 实现从本地文件安装插件 -3. 实现插件更新检查 -4. 实现插件卸载(清理文件和数据) -5. 实现插件启用/禁用 -6. 实现插件权限管理 - -### Phase 6: 清理和测试 - -**任务**: -1. 删除 ProxyCast 中旧的 `providers/` OAuth 代码 -2. 简化 `converter/` 模块 -3. 端到端测试(安装插件 → 配置凭证 → 调用 API) -4. 文档更新 - ---- - -## 九、风险和缓解 - -| 风险 | 影响 | 缓解措施 | -|------|------|---------| -| 迁移过程中服务中断 | 高 | 保留旧代码,通过 feature flag 切换 | -| 某个 Provider 转换出错 | 中 | 每个 Provider 独立测试,灰度发布 | -| 性能下降 | 中 | 基准测试,优化热路径 | -| 数据库迁移失败 | 高 | 备份现有数据,提供回滚脚本 | - ---- - -## 十、成功标准 - -### 10.1 OAuth 插件化 - -1. [ ] 所有 7 个 OAuth Provider 迁移为独立 GitHub 仓库 -2. [ ] 每个插件包含完整的后端代码和前端 UI -3. [ ] 新增 OAuth Provider 只需创建新仓库,无需修改 ProxyCast 核心代码 -4. [ ] 单个 OAuth Provider 可独立更新(通过 GitHub Release) -5. [ ] 插件 UI 在 ProxyCast 中正确加载和渲染 - -### 10.2 API Key 系统 - -1. [ ] API Key 系统保持现有设计不变 -2. [ ] 60+ 系统预设 Provider 继续正常工作 -3. [ ] 用户自定义 Provider 功能正常 - -### 10.3 协议转换 - -1. [ ] Kiro: Anthropic → CodeWhisperer → Anthropic SSE 转换正常 -2. [ ] Antigravity (claude-*): Anthropic → Antigravity → Anthropic SSE 转换正常 -3. [ ] Antigravity (gemini-*): Anthropic → Antigravity → Gemini 协议转换正常 -4. [ ] Claude OAuth: Anthropic → Anthropic 直通正常 -5. [ ] 所有 OAuth Provider 的协议转换测试通过 - -### 10.4 质量保证 - -1. [ ] 现有功能 100% 兼容 -2. [ ] 处理性能无明显下降(<10%) -3. [ ] 完整的单元测试和集成测试 - ---- - -## 附录 - -### A. ProxyCast 关键文件路径 - -**后端(插件宿主)**: - -| 文件 | 用途 | -|------|------| -| `/src-tauri/src/credential/plugin.rs` | CredentialProviderPlugin trait | -| `/src-tauri/src/credential/registry.rs` | CredentialProviderRegistry(加载外部插件)| -| `/src-tauri/src/plugin/loader.rs` | 插件加载器 | -| `/src-tauri/src/plugin/host.rs` | 插件宿主(生命周期管理)| -| `/src-tauri/src/plugin/sdk.rs` | ProxyCast SDK(供插件调用)| - -**前端(插件容器)**: - -| 文件 | 用途 | -|------|------| -| `/src/components/plugin/PluginContainer.tsx` | 插件 UI 容器 | -| `/src/components/plugin/PluginLoader.tsx` | 动态加载插件 JS/CSS | -| `/src/components/plugin/PluginRegistry.tsx` | 前端插件注册表 | -| `/src/pages/ProviderPool/OAuthPluginTab.tsx` | OAuth 插件列表 + 挂载点 | - -### B. 外部插件仓库 - -| 仓库 | 用途 | -|------|------| -| `aiclientproxy/kiro-provider` | Kiro OAuth Provider(后端 + UI)| -| `aiclientproxy/antigravity-provider` | Antigravity OAuth Provider(后端 + UI)| -| `aiclientproxy/claude-oauth-provider` | Claude OAuth Provider(后端 + UI)| -| `aiclientproxy/codex-provider` | Codex OAuth Provider(后端 + UI)| -| `aiclientproxy/gemini-oauth-provider` | Gemini OAuth Provider(后端 + UI)| -| `aiclientproxy/qwen-provider` | Qwen OAuth Provider(后端 + UI)| -| `aiclientproxy/iflow-provider` | iFlow OAuth Provider(后端 + UI)| - -### C. 参考现有代码 - -| 功能 | 现有文件(迁移到独立仓库)| -|------|---------| -| Kiro 风控逻辑 | `/src-tauri/src/providers/kiro.rs` → `kiro-provider` | -| 协议转换 | `/src-tauri/src/converter/openai_to_cw.rs` → `kiro-provider` | -| 凭证池 | `/src-tauri/src/credential/pool.rs`(保留,供插件复用)| -| 负载均衡 | `/src-tauri/src/credential/balancer.rs`(保留,供插件复用)| -| 插件 trait | `/src-tauri/src/plugin/types.rs`(参考)| - -### D. 插件安装目录 - -``` -~/.proxycast/plugins/ -├── kiro-provider/ -│ ├── plugin.json -│ ├── config.json -│ ├── bin/kiro-provider-cli -│ └── dist/ -│ ├── index.js -│ └── styles.css -├── antigravity-provider/ -│ └── ... -└── ... -``` diff --git a/docs/prd/skills-platform-mvp.md b/docs/prd/skills-platform-mvp.md deleted file mode 100644 index 20ef945e2..000000000 --- a/docs/prd/skills-platform-mvp.md +++ /dev/null @@ -1,1088 +0,0 @@ -# ProxyCast Skills Platform MVP - -> 产品需求文档 (PRD) -> 版本: 1.2.0 -> 日期: 2025-12-31 -> 状态: 草案 - ---- - -## 目录 - -1. [概述](#1-概述) -2. [产品定位](#2-产品定位) -3. [核心功能](#3-核心功能) -4. [技术方案](#4-技术方案) -5. [MVP 范围](#5-mvp-范围) -6. [UI 设计](#6-ui-设计) -7. [里程碑](#7-里程碑) -8. [成功指标](#8-成功指标) -9. [风险与缓解](#9-风险与缓解) -10. [附录](#10-附录) - ---- - -## 1. 概述 - -### 1.1 背景 - -#### 市场现状 - -AI Agent 和 Skills 生态正在快速发展: - -- **Claude Code** 等 AI 编码工具普及,催生了大量的 Skills 开发者 -- **Agent Skills** 已成为开放标准(agentskills.io),由 AAIF 基金会维护 -- 市场上出现了大量付费 Skills 的卖家 - -#### 核心痛点 - -``` -┌─────────────────────────────────────────────────────────────┐ -│ 当前市场断层 │ -├─────────────────────────────────────────────────────────────┤ -│ │ -│ Skills 供应商 普通用户 │ -│ ┌─────────┐ ┌─────────┐ │ -│ │ 写 Skills│ ───── 卖 ────► │ 买了但 │ │ -│ │ 很专业 │ │ 不会用 │ │ -│ └─────────┘ └─────────┘ │ -│ │ │ -│ ▼ │ -│ 😵 命令行太难 │ -│ 😵 不知道怎么安装 │ -│ 😵 看不到效果 │ -│ 😵 不知道花了多少钱 │ -│ │ -└─────────────────────────────────────────────────────────────┘ -``` - -1. **普通用户无法使用** - 需要命令行操作,门槛太高 -2. **效果不可见** - Skills 执行是黑盒,不知道在干什么 -3. **成本不透明** - 不知道 Token 花在哪里,花了多少 -4. **体验割裂** - Token 和 Skills 分开购买、分开配置 - -#### ProxyCast 的机会 - -ProxyCast 已有的能力恰好可以解决这些痛点: - -| 现有能力 | 解决的痛点 | -|---------|----------| -| GUI 界面 | 不需要命令行 | -| Flow Monitor | 看到 Skills 在干什么 | -| Credential Pool | 统一管理 Token | -| 插件系统 | 承载和分发 Skills | -| Goose 集成 | Agent 执行引擎(Rust 原生) | - -### 1.2 愿景 - -**ProxyCast 从 AI Proxy 工具升级为 AI 应用平台** - -成为 **Skills** 与 **Token 供应商** 之间的桥梁: - -``` -┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ -│ Token 供应商 │ │ Skills 供应商 │ │ 用户 │ -│ │ │ │ │ │ -│ - OpenAI │ │ - 开发者 │ │ - 普通用户 │ -│ - Anthropic │ │ - 专家 │ │ - 企业 │ -│ - 中转平台 │ │ - 工作室 │ │ - 开发者 │ -└────────┬────────┘ └────────┬────────┘ └────────┬────────┘ - │ │ │ - └───────────────────────┼───────────────────────┘ - │ - ▼ - ┌─────────────────────────┐ - │ ProxyCast │ - │ │ - │ Token + Skills 桥梁 │ - └─────────────────────────┘ -``` - -### 1.3 目标用户 - -| 用户类型 | 描述 | 核心需求 | -|---------|------|---------| -| **普通用户** | 想用 AI 工具但不会命令行 | 一键安装、可视化操作 | -| **Skills 开发者** | 想分发 Skills 给更多用户 | 发布渠道、用户触达 | -| **Token 供应商** | 想有更多应用场景 | 流量入口、使用场景 | -| **企业用户** | 想统一管理 AI 资产 | 成本控制、权限管理 | - -### 1.4 核心价值主张 - -1. **零门槛使用** - 不需要命令行,纯 GUI 操作 -2. **完全透明** - 流量可见、成本可控 -3. **开放标准** - 兼容 Agent Skills 规范 -4. **模型无关** - 支持 Claude、GPT、Gemini 等多模型 - ---- - -## 2. 产品定位 - -### 2.1 与 Agent Skills 标准的关系 - -ProxyCast Skills Platform **完全兼容** [Agent Skills 开放标准](https://agentskills.io): - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ Agent Skills 开放标准 │ -│ │ -│ 维护者: Anthropic (开放给社区贡献) │ -│ 性质: 开放格式,任何 Agent 平台都可以实现 │ -│ 规范: github.com/agentskills/agentskills │ -│ │ -└─────────────────────────────────────────────────────────────────┘ - │ - │ 兼容 - ▼ -┌─────────────────────────────────────────────────────────────────┐ -│ ProxyCast Skills Platform │ -│ │ -│ 定位: Agent Skills 的 GUI 运行环境 │ -│ 差异化: 可视化 + 流量监控 + Token 管理 │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - -### 2.2 Skills 目录结构(遵循标准) - -``` -my-skill/ -├── SKILL.md # 必需:指令 + 元数据 -├── scripts/ # 可选:可执行脚本 -├── references/ # 可选:参考文档 -└── assets/ # 可选:模板、资源文件 -``` - -### 2.3 SKILL.md 格式(遵循标准) - -```yaml ---- -name: code-review -description: 智能代码审查,发现潜在问题和优化建议 -license: MIT -metadata: - author: ProxyCast Team - version: "1.0.0" - category: development - tags: [code, review, quality] ---- - -# 代码审查 Skill - -## 使用场景 -当用户需要审查代码质量、发现潜在 bug 或获取优化建议时使用此 Skill。 - -## 审查流程 -1. 分析代码结构和逻辑 -2. 检查常见问题模式 -3. 识别安全隐患 -4. 提供优化建议 - -## 输出格式 -- 问题列表(按严重程度排序) -- 具体行号和代码片段 -- 修复建议 -``` - -### 2.4 设计原则:标准兼容 vs 实现自主 - -> **核心原则:兼容标准格式,但实现方式可以自主选择。** - -ProxyCast 不是 Claude Code 的复制品,而是一个独立的 Skills + Token 桥梁平台。 - -#### 2.4.1 必须兼容(Agent Skills 标准) - -这些是开放标准定义的内容,ProxyCast **必须支持**: - -| 标准内容 | 说明 | -|---------|------| -| **SKILL.md 格式** | YAML frontmatter + Markdown body | -| **目录结构** | scripts/, references/, assets/ | -| **元数据规范** | name, description, license, metadata.* | -| **仓库兼容** | 支持 anthropics/skills 等标准仓库 | - -#### 2.4.2 实现自主(不必照搬 Claude Code) - -这些是 Claude Code 的具体实现,ProxyCast **可以有自己的方式**: - -| Claude Code 实现 | ProxyCast 可以 | 原因 | -|-----------------|---------------|------| -| Shell Hooks | 不需要 | GUI 应用,不依赖命令行 | -| MCP Servers | 可选集成 | 有自己的 Goose 运行时 | -| Progressive Disclosure | 启动时预加载 | GUI 可以提前展示 | -| `/skill` 命令 | 自然语言触发 | Agent 自动匹配 Skill | -| CLI 安装 | 一键安装 UI | 更友好的用户体验 | - -#### 2.4.3 ProxyCast 特有实现 - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ ProxyCast Skills 实现方式 │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ 启动时: │ -│ ├─ 预加载所有已安装 Skills 的 name + description │ -│ ├─ 生成 XML │ -│ └─ 注入到 Goose Agent System Prompt │ -│ │ -│ 会话中: │ -│ ├─ 用户用自然语言描述任务 │ -│ ├─ Agent 根据 description 匹配合适的 Skill │ -│ └─ Agent 按需读取 SKILL.md 完整内容 │ -│ │ -│ 特点: │ -│ ├─ 被动式 - 用户不需要主动"选择"或"启用" │ -│ ├─ 无感知 - Agent 自动判断是否使用 Skill │ -│ └─ 透明 - Flow Monitor 显示 Skill 使用情况 │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - -### 2.5 差异化价值 - -| 标准提供的 | ProxyCast 额外提供的 | -|-----------|---------------------| -| 文件格式规范 | **GUI 可视化界面** | -| 目录结构约定 | **流量实时监控** | -| 参考实现库 | **Token 消耗统计** | -| CLI 工具 | **多模型支持** | -| | **Skills 商店** | -| | **一键安装** | -| | **成本分析报表** | - ---- - -## 3. 核心功能 - -### 3.1 Skills 生态架构(双轨模式) - -ProxyCast 采用**双轨 Skills 生态**:保留现有 Claude Code Skills 支持,同时建立 ProxyCast 官方仓库。 - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ ProxyCast Skills 生态 │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ Skills 来源(多仓库支持): │ -│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ -│ │ ProxyCast 官方 │ │ Anthropic 官方 │ │ 社区仓库 │ │ -│ │ proxycast/skills│ │ anthropics/skills│ │ ComposioHQ/... │ │ -│ │ (新增,主推) │ │ (保留,兼容) │ │ (保留,兼容) │ │ -│ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │ -│ │ │ │ │ -│ └───────────────────┴───────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────┐ │ -│ │ 统一 Skills 管理层(现有功能增强) │ │ -│ │ 位置: 设置 → 扩展 → Skills │ │ -│ │ - 多仓库管理(保留现有仓库管理功能) │ │ -│ │ - 支持安装到 Claude/Codex/Gemini/ProxyCast │ │ -│ │ - 搜索、过滤、安装/卸载 │ │ -│ └─────────────────────────────────────────────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────┐ │ -│ │ AI Agent 集成(新增功能) │ │ -│ │ 位置: AI Agent 页面 │ │ -│ │ - 被动式:自动加载所有已安装 Skills │ │ -│ │ - Skills 注入到 Agent System Prompt │ │ -│ │ - 流量监控 + Token 统计 │ │ -│ └─────────────────────────────────────────────────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - -### 3.2 Skills 仓库配置 - -#### 3.2.1 默认仓库(更新后) - -| 仓库 | 说明 | 优先级 | -|-----|------|-------| -| **proxycast/skills** | ProxyCast 官方仓库(新增) | 主推 | -| anthropics/skills | Anthropic 官方 Skills | 兼容 | -| ComposioHQ/awesome-claude-skills | 社区精选 | 兼容 | -| cexll/myclaude | 社区贡献 | 兼容 | - -#### 3.2.2 ProxyCast 官方仓库规划 - -``` -github.com/proxycast/skills/ -├── README.md # 仓库说明 + 贡献指南 -├── CONTRIBUTING.md # 贡献规范 -│ -├── official/ # 官方 Skills(精选、高质量) -│ ├── code-review/ -│ │ ├── SKILL.md -│ │ ├── references/ -│ │ └── examples/ -│ ├── doc-generator/ -│ ├── translator/ -│ ├── api-designer/ -│ └── test-writer/ -│ -├── community/ # 社区贡献(经审核) -│ └── ... -│ -└── templates/ # Skill 开发模板 - ├── basic/ - └── advanced/ -``` - -#### 3.2.3 首批官方 Skills - -| Skill | 描述 | 分类 | -|------|------|-----| -| **code-review** | 智能代码审查 | 开发 | -| **doc-generator** | 自动生成文档 | 开发 | -| **translator** | 多语言翻译 | 通用 | -| **api-designer** | API 设计助手 | 开发 | -| **test-writer** | 单元测试生成 | 开发 | -| **commit-message** | Git 提交信息 | 开发 | - -### 3.3 Skills 管理(复用现有功能) - -现有 Skills 管理功能(设置 → 扩展 → Skills)将继续使用,增强点: - -| 现有功能 | 增强内容 | -|---------|---------| -| 仓库管理 | 默认添加 proxycast/skills | -| Skills 列表 | 增加"来源"标签区分官方/社区 | -| 安装/卸载 | 保持不变 | -| 搜索/过滤 | 保持不变 | - -#### 3.3.1 Skills 目录 - -``` -~/.proxycast/skills/ # ProxyCast 应用的 Skills -├── code-review/ -├── doc-generator/ -└── ... - -~/.claude/skills/ # Claude Code 的 Skills(兼容) -├── ... -``` - -#### 3.3.2 Skills 生命周期 - -``` -发现(仓库扫描)→ 安装 → 自动加载 → 被动执行 → 卸载 - ↑ - 无需手动启用 -``` - -### 3.4 AI Agent 集成(核心新功能) - -基于现有 AI Agent 页面扩展,Skills 采用**被动式**集成。 - -#### 3.4.1 被动式设计原则 - -> **核心理念:Skills 不需要用户手动"选择"或"启用",而是自动加载、被动触发。** - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ 被动式 Skills vs 主动式 Skills │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ ❌ 主动式(不采用): │ -│ 用户需要先选择要使用的 Skills → 然后描述任务 │ -│ │ -│ ✅ 被动式(采用): │ -│ 用户直接描述任务 → Agent 自动匹配合适的 Skill │ -│ │ -│ 用户体验差异: │ -│ ├─ 主动式: "我要用代码审查 Skill,帮我审查这段代码" │ -│ └─ 被动式: "帮我审查这段代码"(Agent 自动使用 code-review) │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - -#### 3.4.2 UI 设计(信息展示,非选择器) - -在 AI Agent 页面展示已加载的 Skills(只读信息): - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ 🤖 AI Agent [运行中] ... │ -│ 基于 Goose 框架的 AI Agent 对话 │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ ⚙️ 控制面板 [∧] │ -│ ┌─────────────────────────────────────────────────────────┐ │ -│ │ 进程 [▶] [■] │ │ -│ │ │ │ -│ │ 会话 [claude ▼] [选择模型 ▼] [🗨 创建新会话] │ │ -│ └─────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────────────────────────────────────────────────────┐ │ -│ │ 📦 已加载 5 个 Skills [管理 Skills] │ │ -│ │ │ │ -│ │ code-review · translator · doc-generator · ... │ │ -│ │ │ │ -│ │ 💡 直接描述任务,Agent 会自动使用合适的 Skill │ │ -│ └─────────────────────────────────────────────────────────┘ │ -│ │ -│ [对话区域...] │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - -#### 3.4.3 Skills 注入机制(自动,非手动) - -系统**自动**将所有已安装的 Skills 注入到 Agent: - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ Skills 自动注入流程 │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ 1. ProxyCast 启动 / Skills 安装后 │ -│ └─ 扫描 ~/.proxycast/skills/ 目录 │ -│ │ -│ 2. 解析所有 SKILL.md 的 frontmatter │ -│ └─ 提取 name + description │ -│ │ -│ 3. 生成 XML │ -│ │ -│ 4. 创建 Agent 会话时自动注入 System Prompt │ -│ │ -│ 5. Agent 根据用户消息自动判断是否需要使用 Skill │ -│ ├─ 匹配到: 读取完整 SKILL.md,按指令执行 │ -│ └─ 未匹配: 正常对话 │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - -#### 3.4.3 Skills Prompt XML 格式 - -```xml - - - code-review - 智能代码审查,发现潜在问题和优化建议 - ~/.proxycast/skills/code-review/SKILL.md - - - translator - 多语言翻译,保持专业术语准确性 - ~/.proxycast/skills/translator/SKILL.md - - - -当用户的请求匹配某个 Skill 的描述时,请使用该 Skill 来完成任务。 -``` - -#### 3.4.4 执行流程 - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ Skills 执行流程(AI Agent 集成) │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ 1. 用户在 AI Agent 选择要启用的 Skills │ -│ │ │ -│ ▼ │ -│ 2. 创建会话时,Skills 信息注入 System Prompt │ -│ │ │ -│ ▼ │ -│ 3. 用户发送消息(自然语言) │ -│ │ │ -│ ▼ │ -│ 4. Agent 判断是否需要使用 Skill │ -│ │ │ -│ ├──► 需要: 加载 SKILL.md 内容,按指令执行 │ -│ │ │ -│ └──► 不需要: 正常对话 │ -│ │ │ -│ ▼ │ -│ 5. Flow Monitor 记录(标记 Skill 来源) │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - -### 3.5 Skills 执行(独立模式) - -除了 AI Agent 集成,也支持独立执行 Skills(未来版本)。 - -#### 3.5.1 多模型支持 - -同一个 Skill 可以选择不同的模型执行: - -``` -Skill: 代码审查 -├─ 使用 Claude 3.5 Sonnet(推荐,准确度高) -├─ 使用 GPT-4o(备选) -├─ 使用 Gemini Pro(成本低) -└─ 使用本地模型(隐私优先) -``` - -### 3.3 流量监控集成 - -复用现有 Flow Monitor,增加 Skills 维度: - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ Flow Monitor - Skills 视图 │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ 14:32:01 [代码审查] → Claude API │ -│ Skill: code-review v1.0.0 │ -│ Input: "Review this function: function add(a, b)..." │ -│ Output: "Found 2 issues: 1. Missing type checks..." │ -│ Tokens: 1,234 in / 567 out │ -│ Cost: $0.02 │ -│ Duration: 3.2s │ -│ │ -│ 14:31:45 [翻译助手] → GPT-4o │ -│ Skill: translator v1.2.0 │ -│ ... │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - -### 3.4 Token 管理 - -复用现有 Credential Pool,增加 Skills 统计: - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ Token 消耗统计 │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ 本月总消耗: 125,000 tokens ($3.75) │ -│ │ -│ 按 Skill 分布: │ -│ ├─ 代码审查: 45,000 tokens (36%) │ -│ ├─ 翻译助手: 38,000 tokens (30%) │ -│ ├─ 文档生成: 25,000 tokens (20%) │ -│ └─ 其他: 17,000 tokens (14%) │ -│ │ -│ 按模型分布: │ -│ ├─ Claude 3.5 Sonnet: 80,000 tokens ($2.40) │ -│ ├─ GPT-4o: 35,000 tokens ($1.05) │ -│ └─ Gemini Pro: 10,000 tokens ($0.30) │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - ---- - -## 4. 技术方案 - -### 4.1 整体架构 - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ ProxyCast Skills Platform │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌───────────────────────────────────────────────────────────┐ │ -│ │ Frontend (React) │ │ -│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ -│ │ │Skills Store │ │Skills Exec │ │Flow Monitor │ │ │ -│ │ │ UI │ │ UI │ │ (现有) │ │ │ -│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ -│ └───────────────────────────────────────────────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌───────────────────────────────────────────────────────────┐ │ -│ │ Backend (Rust) │ │ -│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ -│ │ │Skills │ │Goose Agent │ │Credential │ │ │ -│ │ │Manager │ │ (嵌入式) │ │Pool (现有) │ │ │ -│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ -│ │ │ │ -│ │ Goose 核心组件(Rust 原生,直接嵌入): │ │ -│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ -│ │ │Skills │ │Provider │ │Session │ │ │ -│ │ │Extension │ │Manager │ │Manager │ │ │ -│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ -│ └───────────────────────────────────────────────────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - -### 4.2 Goose 集成(库嵌入方式) - -#### 集成优势 - -``` -Goose 嵌入式集成: -┌─────────────────────────────────────────────────────────────────┐ -│ │ -│ 优势: │ -│ ├─ Rust 原生 - 与 Tauri 完美契合 │ -│ ├─ 无进程管理 - 直接调用库,无需 Sidecar │ -│ ├─ 性能最优 - 无进程间通信开销 │ -│ ├─ 30+ LLM 提供商 - Anthropic, OpenAI, Gemini, Ollama... │ -│ └─ Skills 原生支持 - 已支持 SKILL.md 格式 │ -│ │ -│ Goose 原生支持 Skills: │ -│ ├─ ~/.claude/skills/ 目录(与 Claude Code 兼容) │ -│ ├─ YAML frontmatter + Markdown 解析 │ -│ └─ 自动加载并注入 System Prompt │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - -#### 关键文件 - -| 文件 | 作用 | 修改内容 | -|-----|------|---------| -| `src-tauri/src/agent/goose_agent.rs` | Agent 封装 | Goose Agent 管理 | -| `src-tauri/src/agent/goose_types.rs` | 类型定义 | AgentEvent, SessionConfig | -| `src-tauri/Cargo.toml` | 依赖配置 | 添加 goose Git 依赖 | - -### 4.3 Skills 解析器 - -#### Rust 端实现 - -```rust -// src-tauri/src/skills/parser.rs - -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Serialize, Deserialize)] -pub struct SkillManifest { - pub name: String, - pub description: String, - pub license: Option, - pub metadata: Option, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct SkillMetadata { - pub author: Option, - pub version: Option, - pub category: Option, - pub tags: Option>, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct Skill { - pub manifest: SkillManifest, - pub content: String, // SKILL.md body - pub path: PathBuf, - pub has_scripts: bool, - pub has_references: bool, - pub has_assets: bool, -} - -impl Skill { - pub fn load(path: &Path) -> Result { - let skill_md = path.join("SKILL.md"); - let content = std::fs::read_to_string(&skill_md)?; - - // 解析 YAML frontmatter - let manifest = parse_frontmatter(&content)?; - - Ok(Self { - manifest, - content: extract_body(&content), - path: path.to_path_buf(), - has_scripts: path.join("scripts").exists(), - has_references: path.join("references").exists(), - has_assets: path.join("assets").exists(), - }) - } -} -``` - -### 4.4 数据流 - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ 数据流 │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ 用户操作 │ -│ │ │ -│ ▼ │ -│ Frontend (React) │ -│ │ Tauri Command │ -│ ▼ │ -│ Backend (Rust) │ -│ │ │ -│ ├──► Skills Manager: 管理 Skills 生命周期 │ -│ │ │ -│ ├──► Goose Agent: 直接调用 Goose 库执行 Skill │ -│ │ │ │ -│ │ ├──► Skills Extension 加载 Skill 内容 │ -│ │ ├──► PromptManager 构建 System Prompt │ -│ │ ├──► Provider 调用 LLM API │ -│ │ └──► 流式返回 AgentEvent │ -│ │ │ -│ └──► Flow Monitor: 记录流量和消耗 │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - -### 4.5 API 设计 - -#### Tauri Commands (Rust → Frontend) - -```rust -// Skills 管理 -#[tauri::command] -async fn list_skills() -> Result, String>; - -#[tauri::command] -async fn get_skill(name: &str) -> Result; - -#[tauri::command] -async fn install_skill(source: SkillSource) -> Result; - -#[tauri::command] -async fn uninstall_skill(name: &str) -> Result; - -// Skills 执行 -#[tauri::command] -async fn execute_skill( - skill_name: &str, - input: serde_json::Value, - model_config: ModelConfig, -) -> Result; - -// Goose Agent 管理 -#[tauri::command] -async fn get_agent_status() -> Result; - -#[tauri::command] -async fn create_session(provider: &str, model: &str) -> Result; -``` - -#### Goose Agent API(Rust 库调用) - -```rust -// 直接调用 Goose 库,无需 HTTP API -use goose::agents::{Agent, AgentEvent, SessionConfig}; -use goose::providers::create_provider; - -// 创建 Agent -let provider = create_provider("anthropic", "claude-sonnet-4-5").await?; -let agent = Agent::new(); -agent.update_provider(provider, &session_id).await?; - -// 发送消息(流式响应) -let message = Message::user().with_text("帮我审查这段代码"); -let mut stream = agent.reply(message, session_config, None).await?; - -while let Some(Ok(event)) = stream.next().await { - match event { - AgentEvent::Message(msg) => { /* 处理消息 */ } - AgentEvent::ModelChange { model, mode } => { /* 模型切换 */ } - // ... - } -} -``` - ---- - -## 5. MVP 范围 - -### 5.1 P0 - 必须有(第一版发布) - -基于现有功能扩展,最小改动实现核心价值。 - -| 功能 | 描述 | 现有基础 | 验收标准 | -|-----|------|---------|---------| -| ProxyCast 官方仓库 | 创建 proxycast/skills GitHub 仓库 | 无 | 仓库可访问 | -| 默认仓库配置 | 添加 proxycast/skills 到默认仓库列表 | skill_service.rs | 列表中显示 | -| AI Agent Skills 展示 | 在 AI Agent 页面显示已加载 Skills 信息 | AgentChatPage.tsx | 显示已加载 Skills | -| Skills 自动注入 | 已安装 Skills 自动注入 System Prompt | goose_agent.rs | Agent 能感知 Skills | -| 首批官方 Skills | 3-5 个高质量 Skills | 无 | 可安装使用 | - -### 5.2 P1 - 应该有(快速迭代) - -| 功能 | 描述 | 现有基础 | 验收标准 | -|-----|------|---------|---------| -| Skills 来源标签 | 区分官方/社区 Skills | SkillsPage.tsx | 显示来源标签 | -| Flow Monitor 集成 | 显示 Skill 执行流量 | Flow Monitor | 记录中标记 Skill | -| Token 消耗统计 | 按 Skill 统计消耗 | 无 | 看到成本分布 | -| Skills 执行追踪 | Flow Monitor 标记 Skill 使用 | 无 | 能看到用了哪个 Skill | -| Skills 详情面板 | 查看 Skill 完整内容 | 无 | 显示 SKILL.md | - -### 5.3 P2 - 可以有(未来版本) - -| 功能 | 描述 | -|-----|------| -| Skills 独立执行界面 | 不经过 AI Agent,直接执行 Skill | -| 评分/评论系统 | 用户对 Skills 评分评论 | -| Skills 推荐 | 基于使用习惯推荐 | -| 多 Agent 协作 | 多个 Skills 组合工作流 | -| Skills 编辑器 | 在线编辑 SKILL.md | -| 云端同步 | Skills 配置云端备份 | - -### 5.4 关键文件修改清单 - -| 文件 | 修改内容 | 优先级 | -|-----|---------|-------| -| `src-tauri/Cargo.toml` | 添加 goose Git 依赖 | P0 | -| `src-tauri/src/agent/goose_agent.rs` | Goose Agent 封装(新建) | P0 | -| `src-tauri/src/services/skill_service.rs` | 添加 proxycast/skills 到默认仓库 | P0 | -| `src/components/agent/AgentChatPage.tsx` | 添加已加载 Skills 展示 UI | P0 | -| `src-tauri/src/commands/agent_cmd.rs` | 适配 Goose API | P0 | -| `src/components/skills/SkillCard.tsx` | 添加来源标签 | P1 | -| `src/lib/api/skills.ts` | 增加获取 Skill 内容 API | P0 | - ---- - -## 6. UI 设计 - -### 6.1 导航结构 - -``` -ProxyCast -├── 仪表盘 -├── 流量监控 -├── Provider 管理 -├── 凭证池 -├── Skills ← 新增 -│ ├── 我的 Skills -│ ├── Skills 商店 -│ └── 执行历史 -├── 工具 -└── 设置 -``` - -### 6.2 Skills 列表页 - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ Skills [+ 安装 Skill] │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ 🔍 搜索 Skills... [全部 ▼] │ -│ │ -│ ┌─────────────────────────────────────────────────────────┐ │ -│ │ 🔍 代码审查 [运行] │ │ -│ │ 智能代码审查,发现潜在问题和优化建议 │ │ -│ │ 作者: ProxyCast Team | v1.0.0 | 内置 │ │ -│ │ 本月使用: 23 次 | 消耗: 45,230 tokens ($1.35) │ │ -│ └─────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────────────────────────────────────────────────────┐ │ -│ │ 📝 文档生成器 [运行] │ │ -│ │ 根据代码自动生成文档和注释 │ │ -│ │ 作者: ProxyCast Team | v1.0.0 | 内置 │ │ -│ │ 本月使用: 15 次 | 消耗: 28,100 tokens ($0.84) │ │ -│ └─────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────────────────────────────────────────────────────┐ │ -│ │ 🌐 翻译助手 [运行] │ │ -│ │ 多语言翻译,保持专业术语准确性 │ │ -│ │ 作者: ProxyCast Team | v1.0.0 | 内置 │ │ -│ │ 本月使用: 8 次 | 消耗: 12,500 tokens ($0.38) │ │ -│ └─────────────────────────────────────────────────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - -### 6.3 Skill 执行页 - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ ← 返回 | 代码审查 │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────────────────────────────────────────────────────┐ │ -│ │ 📄 输入 │ │ -│ │ │ │ -│ │ ┌────────────────────────────────────────────────────┐ │ │ -│ │ │ // 粘贴或输入要审查的代码 │ │ │ -│ │ │ function add(a, b) { │ │ │ -│ │ │ return a + b; │ │ │ -│ │ │ } │ │ │ -│ │ │ │ │ │ -│ │ └────────────────────────────────────────────────────┘ │ │ -│ │ │ │ -│ │ 或 [📁 上传文件] │ │ -│ └─────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────────────────────────────────────────────────────┐ │ -│ │ ⚙️ 配置 │ │ -│ │ │ │ -│ │ 模型: [Claude 3.5 Sonnet ▼] Token 来源: [默认 ▼] │ │ -│ │ │ │ -│ │ 预估消耗: ~2,000 tokens ($0.06) │ │ -│ └─────────────────────────────────────────────────────────┘ │ -│ │ -│ [▶ 执行] │ -│ │ -├─────────────────────────────────────────────────────────────────┤ -│ 📊 执行结果 │ -│ │ -│ ┌─────────────────────────────────────────────────────────┐ │ -│ │ ✅ 审查完成 │ │ -│ │ │ │ -│ │ 发现 2 个问题: │ │ -│ │ │ │ -│ │ ⚠️ [建议] 缺少类型检查 │ │ -│ │ Line 1: function add(a, b) │ │ -│ │ 建议: 添加参数类型检查或使用 TypeScript │ │ -│ │ │ │ -│ │ ℹ️ [信息] 可以添加 JSDoc 注释 │ │ -│ │ Line 1-3: 整个函数 │ │ -│ │ 建议: 添加 @param 和 @returns 注释 │ │ -│ │ │ │ -│ └─────────────────────────────────────────────────────────┘ │ -│ │ -│ 实际消耗: 1,234 tokens ($0.04) | 耗时: 3.2s │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - -### 6.4 Skills 安装对话框 - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ 安装 Skill [×] │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ 选择安装方式: │ -│ │ -│ ○ 从 URL 安装 │ -│ ┌────────────────────────────────────────────────────────┐ │ -│ │ https://github.com/user/skill-name │ │ -│ └────────────────────────────────────────────────────────┘ │ -│ │ -│ ○ 从本地目录安装 │ -│ [📁 选择目录] │ -│ │ -│ │ -│ [取消] [安装] │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - ---- - -## 7. 里程碑 - -### Phase 1: 官方仓库 + 基础集成(1 周) - -**目标**: 创建 ProxyCast 官方 Skills 仓库,完成基础集成 - -| 任务 | 预估 | 产出 | -|-----|------|-----| -| 创建 proxycast/skills GitHub 仓库 | 0.5d | 仓库结构 | -| 编写首批 3 个官方 Skills | 2d | code-review, translator, doc-generator | -| 修改 skill_service.rs 添加默认仓库 | 0.5d | 代码修改 | -| 测试 Skills 安装流程 | 0.5d | 测试通过 | -| 编写 README 和贡献指南 | 0.5d | 文档 | - -**交付物**: -- ProxyCast 官方 Skills 仓库上线 -- 用户可以在设置 → 扩展 → Skills 中看到官方 Skills - -### Phase 2: AI Agent 集成(1 周) - -**目标**: 在 AI Agent 中使用 Skills - -| 任务 | 预估 | 产出 | -|-----|------|-----| -| AgentChatPage 添加 Skills 信息展示 UI | 1d | React 组件 | -| 实现 Skills Prompt 生成器 | 1d | XML 生成函数 | -| 修改 agent_cmd.rs 支持 Skills 参数 | 1d | Rust 代码 | -| 实现 goose_agent.rs 注入 System Prompt | 1d | Rust 代码 | -| 端到端测试 | 0.5d | 测试通过 | - -**交付物**: -- 用户可以在 AI Agent 页面选择 Skills -- Agent 能感知并使用选中的 Skills - -### Phase 3: 增强功能(1 周) - -**目标**: 完善体验,准备发布 - -| 任务 | 预估 | 产出 | -|-----|------|-----| -| Skills 来源标签(官方/社区) | 1d | UI 增强 | -| Skills 详情面板 | 1d | 查看 SKILL.md | -| Flow Monitor Skills 标记 | 1d | 流量记录增强 | -| 文档编写(用户指南) | 1d | 用户文档 | -| Bug 修复和优化 | 1d | 稳定性 | - -**交付物**: 可发布的 MVP 版本 - -### 总时间线 - -``` -Week 1: Phase 1 - 官方仓库 + 基础集成 -Week 2: Phase 2 - AI Agent 集成 -Week 3: Phase 3 - 增强功能 + 发布准备 -``` - ---- - -## 8. 成功指标 - -### 8.1 用户增长指标 - -| 指标 | 目标(MVP 后 1 个月) | -|-----|---------------------| -| 日活用户 (DAU) | 100+ | -| Skills 安装数 | 500+ | -| Skills 执行数 | 2,000+ | - -### 8.2 用户体验指标 - -| 指标 | 目标 | -|-----|------| -| 首次 Skill 执行成功率 | > 90% | -| 平均执行时间 | < 5s | -| 用户满意度 (NPS) | > 40 | - -### 8.3 业务指标 - -| 指标 | 目标 | -|-----|------| -| Token 中转量 | 100M tokens/月 | -| 活跃 Skills 数 | 20+ | -| 开发者提交 Skills | 10+ | - ---- - -## 9. 风险与缓解 - -| 风险 | 影响 | 可能性 | 缓解措施 | -|-----|------|-------|---------| -| Goose API 变动 | 高 | 中 | 抽象接口层 + 锁定 Git commit | -| Skills 格式不兼容 | 中 | 低 | Goose 原生支持 SKILL.md + 验证器 | -| 性能问题 | 中 | 低 | Rust 嵌入式无进程开销 + 缓存 | -| Token 消耗超预期 | 中 | 低 | 执行前预估 + 消耗限制 + 告警 | -| 安全风险(恶意 Skills) | 高 | 低 | Goose 权限控制 + 审核机制 | - ---- - -## 10. 附录 - -### 10.1 术语表 - -| 术语 | 定义 | -|-----|------| -| **Skill** | 遵循 Agent Skills 标准的 AI 能力包 | -| **SKILL.md** | Skill 的核心定义文件 | -| **Goose** | ProxyCast 使用的 Agent 执行引擎(Rust 原生) | -| **Provider** | Goose 中的 LLM 提供商抽象 | -| **Flow Monitor** | ProxyCast 的流量监控功能 | -| **Credential Pool** | ProxyCast 的凭证管理功能 | - -### 10.2 参考资料 - -- [Agent Skills 规范](https://agentskills.io) -- [Agent Skills GitHub](https://github.com/agentskills/agentskills) -- [Goose 框架](https://github.com/block/goose) -- [ProxyCast 技术规格](../TECH_SPEC.md) - -### 10.3 变更历史 - -| 版本 | 日期 | 作者 | 变更内容 | -|-----|------|-----|---------| -| 1.0.0 | 2025-12-30 | Claude | 初始版本 | -| 1.1.0 | 2025-12-30 | Claude | 添加设计原则:标准兼容 vs 实现自主;更新为被动式 Skills 设计 | -| 1.2.0 | 2025-12-31 | Claude | 将 Agent 执行引擎从 Aster (Go) 替换为 Goose (Rust);采用库嵌入方式 | - ---- - -*本文档由 Claude 协助生成,基于与 ProxyCast 团队的讨论。* diff --git a/docs/prd/skills/async-image-skill-task-prd.md b/docs/prd/skills/async-image-skill-task-prd.md index 0bdc2d595..249d61e01 100644 --- a/docs/prd/skills/async-image-skill-task-prd.md +++ b/docs/prd/skills/async-image-skill-task-prd.md @@ -5,7 +5,7 @@ > 文档版本:v1.0 > 状态:Draft > 更新时间:2026-04-06 -> 适用范围:`image_generate` skill、`lime-cli`、媒体任务协议、Claw 对话框、图片工作台 +> 适用范围:`image_generate` skill、`lime-cli`、媒体任务协议、聊天区、图片工作台 > 目标读者:产品、前端、Rust/CLI、测试 --- @@ -19,12 +19,12 @@ 1. `@配图` 前端快路径 已具备占位反馈、图片卡、图片工作台展开等体验,但真相源偏前端本地运行时。 2. `image_generate` skill 任务路径 - 已具备稳定的任务创建能力,能输出 `task_id / task_type / path / status`,但当前只做到“提交任务”,没有把任务状态与结果动态回流到 Claw 对话框。 + 已具备稳定的任务创建能力,能输出 `task_id / task_type / path / status`,但当前只做到“提交任务”,没有把任务状态与结果动态回流到聊天区。 这导致三个核心问题: 1. **能力割裂**:前端快路径与 skill 任务路径体验不一致。 -2. **黑盒感强**:用户在 Claw 中看不到真实生成进度与真实结果替换。 +2. **黑盒感强**:用户在聊天区中看不到真实生成进度与真实结果替换。 3. **难以组合与测试**:如果图片生成过程继续停留在某个前端页面或某个 skill 内部,就很难在自动化、批处理、队列、重试、回放中复用。 本 PRD 的目标是把图片生成正式收敛为一条异步、解耦、标准化的主链: @@ -40,7 +40,7 @@ ### 2.1 产品目标 -1. 让用户在 Claw 对话框中发起图片 skill 后,立即看到可感知的动态反馈。 +1. 让用户在聊天区中发起图片 skill 后,立即看到可感知的动态反馈。 2. 让图片 skill 与正文配图、封面、自动化、未来 worker 共用同一套任务协议。 3. 让图片任务具备标准生命周期:创建、排队、执行、成功、失败、重试、取消、恢复。 4. 让前端显示的是“真实任务状态”,而不是 assistant 文案猜测。 @@ -63,7 +63,7 @@ ### 3.2 Task File 是唯一真相源 -图片任务的状态、结果、错误、来源关系都必须落到标准 task file 或其等价协议存储中。Claw、工作台、CLI、测试统一读取这一事实源。 +图片任务的状态、结果、错误、来源关系都必须落到标准 task file 或其等价协议存储中。聊天区、工作台、CLI、测试统一读取这一事实源。 ### 3.3 前端是观察者,不是执行器 @@ -95,9 +95,9 @@ ## 四、用户体验目标 -## 4.1 Claw 对话框中的图片任务体验 +## 4.1 聊天区中的图片任务体验 -用户在 Claw 中触发 `image_generate` 后,系统行为应如下: +用户在聊天区中触发 `image_generate` 后,系统行为应如下: 1. 立即创建图片任务。 2. 聊天区立即出现一张图片任务卡。 @@ -147,7 +147,7 @@ ```mermaid graph TD - USER[用户 / Claw 对话框] --> SKILL[image_generate skill] + USER[用户 / 聊天区] --> SKILL[image_generate skill] SKILL --> CLI[CLI / Task API] CLI --> TASKFILE[Task File / 标准任务协议] WORKER[图片执行器 / Worker] --> TASKFILE @@ -512,7 +512,7 @@ skill 输出的语义是: ### 11.1 用户体验验收 -1. 用户在 Claw 中通过图片 skill 发起任务后,聊天区立刻出现图片占位卡。 +1. 用户在聊天区中通过图片 skill 发起任务后,聊天区立刻出现图片占位卡。 2. 任务执行中,占位卡保持动态渲染,不出现“无反馈空窗”。 3. 任务成功后,占位卡自动替换为真实图片。 4. 点击成功图片可以打开图片工作台或图片画布。 @@ -551,7 +551,7 @@ skill 输出的语义是: - 暴露前端任务读取接口 - 保证执行器会写回结果与错误 -### Phase 2:Claw 聊天区动态卡 +### Phase 2:聊天区动态卡 - 监听任务创建 - 插入占位图片卡 diff --git a/docs/prd/tools/task-file-protocol-prd.md b/docs/prd/tools/task-file-protocol-prd.md index dc71f80de..23487c119 100644 --- a/docs/prd/tools/task-file-protocol-prd.md +++ b/docs/prd/tools/task-file-protocol-prd.md @@ -14,7 +14,7 @@ Lime 当前已经具备一套轻量 task file 底座,能够覆盖: - `typesetting` - `modal_resource_search` -现有协议已经解决了“任务创建、状态读取、简单重试”的基础问题,但当 Lime 开始把图片生成、图片编辑、视频生成、视频编辑、自动化工作流、Claw 动态渲染统一收口到同一条主线时,现有 task file 还存在四类缺口: +现有协议已经解决了“任务创建、状态读取、简单重试”的基础问题,但当 Lime 开始把图片生成、图片编辑、视频生成、视频编辑、自动化工作流、聊天区动态渲染统一收口到同一条主线时,现有 task file 还存在四类缺口: 1. **顶层字段不够稳定** - 现在更像“任务记录壳”,还不是“统一任务协议信封” @@ -27,7 +27,7 @@ Lime 当前已经具备一套轻量 task file 底座,能够覆盖: 这会直接影响后续几条主线: -- Claw 对话框中的动态占位图与结果替换 +- 聊天区中的动态占位图与结果替换 - 图片生成 / 图片编辑 / 视频生成 / 视频编辑的统一观察面 - 队列、重试、幂等、恢复、诊断能力 - 类似竞品“统一任务面板”的可交付体验 @@ -297,7 +297,7 @@ Lime 当前已经具备一套轻量 task file 底座,能够覆盖: 如果每次重试都新建任务文件,会带来这些问题: - 前端需要在旧卡片和新卡片之间重新绑定 -- Claw 动态替换更复杂 +- 聊天区动态替换更复杂 - 统一任务列表会出现大量碎片任务 - “这其实还是同一个任务”的语义丢失 @@ -561,7 +561,7 @@ Lime 当前已经具备一套轻量 task file 底座,能够覆盖: ## 10. 进度、错误与 UI 提示 -为了支撑 Claw 动态占位与结果替换,task file 不能只提供最终状态,还必须提供“可渲染的运行时信息”。 +为了支撑聊天区动态占位与结果替换,task file 不能只提供最终状态,还必须提供“可渲染的运行时信息”。 ## 10.1 `progress` @@ -716,7 +716,7 @@ Lime 当前已经具备一套轻量 task file 底座,能够覆盖: 流程: -1. 用户在 Claw 中触发 `image_generate` +1. 用户在聊天区中触发 `image_generate` 2. 创建 `task_family=image / task_type=image_generate` 3. `relationships.slot_id` 绑定正文占位块 4. 前端先显示占位图 @@ -779,7 +779,7 @@ Lime 当前已经具备一套轻量 task file 底座,能够覆盖: 并且保证: -- Claw、CLI、worker 读到的是同一份状态 +- 聊天区、CLI、worker 读到的是同一份状态 - 可以支撑统一任务面板,而不需要第二套状态系统 --- @@ -831,5 +831,4 @@ task file 应该被设计成 Lime 的统一任务协议,而不是某个业务 - **父子任务与依赖关系** - **结构化进度、错误、UI 提示** -这样 Lime 才能把图片生成、图片编辑、视频生成、视频编辑、Claw 动态渲染、CLI、worker、统一任务面板全部收敛到同一条主链。 - +这样 Lime 才能把图片生成、图片编辑、视频生成、视频编辑、聊天区动态渲染、CLI、worker、统一任务面板全部收敛到同一条主链。 diff --git a/docs/prd/unified-extension-platform.md b/docs/prd/unified-extension-platform.md deleted file mode 100644 index 7f1cf85d0..000000000 --- a/docs/prd/unified-extension-platform.md +++ /dev/null @@ -1,1475 +0,0 @@ -# ProxyCast 统一扩展平台架构 PRD - -> 版本: 1.0.0 -> 日期: 2026-01-05 -> 状态: Draft - ---- - -## 一、背景与目标 - -### 1.1 背景 - -当前 ProxyCast 已有多种扩展能力,但分散在不同系统中: - -| 现有能力 | 实现方式 | 问题 | -|---------|---------|------| -| Skills | 独立系统 | 与其他扩展隔离 | -| OAuth Provider | 硬编码枚举 | 新增需改核心代码 | -| API Key Provider | 数据库预设 | 无法独立更新 | -| 工具类 (MachineIdTool) | 独立插件 | 缺乏统一管理 | - -### 1.2 目标 - -构建 **统一扩展平台**,实现: - -1. **多类型扩展支持**:Skills、Token 供应商、OAuth 凭证、工具类等 -2. **服务商生态**:各服务商可发布自己的扩展应用 -3. **统一扩展中心**:一个入口管理所有类型的扩展 -4. **独立更新**:扩展可独立安装、更新、卸载 -5. **开放生态**:第三方开发者可贡献扩展 - ---- - -## 二、扩展类型定义 - -### 2.1 扩展类型总览 - -``` -┌─────────────────────────────────────────────────────────────────────────┐ -│ ProxyCast 统一扩展平台 │ -├─────────────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ -│ │ Skills │ │ Token │ │ OAuth │ │ Tools │ │ -│ │ 技能包 │ │ 供应商 │ │ 凭证 │ │ 工具类 │ │ -│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ -│ │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ -│ │ Provider │ │ Protocol │ │ Theme │ │ -│ │ 服务商插件 │ │ 协议扩展 │ │ 主题包 │ │ -│ └─────────────┘ └─────────────┘ └─────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────────────────┘ -``` - -### 2.2 扩展类型详解 - -| 类型 | ID | 说明 | 示例 | -|------|-----|------|------| -| **Skills** | `skill` | AI 技能包,扩展 Agent 能力 | 代码审查、翻译、写作 | -| **Token 供应商** | `token_provider` | 提供 API Key 的第三方服务 | OpenRouter、TogetherAI | -| **OAuth 凭证** | `oauth_provider` | 第三方 OAuth 授权服务 | Kiro、Claude OAuth、Gemini | -| **工具类** | `tool` | 实用工具 | Machine ID、Browser Interceptor | -| **服务商插件** | `vendor` | 服务商官方应用 | Anthropic 官方、OpenAI 官方 | -| **协议扩展** | `protocol` | 新协议支持 | Doubao、Wenxin | -| **主题包** | `theme` | UI 主题 | Dark Pro、Light Minimal | - ---- - -## 三、统一扩展架构 - -### 3.1 核心架构图 - -``` -┌─────────────────────────────────────────────────────────────────────────┐ -│ Extension Platform Core │ -├─────────────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ ExtensionRegistry (统一注册表) │ │ -│ │ │ │ -│ │ extensions: HashMap> │ │ -│ │ type_index: HashMap> │ │ -│ │ vendor_index: HashMap> │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ ExtensionLoader (加载器) │ │ -│ │ │ │ -│ │ - 扫描 ~/.proxycast/extensions/ │ │ -│ │ - 解析 extension.json │ │ -│ │ - 加载二进制/脚本/UI │ │ -│ │ - 验证签名和权限 │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ ExtensionHost (宿主环境) │ │ -│ │ │ │ -│ │ - 生命周期管理 (init/start/stop/unload) │ │ -│ │ - 权限沙箱 │ │ -│ │ - 资源隔离 │ │ -│ │ - SDK 注入 │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────────────────┘ -``` - -### 3.2 Extension Trait (统一接口) - -```rust -/// 统一扩展接口 - 所有扩展类型的基础 trait -#[async_trait] -pub trait Extension: Send + Sync { - // ========== 基础信息 ========== - - /// 扩展唯一 ID (如 "kiro-provider", "code-review-skill") - fn id(&self) -> &str; - - /// 扩展类型 - fn extension_type(&self) -> ExtensionType; - - /// 显示名称 - fn display_name(&self) -> &str; - - /// 版本号 - fn version(&self) -> &str; - - /// 描述 - fn description(&self) -> &str { "" } - - /// 作者/服务商 - fn vendor(&self) -> Option<&VendorInfo> { None } - - /// 图标 - fn icon(&self) -> Option<&str> { None } - - // ========== 能力声明 ========== - - /// 扩展清单 - fn manifest(&self) -> &ExtensionManifest; - - /// 所需权限 - fn required_permissions(&self) -> Vec { vec![] } - - /// 配置 Schema (JSON Schema) - fn config_schema(&self) -> serde_json::Value { serde_json::json!({}) } - - // ========== 生命周期 ========== - - /// 初始化 - async fn init(&mut self, ctx: &ExtensionContext) -> Result<()>; - - /// 启动 - async fn start(&mut self) -> Result<()> { Ok(()) } - - /// 停止 - async fn stop(&mut self) -> Result<()> { Ok(()) } - - /// 卸载前清理 - async fn unload(&mut self) -> Result<()> { Ok(()) } - - // ========== 配置管理 ========== - - /// 获取当前配置 - fn get_config(&self) -> serde_json::Value { serde_json::json!({}) } - - /// 更新配置 - async fn update_config(&mut self, config: serde_json::Value) -> Result<()> { Ok(()) } -} - -/// 扩展类型枚举 -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -pub enum ExtensionType { - Skill, // AI 技能包 - TokenProvider, // Token 供应商 - OAuthProvider, // OAuth 凭证 - Tool, // 工具类 - Vendor, // 服务商插件 - Protocol, // 协议扩展 - Theme, // 主题包 -} - -/// 服务商信息 -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct VendorInfo { - pub id: String, // "anthropic", "openai", "google" - pub name: String, // "Anthropic" - pub homepage: String, // "https://anthropic.com" - pub verified: bool, // 是否官方认证 - pub logo: Option, // Logo URL -} -``` - -### 3.3 扩展清单 (extension.json) - -```json -{ - "$schema": "https://proxycast.dev/schemas/extension.json", - - "id": "kiro-provider", - "type": "oauth_provider", - "version": "1.2.0", - "name": "Kiro Provider", - "description": "AWS CodeWhisperer OAuth 凭证管理,支持 Claude 模型", - - "vendor": { - "id": "proxycast", - "name": "ProxyCast Team", - "homepage": "https://github.com/aiclientproxy", - "verified": true - }, - - "license": "MIT", - "homepage": "https://github.com/aiclientproxy/kiro-provider", - "repository": "https://github.com/aiclientproxy/kiro-provider", - - "min_proxycast_version": "2.0.0", - - "permissions": [ - "database:read", - "database:write", - "http:request", - "crypto:encrypt", - "fs:read:credentials" - ], - - "entry": { - "type": "binary", - "binary_name": "kiro-provider-cli", - "platform_binaries": { - "macos-arm64": "bin/kiro-provider-aarch64-apple-darwin", - "macos-x64": "bin/kiro-provider-x86_64-apple-darwin", - "linux-x64": "bin/kiro-provider-x86_64-unknown-linux-gnu", - "windows-x64": "bin/kiro-provider-x86_64-pc-windows-msvc.exe" - } - }, - - "ui": { - "entry": "dist/index.js", - "styles": "dist/styles.css", - "surfaces": ["extension_center", "provider_pool"], - "icon": "Cloud", - "width": 800, - "height": 600 - }, - - "config_schema": { - "type": "object", - "properties": { - "risk_control": { - "type": "object", - "properties": { - "machine_id_rotation": { "type": "boolean", "default": true }, - "version_spoofing": { "type": "boolean", "default": true } - } - } - } - }, - - "capabilities": { - "oauth_provider": { - "target_protocol": "anthropic", - "supported_models": ["claude-*"], - "auth_types": ["oauth"], - "credential_schema": { - "type": "object", - "required": ["creds_file_path"], - "properties": { - "creds_file_path": { - "type": "string", - "title": "凭证文件路径" - } - } - } - } - }, - - "tags": ["oauth", "claude", "aws", "kiro"], - "categories": ["ai-provider", "authentication"] -} -``` - ---- - -## 四、各扩展类型详细设计 - -### 4.1 Skills (AI 技能包) - -```rust -/// Skill 扩展 trait -#[async_trait] -pub trait SkillExtension: Extension { - /// 技能触发条件 - fn triggers(&self) -> Vec; - - /// 系统提示词 - fn system_prompt(&self) -> &str; - - /// 可用工具 - fn tools(&self) -> Vec { vec![] } - - /// 执行技能 - async fn execute(&self, ctx: &SkillContext, input: &str) -> Result; -} - -#[derive(Clone, Debug)] -pub enum SkillTrigger { - Command(String), // /review, /translate - Keyword(Vec), // ["代码审查", "review"] - FileType(Vec), // [".rs", ".py"] - Always, // 始终可用 -} -``` - -**Skill extension.json 示例**: - -```json -{ - "id": "code-review-skill", - "type": "skill", - "name": "代码审查", - "description": "专业的代码审查技能,支持多种语言", - - "capabilities": { - "skill": { - "triggers": [ - { "type": "command", "value": "/review" }, - { "type": "keyword", "value": ["代码审查", "code review"] } - ], - "supported_languages": ["rust", "python", "typescript", "go"], - "system_prompt_file": "prompts/system.md", - "tools": ["read_file", "search_code"] - } - } -} -``` - -### 4.2 Token Provider (Token 供应商) - -```rust -/// Token 供应商扩展 trait -#[async_trait] -pub trait TokenProviderExtension: Extension { - /// 支持的模型列表 - async fn list_models(&self) -> Result>; - - /// 获取 API 配置 - fn api_config(&self) -> &ApiConfig; - - /// 验证 API Key - async fn validate_key(&self, key: &str) -> Result; - - /// 获取使用量/配额 - async fn get_usage(&self, key: &str) -> Result; - - /// 价格信息 - fn pricing(&self) -> Option<&PricingInfo> { None } -} - -#[derive(Clone, Debug)] -pub struct ApiConfig { - pub base_url: String, - pub auth_header: String, // "Authorization", "x-api-key" - pub auth_prefix: String, // "Bearer ", "" - pub protocol: String, // "openai", "anthropic" -} -``` - -**Token Provider extension.json 示例**: - -```json -{ - "id": "openrouter-provider", - "type": "token_provider", - "name": "OpenRouter", - "description": "统一 API 访问多种 AI 模型", - - "vendor": { - "id": "openrouter", - "name": "OpenRouter", - "homepage": "https://openrouter.ai", - "verified": true - }, - - "capabilities": { - "token_provider": { - "base_url": "https://openrouter.ai/api/v1", - "protocol": "openai", - "auth_header": "Authorization", - "auth_prefix": "Bearer ", - "models_endpoint": "/models", - "supports_streaming": true, - "pricing_url": "https://openrouter.ai/docs#models" - } - } -} -``` - -### 4.3 OAuth Provider (OAuth 凭证) - -```rust -/// OAuth 凭证扩展 trait (继承自现有设计) -#[async_trait] -pub trait OAuthProviderExtension: Extension { - /// 目标协议 - fn target_protocol(&self) -> &str; - - /// 支持的认证方式 - fn supported_auth_types(&self) -> Vec; - - /// 凭证配置 Schema - fn credential_schema(&self, auth_type: &str) -> serde_json::Value; - - /// 获取凭证 - async fn acquire_credential(&self, model: &str) -> Result; - - /// 释放凭证 - async fn release_credential(&self, id: &str, result: UsageResult); - - /// 刷新 Token - async fn refresh_token(&self, id: &str) -> Result; - - /// 协议转换 - async fn transform_request(&self, req: &mut ChatRequest) -> Result<()>; - - /// 风控适配 - async fn apply_risk_control(&self, req: &mut ChatRequest, cred_id: &str) -> Result<()>; -} -``` - -### 4.4 Tool (工具类) - -```rust -/// 工具扩展 trait -#[async_trait] -pub trait ToolExtension: Extension { - /// 工具类别 - fn category(&self) -> ToolCategory; - - /// 可用命令 - fn commands(&self) -> Vec; - - /// 执行命令 - async fn execute_command(&self, cmd: &str, args: serde_json::Value) -> Result; - - /// 是否需要后台运行 - fn requires_background(&self) -> bool { false } -} - -#[derive(Clone, Debug)] -pub enum ToolCategory { - Security, // Machine ID, 加密工具 - Network, // Browser Interceptor, 代理 - Development, // 代码格式化, Lint - Utility, // 剪贴板, 截图 -} - -#[derive(Clone, Debug)] -pub struct ToolCommand { - pub name: String, - pub description: String, - pub args_schema: serde_json::Value, -} -``` - -**Tool extension.json 示例**: - -```json -{ - "id": "machine-id-tool", - "type": "tool", - "name": "Machine ID 管理", - "description": "生成和管理 Machine ID,用于风控适配", - - "capabilities": { - "tool": { - "category": "security", - "commands": [ - { - "name": "generate", - "description": "生成新的 Machine ID", - "args": {} - }, - { - "name": "list", - "description": "列出所有 Machine ID", - "args": {} - }, - { - "name": "rotate", - "description": "轮换指定凭证的 Machine ID", - "args": { - "credential_id": { "type": "string", "required": true } - } - } - ], - "background_service": false - } - } -} -``` - -### 4.5 Vendor (服务商插件) - -```rust -/// 服务商插件 trait - 聚合多种能力 -#[async_trait] -pub trait VendorExtension: Extension { - /// 服务商提供的子扩展 - fn sub_extensions(&self) -> Vec; - - /// 服务商特有功能 - fn vendor_features(&self) -> Vec; - - /// 官方文档链接 - fn documentation_url(&self) -> Option<&str> { None } - - /// 状态页面 - fn status_page_url(&self) -> Option<&str> { None } -} - -#[derive(Clone, Debug)] -pub struct SubExtensionInfo { - pub id: String, - pub extension_type: ExtensionType, - pub name: String, -} - -#[derive(Clone, Debug)] -pub struct VendorFeature { - pub id: String, - pub name: String, - pub description: String, -} -``` - -**Vendor extension.json 示例**: - -```json -{ - "id": "anthropic-official", - "type": "vendor", - "name": "Anthropic 官方", - "description": "Anthropic 官方扩展包,包含 API Key 和 OAuth 支持", - - "vendor": { - "id": "anthropic", - "name": "Anthropic", - "homepage": "https://anthropic.com", - "verified": true, - "logo": "https://anthropic.com/logo.png" - }, - - "capabilities": { - "vendor": { - "sub_extensions": [ - { - "id": "claude-api", - "type": "token_provider", - "name": "Claude API Key" - }, - { - "id": "claude-oauth", - "type": "oauth_provider", - "name": "Claude OAuth" - } - ], - "features": [ - { - "id": "prompt_caching", - "name": "Prompt Caching", - "description": "缓存系统提示词,降低成本" - }, - { - "id": "batch_api", - "name": "Batch API", - "description": "批量处理请求,50% 折扣" - } - ], - "documentation": "https://docs.anthropic.com", - "status_page": "https://status.anthropic.com" - } - } -} -``` - -### 4.6 Protocol (协议扩展) - -```rust -/// 协议扩展 trait -#[async_trait] -pub trait ProtocolExtension: Extension { - /// 协议 ID - fn protocol_id(&self) -> &str; - - /// 格式化请求 - fn format_request(&self, req: &ChatRequest) -> Result; - - /// 解析响应 - fn parse_response(&self, resp: &serde_json::Value) -> Result; - - /// 解析流式响应 - fn parse_stream_chunk(&self, chunk: &[u8]) -> Result>; - - /// 错误解析 - fn parse_error(&self, status: u16, body: &str) -> ProviderError; -} -``` - -**Protocol extension.json 示例**: - -```json -{ - "id": "doubao-protocol", - "type": "protocol", - "name": "豆包协议", - "description": "字节跳动豆包 API 协议支持", - - "capabilities": { - "protocol": { - "protocol_id": "doubao", - "base_compatible": "openai", - "differences": [ - "model 字段格式不同", - "流式响应格式略有差异" - ], - "documentation": "https://www.volcengine.com/docs/82379" - } - } -} -``` - ---- - -## 五、扩展中心 UI 设计 - -### 5.1 统一入口 - -``` -┌─────────────────────────────────────────────────────────────────────────┐ -│ 扩展中心 (Extension Center) │ -├─────────────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ 🔍 搜索扩展... [+ 安装扩展] [⚙️] │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐ │ -│ │ 全部 │ Skills │ Token │ OAuth │ 工具 │ 服务商 │ │ -│ │ (23) │ (5) │ (8) │ (4) │ (3) │ (3) │ │ -│ └─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘ │ -│ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ 已安装扩展 │ │ -│ ├─────────────────────────────────────────────────────────────────┤ │ -│ │ │ │ -│ │ ┌─────────────────────────────────────────────────────────┐ │ │ -│ │ │ 🔌 Kiro Provider v1.2.0 │ │ │ -│ │ │ OAuth 凭证 · ProxyCast Team │ │ │ -│ │ │ AWS CodeWhisperer OAuth 凭证管理 │ │ │ -│ │ │ │ │ │ -│ │ │ [● 已启用] [配置] [更新可用 ↑] [卸载] │ │ │ -│ │ └─────────────────────────────────────────────────────────┘ │ │ -│ │ │ │ -│ │ ┌─────────────────────────────────────────────────────────┐ │ │ -│ │ │ 🛠️ Machine ID Tool v0.3.0 │ │ │ -│ │ │ 工具 · ProxyCast Team │ │ │ -│ │ │ Machine ID 生成和管理工具 │ │ │ -│ │ │ │ │ │ -│ │ │ [● 已启用] [打开] [配置] [卸载] │ │ │ -│ │ └─────────────────────────────────────────────────────────┘ │ │ -│ │ │ │ -│ │ ┌─────────────────────────────────────────────────────────┐ │ │ -│ │ │ ✨ 代码审查 Skill v2.0.0 │ │ │ -│ │ │ Skill · Community │ │ │ -│ │ │ 专业的代码审查技能,支持多种语言 │ │ │ -│ │ │ │ │ │ -│ │ │ [○ 已禁用] [启用] [配置] [卸载] │ │ │ -│ │ └─────────────────────────────────────────────────────────┘ │ │ -│ │ │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ 扩展市场 │ │ -│ ├─────────────────────────────────────────────────────────────────┤ │ -│ │ │ │ -│ │ 🔥 热门扩展 │ │ -│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ -│ │ │OpenRouter│ │Anthropic │ │ Browser │ │ 翻译 │ │ │ -│ │ │ Provider │ │ 官方 │ │Intercept │ │ Skill │ │ │ -│ │ │ ⭐ 4.8 │ │ ⭐ 4.9 │ │ ⭐ 4.5 │ │ ⭐ 4.7 │ │ │ -│ │ │ [安装] │ │ [安装] │ │ [安装] │ │ [安装] │ │ │ -│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │ -│ │ │ │ -│ │ 📦 官方认证 │ │ -│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ -│ │ │ Google │ │ OpenAI │ │ 阿里云 │ │ │ -│ │ │ 官方 │ │ 官方 │ │ 通义 │ │ │ -│ │ │ ✓ 认证 │ │ ✓ 认证 │ │ ✓ 认证 │ │ │ -│ │ │ [安装] │ │ [安装] │ │ [安装] │ │ │ -│ │ └──────────┘ └──────────┘ └──────────┘ │ │ -│ │ │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────────────────┘ -``` - -### 5.2 扩展详情页 - -``` -┌─────────────────────────────────────────────────────────────────────────┐ -│ ← 返回 │ -├─────────────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ │ │ -│ │ 🔌 Kiro Provider │ │ -│ │ ══════════════════════════════════════════════════════════════ │ │ -│ │ │ │ -│ │ 版本: 1.2.0 类型: OAuth 凭证 │ │ -│ │ 作者: ProxyCast Team 许可: MIT │ │ -│ │ 下载: 12.5k 评分: ⭐⭐⭐⭐⭐ (4.9) │ │ -│ │ │ │ -│ │ [安装] [GitHub] [文档] [问题反馈] │ │ -│ │ │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ 📝 描述 │ │ -│ ├─────────────────────────────────────────────────────────────────┤ │ -│ │ │ │ -│ │ AWS CodeWhisperer OAuth 凭证管理插件,支持: │ │ -│ │ - Claude 全系列模型 (Opus, Sonnet, Haiku) │ │ -│ │ - 自动 Token 刷新 │ │ -│ │ - Machine ID 风控适配 │ │ -│ │ - 多凭证负载均衡 │ │ -│ │ │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ 🔐 所需权限 │ │ -│ ├─────────────────────────────────────────────────────────────────┤ │ -│ │ │ │ -│ │ ✓ database:read - 读取数据库 │ │ -│ │ ✓ database:write - 写入数据库 │ │ -│ │ ✓ http:request - 发送 HTTP 请求 │ │ -│ │ ✓ crypto:encrypt - 加密敏感数据 │ │ -│ │ ✓ fs:read:credentials - 读取凭证文件 │ │ -│ │ │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ 📊 更新日志 │ │ -│ ├─────────────────────────────────────────────────────────────────┤ │ -│ │ │ │ -│ │ v1.2.0 (2026-01-05) │ │ -│ │ - 新增 Machine ID 自动轮换 │ │ -│ │ - 修复 Token 刷新失败问题 │ │ -│ │ - 优化凭证健康检查逻辑 │ │ -│ │ │ │ -│ │ v1.1.0 (2025-12-20) │ │ -│ │ - 支持 Claude 3.5 Sonnet │ │ -│ │ - 新增凭证导入/导出功能 │ │ -│ │ │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────────────────┘ -``` - -### 5.3 扩展配置面板 - -``` -┌─────────────────────────────────────────────────────────────────────────┐ -│ Kiro Provider 配置 [保存] [×] │ -├─────────────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ 基础设置 │ │ -│ ├─────────────────────────────────────────────────────────────────┤ │ -│ │ │ │ -│ │ 启用状态: [✓] 启用 │ │ -│ │ │ │ -│ │ 请求超时: [30000] ms │ │ -│ │ │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ 风控设置 │ │ -│ ├─────────────────────────────────────────────────────────────────┤ │ -│ │ │ │ -│ │ Machine ID 轮换: [✓] 启用 │ │ -│ │ │ │ -│ │ 版本号伪装: [✓] 启用 │ │ -│ │ │ │ -│ │ 冷却期 (秒): [300] │ │ -│ │ │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ 凭证管理 │ │ -│ ├─────────────────────────────────────────────────────────────────┤ │ -│ │ │ │ -│ │ 已添加凭证: 3 │ │ -│ │ │ │ -│ │ ┌─────────────────────────────────────────────────────────┐ │ │ -│ │ │ 凭证 1 (account1@example.com) ● 健康 [删除] │ │ │ -│ │ │ 凭证 2 (account2@example.com) ● 健康 [删除] │ │ │ -│ │ │ 凭证 3 (account3@example.com) ○ 冷却 [删除] │ │ │ -│ │ └─────────────────────────────────────────────────────────┘ │ │ -│ │ │ │ -│ │ [+ 添加凭证] │ │ -│ │ │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────────────────┘ -``` - ---- - -## 六、扩展注册表与加载器 - -### 6.1 统一注册表 - -```rust -/// 统一扩展注册表 -pub struct ExtensionRegistry { - /// 所有已加载扩展 - extensions: HashMap>, - - /// 按类型索引 - type_index: HashMap>, - - /// 按服务商索引 - vendor_index: HashMap>, - - /// 扩展目录 - extensions_dir: PathBuf, - - /// 事件发送器 - event_tx: broadcast::Sender, -} - -impl ExtensionRegistry { - /// 创建注册表 - pub fn new(extensions_dir: PathBuf) -> Self; - - /// 加载所有扩展 - pub async fn load_all(&mut self) -> Result<()>; - - /// 安装扩展 - pub async fn install(&mut self, source: ExtensionSource) -> Result; - - /// 卸载扩展 - pub async fn uninstall(&mut self, id: &str) -> Result<()>; - - /// 启用/禁用扩展 - pub async fn set_enabled(&mut self, id: &str, enabled: bool) -> Result<()>; - - /// 获取扩展 - pub fn get(&self, id: &str) -> Option>; - - /// 按类型获取 - pub fn get_by_type(&self, ext_type: ExtensionType) -> Vec>; - - /// 按服务商获取 - pub fn get_by_vendor(&self, vendor_id: &str) -> Vec>; - - /// 检查更新 - pub async fn check_updates(&self) -> Result>; - - /// 更新扩展 - pub async fn update(&mut self, id: &str) -> Result<()>; - - /// 订阅事件 - pub fn subscribe(&self) -> broadcast::Receiver; -} - -/// 扩展来源 -pub enum ExtensionSource { - /// 从 GitHub Release - GitHub { owner: String, repo: String, version: Option }, - /// 从本地文件 - LocalFile(PathBuf), - /// 从 URL - Url(String), - /// 从扩展市场 - Marketplace { id: String, version: Option }, -} - -/// 扩展事件 -pub enum ExtensionEvent { - Installed { id: String }, - Uninstalled { id: String }, - Enabled { id: String }, - Disabled { id: String }, - Updated { id: String, from: String, to: String }, - Error { id: String, error: String }, -} -``` - -### 6.2 扩展加载器 - -```rust -/// 扩展加载器 -pub struct ExtensionLoader { - extensions_dir: PathBuf, - sdk: Arc, -} - -impl ExtensionLoader { - /// 加载单个扩展 - pub async fn load(&self, ext_dir: &Path) -> Result> { - // 1. 读取 extension.json - let manifest_path = ext_dir.join("extension.json"); - let manifest: ExtensionManifest = serde_json::from_str( - &fs::read_to_string(&manifest_path)? - )?; - - // 2. 验证签名(如果有) - if let Some(signature) = &manifest.signature { - self.verify_signature(ext_dir, signature)?; - } - - // 3. 根据类型创建扩展实例 - let extension: Box = match manifest.extension_type { - ExtensionType::Skill => { - Box::new(SkillExtensionImpl::new(ext_dir, manifest, self.sdk.clone())?) - } - ExtensionType::TokenProvider => { - Box::new(TokenProviderImpl::new(ext_dir, manifest, self.sdk.clone())?) - } - ExtensionType::OAuthProvider => { - Box::new(OAuthProviderImpl::new(ext_dir, manifest, self.sdk.clone())?) - } - ExtensionType::Tool => { - Box::new(ToolExtensionImpl::new(ext_dir, manifest, self.sdk.clone())?) - } - ExtensionType::Vendor => { - Box::new(VendorExtensionImpl::new(ext_dir, manifest, self.sdk.clone())?) - } - ExtensionType::Protocol => { - Box::new(ProtocolExtensionImpl::new(ext_dir, manifest, self.sdk.clone())?) - } - ExtensionType::Theme => { - Box::new(ThemeExtensionImpl::new(ext_dir, manifest)?) - } - }; - - Ok(extension) - } - - /// 验证签名 - fn verify_signature(&self, ext_dir: &Path, signature: &str) -> Result<()>; -} -``` - -### 6.3 ProxyCast SDK - -```rust -/// ProxyCast SDK - 供扩展使用的能力集 -pub struct ProxyCastSDK { - database: Arc, - http: Arc, - crypto: Arc, - notification: Arc, - events: Arc, - storage: Arc, -} - -impl ProxyCastSDK { - // ========== 数据库 ========== - - /// 查询数据 - pub async fn db_query(&self, sql: &str, params: &[&dyn ToSql]) -> Result>; - - /// 执行 SQL - pub async fn db_execute(&self, sql: &str, params: &[&dyn ToSql]) -> Result; - - // ========== HTTP ========== - - /// 发送请求 - pub async fn http_request(&self, req: HttpRequest) -> Result; - - // ========== 加密 ========== - - /// 加密数据 - pub fn encrypt(&self, data: &str) -> Result; - - /// 解密数据 - pub fn decrypt(&self, data: &str) -> Result; - - // ========== 通知 ========== - - /// 显示通知 - pub fn notify(&self, notification: Notification); - - // ========== 事件 ========== - - /// 发送事件 - pub fn emit(&self, event: &str, data: serde_json::Value); - - /// 订阅事件 - pub fn on(&self, event: &str, callback: Box); - - // ========== 存储 ========== - - /// 获取扩展专属存储 - pub fn storage(&self, extension_id: &str) -> ExtensionStorage; -} - -/// 扩展专属存储 -pub struct ExtensionStorage { - extension_id: String, - base_path: PathBuf, -} - -impl ExtensionStorage { - /// 读取配置 - pub fn get_config(&self) -> Result; - - /// 保存配置 - pub fn set_config(&self, config: serde_json::Value) -> Result<()>; - - /// 读取文件 - pub fn read_file(&self, path: &str) -> Result>; - - /// 写入文件 - pub fn write_file(&self, path: &str, data: &[u8]) -> Result<()>; -} -``` - ---- - -## 七、扩展市场 - -### 7.1 市场架构 - -``` -┌─────────────────────────────────────────────────────────────────────────┐ -│ 扩展市场 (Extension Marketplace) │ -├─────────────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ 市场 API (marketplace.proxycast.dev) │ │ -│ │ │ │ -│ │ GET /api/extensions - 扩展列表 │ │ -│ │ GET /api/extensions/:id - 扩展详情 │ │ -│ │ GET /api/extensions/:id/versions - 版本列表 │ │ -│ │ GET /api/extensions/:id/download - 下载扩展 │ │ -│ │ POST /api/extensions - 发布扩展 (需认证) │ │ -│ │ GET /api/vendors - 服务商列表 │ │ -│ │ GET /api/categories - 分类列表 │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────────────────────────────────────────────────────────────┐ │ -│ │ 扩展索引 (Extension Index) │ │ -│ │ │ │ -│ │ { │ │ -│ │ "id": "kiro-provider", │ │ -│ │ "name": "Kiro Provider", │ │ -│ │ "type": "oauth_provider", │ │ -│ │ "vendor": { "id": "proxycast", "verified": true }, │ │ -│ │ "latest_version": "1.2.0", │ │ -│ │ "downloads": 12500, │ │ -│ │ "rating": 4.9, │ │ -│ │ "tags": ["oauth", "claude", "aws"], │ │ -│ │ "download_url": "https://..." │ │ -│ │ } │ │ -│ └─────────────────────────────────────────────────────────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────────────────┘ -``` - -### 7.2 发布流程 - -``` -开发者提交扩展 - │ - ▼ -┌─────────────────────────────────────┐ -│ 1. 自动化检查 │ -│ - extension.json 格式验证 │ -│ - 权限声明审核 │ -│ - 安全扫描 │ -│ - 二进制签名验证 │ -└─────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────┐ -│ 2. 人工审核 (可选) │ -│ - 官方认证扩展需要 │ -│ - 高权限扩展需要 │ -└─────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────┐ -│ 3. 发布到市场 │ -│ - 生成下载链接 │ -│ - 更新索引 │ -│ - 通知订阅用户 │ -└─────────────────────────────────────┘ -``` - ---- - -## 八、权限系统 - -### 8.1 权限定义 - -```rust -/// 扩展权限 -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum Permission { - // 数据库 - DatabaseRead, - DatabaseWrite, - - // 网络 - HttpRequest, - HttpRequestExternal, // 访问外部 URL - - // 文件系统 - FsReadCredentials, // 读取凭证文件 - FsReadConfig, // 读取配置文件 - FsWriteConfig, // 写入配置文件 - FsReadAny, // 读取任意文件 (高危) - FsWriteAny, // 写入任意文件 (高危) - - // 加密 - CryptoEncrypt, - CryptoDecrypt, - - // 系统 - SystemInfo, // 获取系统信息 - ProcessSpawn, // 启动子进程 (高危) - - // UI - UiNotification, - UiDialog, - UiMainWindow, - - // 扩展间通信 - ExtensionCommunicate, -} - -impl Permission { - /// 是否为高危权限 - pub fn is_dangerous(&self) -> bool { - matches!(self, - Permission::FsReadAny | - Permission::FsWriteAny | - Permission::ProcessSpawn | - Permission::HttpRequestExternal - ) - } - - /// 权限描述 - pub fn description(&self) -> &str { - match self { - Permission::DatabaseRead => "读取数据库", - Permission::DatabaseWrite => "写入数据库", - Permission::HttpRequest => "发送 HTTP 请求到 ProxyCast 服务", - Permission::HttpRequestExternal => "发送 HTTP 请求到外部服务", - Permission::FsReadCredentials => "读取凭证文件", - Permission::CryptoEncrypt => "加密敏感数据", - Permission::CryptoDecrypt => "解密敏感数据", - // ... - _ => "未知权限" - } - } -} -``` - -### 8.2 权限检查 - -```rust -/// 权限检查器 -pub struct PermissionChecker { - granted: HashSet, -} - -impl PermissionChecker { - /// 检查权限 - pub fn check(&self, permission: Permission) -> Result<()> { - if self.granted.contains(&permission) { - Ok(()) - } else { - Err(Error::PermissionDenied(permission)) - } - } - - /// 请求权限 (弹窗确认) - pub async fn request(&mut self, permissions: Vec) -> Result<()>; -} -``` - ---- - -## 九、目录结构 - -### 9.1 ProxyCast 主项目结构 - -``` -src-tauri/src/ -├── extension/ # 【新增】统一扩展系统 -│ ├── mod.rs # 模块入口 -│ ├── types.rs # Extension trait 和类型定义 -│ ├── registry.rs # ExtensionRegistry 统一注册表 -│ ├── loader.rs # ExtensionLoader 加载器 -│ ├── host.rs # ExtensionHost 宿主环境 -│ ├── sdk.rs # ProxyCastSDK -│ ├── permission.rs # 权限系统 -│ │ -│ ├── impls/ # 各类型扩展实现 -│ │ ├── skill.rs # SkillExtension 实现 -│ │ ├── token_provider.rs # TokenProviderExtension 实现 -│ │ ├── oauth_provider.rs # OAuthProviderExtension 实现 -│ │ ├── tool.rs # ToolExtension 实现 -│ │ ├── vendor.rs # VendorExtension 实现 -│ │ ├── protocol.rs # ProtocolExtension 实现 -│ │ └── theme.rs # ThemeExtension 实现 -│ │ -│ └── marketplace/ # 扩展市场客户端 -│ ├── client.rs # API 客户端 -│ └── types.rs # 市场数据类型 -│ -├── credential/ # 保留,供 OAuth Provider 扩展复用 -│ ├── pool.rs -│ ├── balancer.rs -│ └── health.rs -│ -└── plugin/ # 现有插件系统,逐步迁移到 extension/ -``` - -### 9.2 前端目录结构 - -``` -src/ -├── pages/ -│ └── ExtensionCenter/ # 【新增】扩展中心页面 -│ ├── index.tsx # 主页面 -│ ├── ExtensionList.tsx # 扩展列表 -│ ├── ExtensionDetail.tsx # 扩展详情 -│ ├── ExtensionConfig.tsx # 扩展配置 -│ ├── Marketplace.tsx # 扩展市场 -│ └── components/ -│ ├── ExtensionCard.tsx -│ ├── TypeFilter.tsx -│ ├── VendorBadge.tsx -│ └── PermissionList.tsx -│ -├── components/ -│ └── extension/ # 【新增】扩展相关组件 -│ ├── ExtensionContainer.tsx # 扩展 UI 容器 -│ ├── ExtensionLoader.tsx # 扩展 JS/CSS 加载 -│ └── ExtensionRegistry.tsx # 前端扩展注册表 -│ -└── hooks/ - └── useExtension.ts # 【新增】扩展相关 hooks -``` - -### 9.3 扩展安装目录 - -``` -~/.proxycast/extensions/ -├── kiro-provider/ # OAuth Provider 扩展 -│ ├── extension.json -│ ├── config.json -│ ├── bin/ -│ │ └── kiro-provider-cli -│ └── dist/ -│ ├── index.js -│ └── styles.css -│ -├── machine-id-tool/ # Tool 扩展 -│ ├── extension.json -│ ├── config.json -│ └── bin/ -│ └── machine-id-tool -│ -├── code-review-skill/ # Skill 扩展 -│ ├── extension.json -│ ├── config.json -│ └── prompts/ -│ └── system.md -│ -├── openrouter-provider/ # Token Provider 扩展 -│ ├── extension.json -│ └── config.json -│ -└── anthropic-official/ # Vendor 扩展 - ├── extension.json - ├── config.json - └── sub_extensions/ - ├── claude-api/ - └── claude-oauth/ -``` - ---- - -## 十、数据库设计 - -### 10.1 扩展表 - -```sql --- 已安装扩展 -CREATE TABLE extensions ( - id TEXT PRIMARY KEY, -- "kiro-provider" - type TEXT NOT NULL, -- "oauth_provider", "skill", etc. - name TEXT NOT NULL, - version TEXT NOT NULL, - vendor_id TEXT, - enabled INTEGER DEFAULT 1, - config TEXT, -- JSON 配置 - permissions TEXT, -- JSON 权限列表 - install_path TEXT NOT NULL, - installed_at INTEGER NOT NULL, - updated_at INTEGER NOT NULL -); - --- 扩展凭证 (OAuth Provider 专用) -CREATE TABLE extension_credentials ( - id TEXT PRIMARY KEY, - extension_id TEXT NOT NULL, - credential_data TEXT NOT NULL, -- 加密的凭证数据 - status TEXT DEFAULT 'active', - stats TEXT, -- JSON 统计 - created_at INTEGER NOT NULL, - updated_at INTEGER NOT NULL, - FOREIGN KEY (extension_id) REFERENCES extensions(id) -); - --- 服务商信息 -CREATE TABLE vendors ( - id TEXT PRIMARY KEY, -- "anthropic", "openai" - name TEXT NOT NULL, - homepage TEXT, - verified INTEGER DEFAULT 0, - logo_url TEXT, - created_at INTEGER NOT NULL -); - --- 扩展市场缓存 -CREATE TABLE marketplace_cache ( - id TEXT PRIMARY KEY, - data TEXT NOT NULL, -- JSON 扩展信息 - cached_at INTEGER NOT NULL -); -``` - ---- - -## 十一、迁移计划 - -### 11.1 阶段一:基础架构 (2 周) - -| 任务 | 说明 | -|------|------| -| Extension trait 定义 | 统一扩展接口 | -| ExtensionRegistry | 统一注册表 | -| ExtensionLoader | 扩展加载器 | -| ProxyCastSDK | 扩展 SDK | -| 权限系统 | Permission 定义和检查 | - -### 11.2 阶段二:扩展类型实现 (3 周) - -| 任务 | 说明 | -|------|------| -| OAuthProviderExtension | 迁移现有 OAuth Provider | -| TokenProviderExtension | 迁移现有 API Key Provider | -| ToolExtension | 迁移 MachineIdTool | -| SkillExtension | 迁移现有 Skills | - -### 11.3 阶段三:UI 与市场 (2 周) - -| 任务 | 说明 | -|------|------| -| 扩展中心页面 | 统一管理入口 | -| 扩展配置面板 | 动态表单生成 | -| 扩展市场客户端 | 浏览、安装、更新 | - -### 11.4 阶段四:生态建设 (持续) - -| 任务 | 说明 | -|------|------| -| 官方扩展发布 | Kiro、Anthropic、OpenAI 等 | -| 开发者文档 | 扩展开发指南 | -| 市场后端 | marketplace.proxycast.dev | - ---- - -## 十二、与现有系统的关系 - -### 12.1 兼容性设计 - -``` -┌─────────────────────────────────────────────────────────────────────────┐ -│ 现有系统 → 统一扩展平台 │ -├─────────────────────────────────────────────────────────────────────────┤ -│ │ -│ 现有 ProviderType 枚举 (11种) │ -│ │ │ -│ ├── OAuth 类型 (7种) ──────→ OAuthProviderExtension │ -│ │ Kiro, Gemini, Qwen, Antigravity, │ -│ │ ClaudeOAuth, Codex, IFlow │ -│ │ │ -│ └── API Key 类型 (4种) ────→ TokenProviderExtension │ -│ Claude, OpenAI, GeminiApiKey, Vertex │ -│ │ -│ ───────────────────────────────────────────────────────────────────── │ -│ │ -│ 现有 api_key_providers 表 (60+ 预设) │ -│ │ │ -│ └── 保持不变,作为 TokenProviderExtension 的数据源 │ -│ │ -│ ───────────────────────────────────────────────────────────────────── │ -│ │ -│ 现有 Plugin 系统 (MachineIdTool) │ -│ │ │ -│ └── 迁移为 ToolExtension │ -│ │ -│ ───────────────────────────────────────────────────────────────────── │ -│ │ -│ 现有 Skills 系统 │ -│ │ │ -│ └── 迁移为 SkillExtension │ -│ │ -└─────────────────────────────────────────────────────────────────────────┘ -``` - -### 12.2 渐进式迁移 - -1. **第一步**:新建 `extension/` 模块,不影响现有代码 -2. **第二步**:实现各类型 Extension trait -3. **第三步**:将现有 Provider 包装为 Extension -4. **第四步**:新功能使用 Extension 系统 -5. **第五步**:逐步删除旧代码 - ---- - -## 十三、总结 - -### 13.1 核心价值 - -| 价值 | 说明 | -|------|------| -| **统一管理** | 一个入口管理所有扩展类型 | -| **独立更新** | 扩展可独立安装、更新、卸载 | -| **开放生态** | 第三方开发者可贡献扩展 | -| **服务商友好** | 服务商可发布官方扩展 | -| **安全可控** | 权限系统保障安全 | - -### 13.2 扩展类型总结 - -| 类型 | 数量 | 示例 | -|------|------|------| -| Skills | 5+ | 代码审查、翻译、写作 | -| Token Provider | 10+ | OpenRouter、TogetherAI、官方 API | -| OAuth Provider | 7+ | Kiro、Claude OAuth、Gemini | -| Tool | 3+ | Machine ID、Browser Interceptor | -| Vendor | 5+ | Anthropic、OpenAI、Google | -| Protocol | 3+ | Doubao、Wenxin | -| Theme | 2+ | Dark Pro、Light Minimal | - -### 13.3 关键设计决策 - -1. **统一 Extension trait**:所有扩展类型继承同一基础接口 -2. **extension.json 清单**:标准化扩展元数据格式 -3. **ProxyCastSDK**:为扩展提供统一的能力访问 -4. **权限系统**:细粒度权限控制,保障安全 -5. **扩展市场**:官方市场 + GitHub Release 双渠道 -6. **渐进式迁移**:不破坏现有功能,逐步演进 diff --git a/docs/roadmap/lime-service-skill-cloud-config-prd.md b/docs/roadmap/lime-service-skill-cloud-config-prd.md index e4b894dc7..cffb6ba6a 100644 --- a/docs/roadmap/lime-service-skill-cloud-config-prd.md +++ b/docs/roadmap/lime-service-skill-cloud-config-prd.md @@ -1,8 +1,10 @@ # Lime 服务型技能:端优先执行、云配置同步 PRD -> 状态:提案 -> 更新时间:2026-03-24 +> 状态:current supporting cross-repo plan +> 更新时间:2026-04-19 +> 当前主规划:`docs/roadmap/limenextv2/README.md` > 目标:吸收 Ribbi 式服务型技能入口的产品方法,但保持 Lime 的端优先执行与低云成本架构 +> 作用域:本文只保留服务型技能在 `lime` / `limecore` 之间的产品对象、目录分层与执行边界,不替代 `docs/aiprompts/command-runtime.md`、`docs/aiprompts/limecore-collaboration-entry.md` 与 `limecore/docs/api/lime-client-integration.md` ## 1. 文档依据 @@ -10,25 +12,46 @@ `lime` 侧主要事实源: -- `src/components/agent/chat/index.tsx` -- `src/components/agent/chat/components/EmptyState.tsx` -- `src-tauri/src/skills/README.md` -- `src-tauri/src/services/automation_service/mod.rs` -- `src-tauri/src/services/execution_tracker_service.rs` +- `src/lib/api/serviceSkills.ts` +- `src/lib/serviceSkillCatalogBootstrap.ts` +- `src/hooks/useOemCloudAccess.ts` +- `src/components/agent/chat/workspace/serviceSkillSceneLaunch.ts` +- `src/components/agent/chat/workspace/useWorkspaceSendActions.ts` +- `docs/aiprompts/command-runtime.md` `limecore` 侧主要事实源: - `docs/api/lime-client-integration.md` +- `docs/aiprompts/lime-limecore-collaboration.md` - `services/control-plane-svc/internal/model/client_bootstrap.go` +- `services/control-plane-svc/internal/controller/public_client.go` - `services/scene-orchestrator-svc/README.md` - `services/control-plane-svc/internal/model/commercial.go` 关键环境事实: 1. `lime` 已有任务入口、技能执行链、自动化调度链、执行追踪链。 -2. `limecore` 已有 `control-plane-svc / gateway-svc / scene-orchestrator-svc`,并已有客户端 bootstrap 聚合接口。 -3. `bootstrap.serviceCatalog` 现有语义偏商业服务目录,不适合直接承载新的服务型技能目录。 -4. `scene-orchestrator-svc` 已定位为 Scene 运行时服务,但不应在本方案中演进为默认主执行流。 +2. `limecore` 已有 `control-plane-svc / gateway-svc / scene-orchestrator-svc`,并已提供 `client/bootstrap`、`client/skills`、`client/service-skills`。 +3. `client/bootstrap` 当前已同时返回 `skillCatalog` 与 `serviceSkillCatalog`: + - `skillCatalog.entries` 是统一命令发现协议 + - `serviceSkillCatalog` 是完整服务型技能目录 + - `serviceCatalog` 仍保持商业服务目录语义,不应混用 +4. `lime` 当前已消费在线目录并保留 seeded / fallback 韧性兜底,不再只依赖客户端静态常量。 +5. `scene-orchestrator-svc` 已定位为 Scene 运行时服务,但不应在本方案中演进为普通任务的默认主执行流。 + +## 1.1 当前吸收结果(2026-04-19) + +这份 PRD 的核心判断已经被 current 主链部分吸收: + +1. `limecore` 负责在线目录事实源: + - `bootstrap.skillCatalog` + - `bootstrap.serviceSkillCatalog` + - `GET /api/v1/public/tenants/:tenantId/client/skills` + - `GET /api/v1/public/tenants/:tenantId/client/service-skills` +2. `lime` 负责本地 catalog 同步、seeded fallback、补参启动与执行路由。 +3. `skillCatalog.entries` 负责统一 `@ / / skill` 发现协议;`serviceSkillCatalog` 继续保留完整服务型技能目录,不与 `serviceCatalog` 混用。 + +因此,本文今天更适合作为跨仓产品边界说明,而不是单独的待落地提案。 ## 2. 背景与问题 @@ -117,17 +140,22 @@ Ribbi 这类产品最值得借鉴的,不是“49 个技能入口”或“看 ## 5.2 ServiceSkillCatalog -新的客户端目录字段命名为: +当前客户端目录已经分成两层: -`serviceSkillCatalog` +1. `skillCatalog` + - 聚合后的技能中心目录 + - `entries` 负责统一命令发现协议 +2. `serviceSkillCatalog` + - 完整服务型技能目录 + - 适合技能发布、诊断、细粒度刷新与运行时绑定解析 -而不是复用现有 `bootstrap.serviceCatalog`。 +`serviceSkillCatalog` 仍然不应复用 `serviceCatalog`。 原因: -- 现有 `serviceCatalog` 在 `limecore` 中偏商业服务目录与计费目录 -- 新目录是客户端任务入口目录,语义不同 -- 强行复用会让商业服务和服务型技能混成一层 +- `serviceCatalog` 在 `limecore` 中仍偏商业服务目录与计费目录 +- `skillCatalog` 与 `serviceSkillCatalog` 分别承担“统一发现”和“完整目录”两种不同职责 +- 强行混用会让商业服务、通用技能与服务型技能重新打成一团 建议结构: @@ -249,10 +277,11 @@ flowchart TB ### `limecore control-plane-svc` 负责 -- `serviceSkillCatalog` 下发 +- `bootstrap.skillCatalog` 与 `bootstrap.serviceSkillCatalog` 聚合 +- `client/skills` 与 `client/service-skills` 下发 - OEM/租户级目录配置 - 开关、排序、默认参数、版本 -- 客户端 bootstrap 聚合 +- 客户端 bootstrap 聚合与目录事实源发布 ### `limecore scene-orchestrator-svc` 负责 @@ -280,7 +309,7 @@ sequenceDiagram User->>Lime: 启动客户端 Lime->>CP: GET /client/bootstrap alt 拉取成功 - CP-->>Lime: bootstrap + serviceSkillCatalog + CP-->>Lime: bootstrap(skillCatalog + serviceSkillCatalog) Lime->>Cache: 写入目录缓存(version, syncedAt, items) Lime-->>User: 首页展示云目录服务项 else 拉取失败 @@ -493,7 +522,7 @@ flowchart LR ### Phase 1:目录与即时执行 -- `limecore` 下发 `serviceSkillCatalog` +- `limecore` 下发 `skillCatalog.entries` 与 `serviceSkillCatalog` - `lime` 接收并缓存云目录 - 首页展示服务型技能卡片 - 跑通 `instant + client_default` @@ -514,7 +543,7 @@ flowchart LR 满足以下条件视为本 PRD 成立: -1. 客户端可从 bootstrap 读取独立的 `serviceSkillCatalog`。 +1. 客户端可从 `bootstrap.skillCatalog + bootstrap.serviceSkillCatalog` 读取统一发现目录与完整服务型技能目录。 2. 云目录可本地缓存,离线时可回退展示。 3. 首页可直接启动服务型技能,而不是先选模型和能力开关。 4. 参数采集由 `slotSchema` 驱动,而不是纯 prompt 注入。 @@ -528,7 +557,7 @@ flowchart LR 1. 客户端职责膨胀风险 - 如果目录、参数采集、执行、任务中心同时无边界扩张,客户端仍会变重 2. 术语冲突风险 - - `serviceCatalog / sceneCatalog / serviceSkillCatalog` 若不统一,会让实现和产品都混乱 + - `serviceCatalog / skillCatalog / serviceSkillCatalog / sceneCatalog` 若不统一,会让实现和产品都混乱 3. 本地调度可靠性风险 - `scheduled / managed` 留在本地会受到应用在线状态影响 4. 云执行漂移风险 diff --git a/playwright-after-automation.yml b/playwright-after-automation.yml deleted file mode 100644 index 2764f424f..000000000 --- a/playwright-after-automation.yml +++ /dev/null @@ -1,41 +0,0 @@ -- generic [ref=e2]: - - generic [ref=e14]: - - complementary [ref=e15]: - - generic [ref=e16]: - - generic [ref=e17]: - - button "Lime Lime" [ref=e18] [cursor=pointer] - - button "折叠导航栏" [ref=e22] [cursor=pointer] - - button "搜索任务" [ref=e26] [cursor=pointer]: - - img [ref=e27] - - generic [ref=e30]: 搜索任务 - - generic [ref=e31]: - - generic [ref=e32]: - - generic [ref=e33]: 任务 - - button "新建任务" [ref=e34] [cursor=pointer] - - button "生成" [ref=e37] [cursor=pointer] - - generic [ref=e41]: - - generic [ref=e42]: 能力 - - button "我的方法" [ref=e43] [cursor=pointer] - - button "创作场景" [ref=e47] [cursor=pointer] - - button "持续流程" [active] [ref=e53] [cursor=pointer] - - button "消息渠道" [ref=e57] [cursor=pointer] - - generic [ref=e62]: - - generic [ref=e63]: 资料 - - button "资料库" [ref=e64] [cursor=pointer] - - button "灵感库" [ref=e68] [cursor=pointer] - - generic [ref=e82]: - - generic [ref=e83]: - - generic [ref=e84]: 系统 - - button "OpenClaw" [ref=e85] [cursor=pointer] - - button "设置" [ref=e90] [cursor=pointer] - - button "切换到深色模式" [ref=e96] [cursor=pointer]: - - img [ref=e97] - - main [ref=e103]: - - generic [ref=e630]: - - generic [ref=e632]: - - generic [ref=e633] - - generic [ref=e653] - - tabpanel [ref=e664]: - - generic [ref=e665] - - generic [ref=e734] - - region "Notifications alt+T" \ No newline at end of file diff --git a/playwright-automation-after-open.md b/playwright-automation-after-open.md deleted file mode 100644 index 7ee4d08a3..000000000 --- a/playwright-automation-after-open.md +++ /dev/null @@ -1,328 +0,0 @@ -- generic [ref=e2]: - - generic [ref=e4]: - - complementary [ref=e5]: - - generic [ref=e6]: - - generic [ref=e7]: - - button "Lime Lime" [ref=e8] [cursor=pointer]: - - img "Lime" [ref=e10] - - generic [ref=e11]: Lime - - button "折叠导航栏" [ref=e12] [cursor=pointer]: - - img [ref=e13] - - button "搜索任务" [ref=e16] [cursor=pointer]: - - img [ref=e17] - - generic [ref=e20]: 搜索任务 - - generic [ref=e21]: - - generic [ref=e22]: - - generic [ref=e23]: 任务 - - button "新建任务" [ref=e24] [cursor=pointer]: - - img [ref=e25] - - generic [ref=e26]: 新建任务 - - button "生成" [ref=e27] [cursor=pointer]: - - img [ref=e28] - - generic [ref=e30]: 生成 - - generic [ref=e31]: - - generic [ref=e32]: 能力 - - button "我的方法" [ref=e33] [cursor=pointer]: - - img [ref=e34] - - generic [ref=e36]: 我的方法 - - button "创作场景" [ref=e37] [cursor=pointer]: - - img [ref=e38] - - generic [ref=e42]: 创作场景 - - button "持续流程" [active] [ref=e43] [cursor=pointer]: - - img [ref=e44] - - generic [ref=e46]: 持续流程 - - button "消息渠道" [ref=e47] [cursor=pointer]: - - img [ref=e48] - - generic [ref=e51]: 消息渠道 - - generic [ref=e52]: - - generic [ref=e53]: 资料 - - button "资料库" [ref=e54] [cursor=pointer]: - - img [ref=e55] - - generic [ref=e57]: 资料库 - - button "灵感库" [ref=e58] [cursor=pointer]: - - img [ref=e59] - - generic [ref=e71]: 灵感库 - - generic [ref=e72]: - - generic [ref=e73]: - - generic [ref=e74]: 系统 - - button "OpenClaw" [ref=e75] [cursor=pointer]: - - img [ref=e76] - - generic [ref=e79]: OpenClaw - - button "设置" [ref=e80] [cursor=pointer]: - - img [ref=e81] - - generic [ref=e84]: 设置 - - button "切换到深色模式" [ref=e86] [cursor=pointer]: - - img [ref=e87] - - main [ref=e93]: - - generic [ref=e589]: - - generic [ref=e590]: - - generic [ref=e591]: - - generic [ref=e592]: - - generic [ref=e593]: CREATE SCENES - - heading "按创作场景组织完整结果链" [level=1] [ref=e594] - - paragraph [ref=e595]: 这里前台讲的是创作场景,不是内部 SceneApp 名词。每条场景都会带上参考素材、风格摘要、工具能力和交付合同,帮助你先完成选路与装配,再进入生成、结果交付和复盘。 - - button "刷新目录" [ref=e596] [cursor=pointer] - - generic [ref=e597]: - - generic [ref=e598]: - - button "场景目录" [ref=e599] [cursor=pointer] - - button "生成准备" [ref=e600] [cursor=pointer] - - button "治理复盘" [ref=e601] [cursor=pointer] - - paragraph [ref=e602]: 集中查看交付合同、上下文基线和进入生成前的准备。 - - generic [ref=e603]: - - generic [ref=e604]: 当前场景: - - generic [ref=e605]: 短视频编排 - - generic [ref=e606]: 把文本、线框图、配乐、剧本和短视频草稿收口成一条多模态结果链。 - - button "查看准备" [ref=e607] [cursor=pointer] - - button "查看治理" [ref=e608] [cursor=pointer] - - generic [ref=e609]: - - generic [ref=e611]: - - generic [ref=e612]: - - generic [ref=e613]: - - generic [ref=e614]: 多模态组合 - - heading "短视频编排" [level=2] [ref=e615] - - paragraph [ref=e616]: 把文本、线框图、配乐、剧本和短视频草稿收口成一条多模态结果链。 - - generic [ref=e617]: - - generic [ref=e618]: 多能力组合 - - generic [ref=e619]: 项目资料包 - - generic [ref=e620]: - - generic [ref=e621]: 从一句主题串起脚本、线框图、配乐方向和短视频草稿。 - - generic [ref=e622]: - - generic [ref=e623]: 产出:短视频项目包 - - generic [ref=e624]: 执行主链:云端 Scene - - generic [ref=e625]: 来源包:lime-core-sceneapps - - generic [ref=e626]: 版本:2026-04-15 - - generic [ref=e627]: - - generic [ref=e628]: - - generic [ref=e629]: 设计模式 - - generic [ref=e630]: - - generic [ref=e631]: 步骤链 - - generic [ref=e632]: 先补上下文 - - generic [ref=e633]: 结果生成 - - generic [ref=e634]: 质量复核 - - generic [ref=e635]: - - generic [ref=e636]: 启动前置 - - generic [ref=e637]: - - generic [ref=e638]: 需要主题、风格或脚本线索作为场景输入。 - - generic [ref=e639]: 需要项目目录承接线框图、脚本和媒体结果。 - - generic [ref=e640]: 需要可用的云端运行时来完成多模态媒体处理。 - - generic [ref=e641]: - - generic [ref=e642]: - - generic [ref=e643]: 交付合同 - - paragraph [ref=e644]: 这条 SceneApp 会把结果收口成一份可继续编辑的项目资料包,至少包含 任务简报、分镜 / 线框图、剧本、配乐建议、短视频草稿、复核意见。 - - generic [ref=e645]: - - generic [ref=e646]: 主结果:短视频项目包 - - generic [ref=e647]: 默认主件:任务简报 - - generic [ref=e648]: 查看方式:结果包查看 - - generic [ref=e649]: Artifact:story-video-artifacts - - generic [ref=e650]: - - generic [ref=e651]: 任务简报 - - generic [ref=e652]: 分镜 / 线框图 - - generic [ref=e653]: 剧本 - - generic [ref=e654]: 配乐建议 - - generic [ref=e655]: 短视频草稿 - - generic [ref=e656]: 复核意见 - - generic [ref=e657]: - - generic [ref=e658]: 组合步骤 - - generic [ref=e659]: - - generic [ref=e660]: 蓝图:story-video-blueprint - - generic [ref=e661]: 阶段数:6 - - generic [ref=e662]: - - generic [ref=e663]: - - generic [ref=e664]: 第 1 步 · 任务简报 - - generic [ref=e665]: 执行面:本机技能 - - generic [ref=e666]: - - generic [ref=e667]: 第 2 步 · 分镜 / 线框图 - - generic [ref=e668]: 执行面:本机技能 - - generic [ref=e669]: - - generic [ref=e670]: 第 3 步 · 剧本 - - generic [ref=e671]: 执行面:本机技能 - - generic [ref=e672]: - - generic [ref=e673]: 第 4 步 · 配乐建议 - - generic [ref=e674]: 执行面:云端 Scene - - generic [ref=e675]: - - generic [ref=e676]: 第 5 步 · 短视频草稿 - - generic [ref=e677]: 执行面:云端 Scene - - generic [ref=e678]: - - generic [ref=e679]: 第 6 步 · 复核意见 - - generic [ref=e680]: 执行面:本机技能 - - generic [ref=e681]: - - generic [ref=e682]: 评分口径 - - paragraph [ref=e683]: 经营上优先看整包是否交齐、是否通过复核,以及结果是否继续被打开编辑或发布。 - - generic [ref=e684]: Profile:story-video-scorecard - - generic [ref=e685]: - - generic [ref=e686]: 整包交付率 - - generic [ref=e687]: 复核通过率 - - generic [ref=e688]: 发布转化率 - - generic [ref=e689]: - - generic [ref=e690]: 重点关注 - - generic [ref=e691]: - - generic [ref=e692]: 整包不完整 - - generic [ref=e693]: 复核阻塞 - - generic [ref=e694]: 发布卡点 - - generic [ref=e695]: - - generic [ref=e696]: - - generic [ref=e697]: - - generic [ref=e698]: 执行预规划 - - generic [ref=e699]: 待补 1 项 - - paragraph [ref=e700]: 当前预规划已生成,但还有 1 项前置待补齐;补齐后会继续沿 云端 Scene 执行。 - - generic [ref=e701]: - - generic [ref=e702]: 仍待补齐 - - generic [ref=e704]: 需要可用的云端运行时来完成多模态媒体处理。 - - generic [ref=e705]: - - generic [ref=e706]: - - generic [ref=e707]: 活跃层 - - generic [ref=e708]: - - generic [ref=e709]: Skill - - generic [ref=e710]: Tool - - generic [ref=e711]: Memory - - generic [ref=e712]: Reference - - generic [ref=e713]: Taste - - generic [ref=e714]: 参考注入:1 条 - - generic [ref=e715]: 作用域:项目 849e36ff-8f64-45ed-ba51-aab6b8e182e4 - - generic [ref=e716]: - - generic [ref=e717]: 场景绑定 - - generic [ref=e718]: - - generic [ref=e719]: Story video suite - - generic [ref=e720]: Sceneapp service story video - - generic [ref=e721]: Story video blueprint - - generic [ref=e722]: - - generic [ref=e723]: 记忆引用 - - generic [ref=e724]: - - generic [ref=e725]: Workspace · 849e36ff-8f64-45ed-ba51-aab6b8e182e4 - - generic [ref=e726]: Project · 849e36ff-8f64-45ed-ba51-aab6b8e182e4 - - generic [ref=e727]: Memory profile · user_input - - generic [ref=e728]: - - generic [ref=e729]: 工具开放面 - - generic [ref=e730]: - - generic [ref=e731]: Cloud scene - - generic [ref=e732]: Native skill - - generic [ref=e733]: Workspace storage - - generic [ref=e734]: Artifact viewer - - generic [ref=e735]: - - generic [ref=e736]: 参考条目 - - generic [ref=e738]: - - generic [ref=e739]: - - generic [ref=e740]: 用户输入 - - generic [ref=e741]: 用户输入 - - generic [ref=e742]: 文本 - - generic [ref=e743]: 请围绕一个产品卖点,生成一版 30 秒短视频方案:先给脚本方向、镜头结构、线框图提示和配乐情绪。 - - generic [ref=e744]: 风格摘要:当前 TasteProfile 已在项目沉淀基础上,结合 1 条参考输入更新启发式摘要。 - - generic [ref=e745]: - - generic [ref=e746]: 偏好关键词 - - generic [ref=e747]: - - generic [ref=e748]: story-video - - generic [ref=e749]: mv-pipeline - - generic [ref=e750]: 短视频项目包 - - generic [ref=e751]: - - generic [ref=e752]: 避免方向 - - generic [ref=e754]: 偏离参考素材 - - generic [ref=e755]: - - generic [ref=e756]: 已装配 3 条 memory 引用。 - - generic [ref=e757]: 已从项目上下文恢复 1 条历史参考。 - - generic [ref=e758]: 本次新增 1 条参考输入,当前 planning 共带上 1 条参考。 - - generic [ref=e759]: 当前已复用项目级 TasteProfile,并按最新输入继续更新。 - - generic [ref=e761]: 当前 SceneApp 仍有未满足的启动前置条件。 - - generic [ref=e762]: - - generic [ref=e763]: Project Pack 规划 - - generic [ref=e764]: - - generic [ref=e765]: 交付形态:项目资料包 - - generic [ref=e766]: 完成策略:按必含部件判断整包完成度 - - generic [ref=e767]: 主件:任务简报 - - generic [ref=e768]: 查看方式:结果包查看 - - generic [ref=e769]: - - generic [ref=e770]: 任务简报 - - generic [ref=e771]: 分镜 / 线框图 - - generic [ref=e772]: 剧本 - - generic [ref=e773]: 配乐建议 - - generic [ref=e774]: 短视频草稿 - - generic [ref=e775]: 复核意见 - - generic [ref=e776]: - - generic [ref=e777]: 当前 SceneApp 以结果包作为默认交付单位。 - - generic [ref=e778]: 完整度将按 6 个必含部件判断。 - - generic [ref=e779]: 结果会优先回写到项目 849e36ff-8f64-45ed-ba51-aab6b8e182e4,便于继续编辑与复盘。 - - generic [ref=e780]: 结果包会连同参考与风格快照一起进入后续治理链。 - - generic [ref=e781]: 结果包可继续复用当前 viewer 主链打开与检查。 - - generic [ref=e782]: - - generic [ref=e783]: 启动输入 - - paragraph [ref=e784]: 这一步只负责补齐场景意图和上下文基线;真正执行会进入生成主执行面,继续复用 Agent 或自动化主链。 - - generic [ref=e785]: - - generic [ref=e786]: 项目工作区 - - button "📁 默认项目 默认" [ref=e787] [cursor=pointer]: - - generic [ref=e788]: - - generic [ref=e790]: 📁 - - generic [ref=e792]: - - generic [ref=e793]: 默认项目 - - generic [ref=e794]: 默认 - - img [ref=e796] - - generic [ref=e798]: - - generic [ref=e799]: 启动意图 - - textbox "请围绕一个产品卖点,生成一版 30 秒短视频方案:先给脚本方向、镜头结构、线框图提示和配乐情绪。" [ref=e800] - - generic [ref=e801]: - - generic [ref=e802]: 将使用内置起步稿启动 - - generic [ref=e803]: 请围绕一个产品卖点,生成一版 30 秒短视频方案:先给脚本方向、镜头结构、线框图提示和配乐情绪。 - - paragraph [ref=e804]: 写入当前场景基线会把这次显式带入的灵感对象、输入摘要和风格偏好沉淀到项目目录,供后续 planning 继续复用。 - - paragraph [ref=e805]: 先带入灵感对象或启动输入,再写入当前场景基线 - - generic [ref=e807]: - - button "写入当前场景基线" [disabled] - - button "进入生成" [ref=e808] [cursor=pointer] - - generic [ref=e809]: - - generic [ref=e810]: - - generic [ref=e811]: - - generic [ref=e812]: 经营评分 - - paragraph [ref=e813]: 用统一 scorecard 判断这个场景交付的结果是否值得继续放大、优化还是收口。 - - generic [ref=e814]: 适合继续启动 - - paragraph [ref=e815]: 基于最近 1 次真实运行,多模态组合场景的整包交付率为 0.0% ,复核通过率为 0.0% ,发布转化率为 100.0% 。当前主要阻塞集中在复核阻塞。当前样本已经以终态运行记录为主。 目前更适合继续扩大样本。 - - generic [ref=e816]: - - generic [ref=e817]: 当前经营口径 - - paragraph [ref=e818]: 经营上优先看整包是否交齐、是否通过复核,以及结果是否继续被打开编辑或发布。 - - generic [ref=e819]: 交付合同:项目资料包 - - generic [ref=e820]: 查看方式:结果包查看 - - generic [ref=e821]: 完成口径:按必含部件判断整包完成度 - - generic [ref=e822]: - - generic [ref=e823]: 任务简报 - - generic [ref=e824]: 分镜 / 线框图 - - generic [ref=e825]: 剧本 - - generic [ref=e826]: 配乐建议 - - generic [ref=e827]: 短视频草稿 - - generic [ref=e828]: 复核意见 - - generic [ref=e829]: Profile:story-video-scorecard - - generic [ref=e830]: - - generic [ref=e831]: 整包交付率 - - generic [ref=e832]: 复核通过率 - - generic [ref=e833]: 发布转化率 - - generic [ref=e834]: - - generic [ref=e835]: 整包不完整 - - generic [ref=e836]: 复核阻塞 - - generic [ref=e837]: 发布卡点 - - generic [ref=e838]: 当前主要阻塞:复核阻塞 - - generic [ref=e839]: - - generic [ref=e840]: 规划备注 - - generic [ref=e841]: - - generic [ref=e842]: 当前 SceneApp 以结果包作为默认交付单位。 - - generic [ref=e843]: 完整度将按 6 个必含部件判断。 - - generic [ref=e844]: 结果会优先回写到项目 849e36ff-8f64-45ed-ba51-aab6b8e182e4,便于继续编辑与复盘。 - - generic [ref=e845]: 结果包会连同参考与风格快照一起进入后续治理链。 - - generic [ref=e846]: 结果包可继续复用当前 viewer 主链打开与检查。 - - generic [ref=e847]: - - generic [ref=e848]: Planning 基线 - - generic [ref=e849]: 参考注入:1 条 - - generic [ref=e850]: 作用域:项目 849e36ff-8f64-45ed-ba51-aab6b8e182e4 - - generic [ref=e852]: 用户输入 · 复核阻塞 - - generic [ref=e853]: 风格摘要:当前 TasteProfile 已在项目沉淀基础上,结合 1 条参考输入更新启发式摘要。 - - generic [ref=e854]: 最近反馈:当前主要卡点是复核阻塞。经营上建议继续补样本。 - - generic [ref=e856]: 复核阻塞 - - generic [ref=e858]: 复核阻塞 - - generic [ref=e859]: - - article [ref=e860]: - - generic [ref=e861]: - - generic [ref=e862]: 整包交付率 - - generic [ref=e863]: "0" - - article [ref=e864]: - - generic [ref=e865]: - - generic [ref=e866]: 复核通过率 - - generic [ref=e867]: "0" - - article [ref=e868]: - - generic [ref=e869]: - - generic [ref=e870]: 发布转化率 - - generic [ref=e871]: "100" - - region "Notifications alt+T" \ No newline at end of file diff --git a/playwright-console-errors-after-reload.txt b/playwright-console-errors-after-reload.txt deleted file mode 100644 index d8f14e168..000000000 --- a/playwright-console-errors-after-reload.txt +++ /dev/null @@ -1,87 +0,0 @@ -Total messages: 51 (Errors: 10, Warnings: 3) -Returning 10 messages for level "error" - -[ERROR] [DevBridge] HTTP 调用失败: get_config Error: Failed to fetch (bridge health check failed) - at createBridgeConnectionFailureError (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:85:10) - at ensureBridgeReachable (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:151:11) - at async invokeViaHttp (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:324:5) - at async safeInvoke (http://127.0.0.1:1420/src/lib/dev-bridge/safeInvoke.ts:343:22) @ http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:349 -[ERROR] [DevBridge] HTTP 调用失败: get_config Error: Failed to fetch (bridge cooldown active) - at createBridgeConnectionFailureError (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:85:10) - at ensureBridgeReachable (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:112:11) - at invokeViaHttp (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:324:11) - at invoke (http://127.0.0.1:1420/src/lib/tauri-mock/core.ts:5753:20) - at invokeExplicitMock (http://127.0.0.1:1420/src/lib/dev-bridge/explicitMockFallback.ts:13:10) - at async safeInvoke (http://127.0.0.1:1420/src/lib/dev-bridge/safeInvoke.ts:363:24) @ http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:349 -[ERROR] [DevBridge] HTTP 调用失败: workspace_list Error: Failed to fetch (bridge cooldown active) - at createBridgeConnectionFailureError (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:85:10) - at ensureBridgeReachable (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:112:11) - at invokeViaHttp (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:324:11) - at safeInvoke (http://127.0.0.1:1420/src/lib/dev-bridge/safeInvoke.ts:343:28) - at listProjects (http://127.0.0.1:1420/src/lib/api/project.ts:37:26) - at http://127.0.0.1:1420/src/hooks/useProjects.ts:41:9 - at http://127.0.0.1:1420/src/hooks/useProjects.ts:145:5 - at commitHookEffectListMount (http://127.0.0.1:1420/node_modules/.vite-tauri/deps/chunk-5B54REGN.js?v=d1d1c67b:16915:34) - at commitPassiveMountOnFiber (http://127.0.0.1:1420/node_modules/.vite-tauri/deps/chunk-5B54REGN.js?v=d1d1c67b:18156:19) - at commitPassiveMountEffects_complete (http://127.0.0.1:1420/node_modules/.vite-tauri/deps/chunk-5B54REGN.js?v=d1d1c67b:18129:17) @ http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:349 -[ERROR] [DevBridge] HTTP 调用失败: workspace_get_default Error: Failed to fetch (bridge cooldown active) - at createBridgeConnectionFailureError (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:85:10) - at ensureBridgeReachable (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:112:11) - at invokeViaHttp (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:324:11) - at safeInvoke (http://127.0.0.1:1420/src/lib/dev-bridge/safeInvoke.ts:343:28) - at getDefaultProject (http://127.0.0.1:1420/src/lib/api/project.ts:45:25) - at http://127.0.0.1:1420/src/hooks/useProjects.ts:42:9 - at http://127.0.0.1:1420/src/hooks/useProjects.ts:145:5 - at commitHookEffectListMount (http://127.0.0.1:1420/node_modules/.vite-tauri/deps/chunk-5B54REGN.js?v=d1d1c67b:16915:34) - at commitPassiveMountOnFiber (http://127.0.0.1:1420/node_modules/.vite-tauri/deps/chunk-5B54REGN.js?v=d1d1c67b:18156:19) - at commitPassiveMountEffects_complete (http://127.0.0.1:1420/node_modules/.vite-tauri/deps/chunk-5B54REGN.js?v=d1d1c67b:18129:17) @ http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:349 -[ERROR] [DevBridge] HTTP 调用失败: sceneapp_list_catalog Error: Failed to fetch (bridge cooldown active) - at createBridgeConnectionFailureError (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:85:10) - at ensureBridgeReachable (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:112:11) - at invokeViaHttp (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:324:11) - at safeInvoke (http://127.0.0.1:1420/src/lib/dev-bridge/safeInvoke.ts:343:28) - at listSceneAppCatalog (http://127.0.0.1:1420/src/lib/api/sceneapp.ts:3:10) - at http://127.0.0.1:1420/src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.ts?t=1776433812565:40:10 - at commitHookEffectListMount (http://127.0.0.1:1420/node_modules/.vite-tauri/deps/chunk-5B54REGN.js?v=d1d1c67b:16915:34) - at commitPassiveMountOnFiber (http://127.0.0.1:1420/node_modules/.vite-tauri/deps/chunk-5B54REGN.js?v=d1d1c67b:18156:19) - at commitPassiveMountEffects_complete (http://127.0.0.1:1420/node_modules/.vite-tauri/deps/chunk-5B54REGN.js?v=d1d1c67b:18129:17) - at commitPassiveMountEffects_begin (http://127.0.0.1:1420/node_modules/.vite-tauri/deps/chunk-5B54REGN.js?v=d1d1c67b:18119:15) @ http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:349 -[ERROR] [DevBridge] HTTP 调用失败: get_or_create_default_project Error: Failed to fetch (bridge cooldown active) - at createBridgeConnectionFailureError (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:85:10) - at ensureBridgeReachable (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:112:11) - at invokeViaHttp (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:324:11) - at safeInvoke (http://127.0.0.1:1420/src/lib/dev-bridge/safeInvoke.ts:343:28) - at getOrCreateDefaultProject (http://127.0.0.1:1420/src/lib/api/project.ts:71:25) - at http://127.0.0.1:1420/src/hooks/useProjects.ts:137:27 - at ensureSelection (http://127.0.0.1:1420/src/components/projects/ProjectSelector.tsx:267:40) - at http://127.0.0.1:1420/src/components/projects/ProjectSelector.tsx:275:12 - at commitHookEffectListMount (http://127.0.0.1:1420/node_modules/.vite-tauri/deps/chunk-5B54REGN.js?v=d1d1c67b:16915:34) - at commitPassiveMountOnFiber (http://127.0.0.1:1420/node_modules/.vite-tauri/deps/chunk-5B54REGN.js?v=d1d1c67b:18156:19) @ http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:349 -[ERROR] [DevBridge] HTTP 调用失败: get_or_create_default_project Error: Failed to fetch (bridge cooldown active) - at createBridgeConnectionFailureError (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:85:10) - at ensureBridgeReachable (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:112:11) - at invokeViaHttp (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:324:11) - at invoke (http://127.0.0.1:1420/src/lib/tauri-mock/core.ts:5753:20) - at invokeExplicitMock (http://127.0.0.1:1420/src/lib/dev-bridge/explicitMockFallback.ts:13:10) @ http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:349 -[ERROR] 创建默认项目失败: Error: [DevBridge] 浏览器模式无法连接后端桥接,命令 "get_or_create_default_project" 执行失败。请先启动 Tauri 开发后端(例如 npm run tauri:dev 或 npm run tauri:dev:headless),并确认 http://127.0.0.1:3030 可访问。原始错误: Failed to fetch (bridge cooldown active) - at normalizeDevBridgeError (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:168:12) - at safeInvoke (http://127.0.0.1:1420/src/lib/dev-bridge/safeInvoke.ts:348:31) - at async getOrCreateDefaultProject (http://127.0.0.1:1420/src/lib/api/project.ts:71:19) - at async http://127.0.0.1:1420/src/hooks/useProjects.ts:137:21 - at async ensureSelection (http://127.0.0.1:1420/src/components/projects/ProjectSelector.tsx:267:34) @ http://127.0.0.1:1420/src/components/projects/ProjectSelector.tsx:271 -[ERROR] [DevBridge] HTTP 调用失败: workspace_list Error: Failed to fetch (bridge cooldown active) - at createBridgeConnectionFailureError (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:85:10) - at ensureBridgeReachable (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:112:11) - at invokeViaHttp (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:324:11) - at safeInvoke (http://127.0.0.1:1420/src/lib/dev-bridge/safeInvoke.ts:343:28) - at listProjects (http://127.0.0.1:1420/src/lib/api/project.ts:37:26) - at http://127.0.0.1:1420/src/hooks/useProjects.ts:41:9 - at http://127.0.0.1:1420/src/hooks/useProjects.ts:158:12 @ http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:349 -[ERROR] [DevBridge] HTTP 调用失败: workspace_get_default Error: Failed to fetch (bridge cooldown active) - at createBridgeConnectionFailureError (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:85:10) - at ensureBridgeReachable (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:112:11) - at invokeViaHttp (http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:324:11) - at safeInvoke (http://127.0.0.1:1420/src/lib/dev-bridge/safeInvoke.ts:343:28) - at getDefaultProject (http://127.0.0.1:1420/src/lib/api/project.ts:45:25) - at http://127.0.0.1:1420/src/hooks/useProjects.ts:42:9 - at http://127.0.0.1:1420/src/hooks/useProjects.ts:158:12 @ http://127.0.0.1:1420/src/lib/dev-bridge/http-client.ts:349 \ No newline at end of file diff --git a/playwright-network-sceneapps-before-return.txt b/playwright-network-sceneapps-before-return.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/playwright-sceneapps-after-automation.yml b/playwright-sceneapps-after-automation.yml deleted file mode 100644 index 5788408dd..000000000 --- a/playwright-sceneapps-after-automation.yml +++ /dev/null @@ -1,42 +0,0 @@ -- generic [ref=e2]: - - generic [ref=e14]: - - complementary [ref=e15]: - - generic [ref=e16]: - - generic [ref=e17]: - - button "Lime Lime" [ref=e18] [cursor=pointer] - - button "折叠导航栏" [ref=e22] [cursor=pointer] - - button "搜索任务" [ref=e26] [cursor=pointer]: - - img [ref=e27] - - generic [ref=e30]: 搜索任务 - - generic [ref=e31]: - - generic [ref=e32]: - - generic [ref=e33]: 任务 - - button "新建任务" [ref=e34] [cursor=pointer] - - button "生成" [ref=e37] [cursor=pointer] - - generic [ref=e41]: - - generic [ref=e42]: 能力 - - button "我的方法" [ref=e43] [cursor=pointer] - - button "创作场景" [active] [ref=e47] [cursor=pointer] - - button "持续流程" [ref=e53] [cursor=pointer] - - button "消息渠道" [ref=e57] [cursor=pointer] - - generic [ref=e62]: - - generic [ref=e63]: 资料 - - button "资料库" [ref=e64] [cursor=pointer] - - button "灵感库" [ref=e68] [cursor=pointer] - - generic [ref=e82]: - - generic [ref=e83]: - - generic [ref=e84]: 系统 - - button "OpenClaw" [ref=e85] [cursor=pointer] - - button "设置" [ref=e90] [cursor=pointer] - - button "切换到深色模式" [ref=e96] [cursor=pointer]: - - img [ref=e97] - - main [ref=e103]: - - generic [ref=e796]: - - generic [ref=e797]: - - generic [ref=e798] - - generic [ref=e804] - - generic [ref=e816]: - - generic [ref=e817] - - generic [ref=e835] - - generic [ref=e838] - - region "Notifications alt+T" \ No newline at end of file diff --git a/playwright-sceneapps-after-fix-1.yml b/playwright-sceneapps-after-fix-1.yml deleted file mode 100644 index de4706bf9..000000000 --- a/playwright-sceneapps-after-fix-1.yml +++ /dev/null @@ -1,79 +0,0 @@ -- generic [ref=e2]: - - generic [ref=e4]: - - complementary [ref=e5]: - - generic [ref=e6]: - - generic [ref=e7]: - - button "Lime Lime" [ref=e8] [cursor=pointer]: - - img "Lime" [ref=e10] - - generic [ref=e11]: Lime - - button "折叠导航栏" [ref=e12] [cursor=pointer]: - - img [ref=e13] - - button "搜索任务" [ref=e16] [cursor=pointer]: - - img [ref=e17] - - generic [ref=e20]: 搜索任务 - - generic [ref=e21]: - - generic [ref=e22]: - - generic [ref=e23]: 任务 - - button "新建任务" [ref=e24] [cursor=pointer]: - - img [ref=e25] - - generic [ref=e26]: 新建任务 - - button "生成" [ref=e27] [cursor=pointer]: - - img [ref=e28] - - generic [ref=e30]: 生成 - - generic [ref=e31]: - - generic [ref=e32]: 能力 - - button "我的方法" [ref=e33] [cursor=pointer]: - - img [ref=e34] - - generic [ref=e36]: 我的方法 - - button "创作场景" [ref=e37] [cursor=pointer]: - - img [ref=e38] - - generic [ref=e42]: 创作场景 - - button "持续流程" [ref=e43] [cursor=pointer]: - - img [ref=e44] - - generic [ref=e46]: 持续流程 - - button "消息渠道" [ref=e47] [cursor=pointer]: - - img [ref=e48] - - generic [ref=e51]: 消息渠道 - - generic [ref=e52]: - - generic [ref=e53]: 资料 - - button "资料库" [ref=e54] [cursor=pointer]: - - img [ref=e55] - - generic [ref=e57]: 资料库 - - button "灵感库" [ref=e58] [cursor=pointer]: - - img [ref=e59] - - generic [ref=e71]: 灵感库 - - generic [ref=e72]: - - generic [ref=e73]: - - generic [ref=e74]: 系统 - - button "OpenClaw" [ref=e75] [cursor=pointer]: - - img [ref=e76] - - generic [ref=e79]: OpenClaw - - button "设置" [ref=e80] [cursor=pointer]: - - img [ref=e81] - - generic [ref=e84]: 设置 - - button "切换到深色模式" [ref=e86] [cursor=pointer]: - - img [ref=e87] - - main [ref=e93]: - - generic [ref=e303]: - - generic [ref=e304]: - - generic [ref=e305]: - - generic [ref=e306] - - button "刷新目录" [ref=e310] [cursor=pointer] - - generic [ref=e311]: - - generic [ref=e312] - - paragraph [ref=e316]: 集中查看交付合同、上下文基线和进入生成前的准备。 - - generic [ref=e317] - - generic [ref=e323]: - - generic [ref=e325]: - - generic [ref=e326] - - generic [ref=e334] - - generic [ref=e341] - - generic [ref=e355] - - generic [ref=e409] - - generic [ref=e496] - - generic [ref=e523]: - - generic [ref=e524] - - paragraph [ref=e529]: 基于最近 1 次真实运行,多模态组合场景的整包交付率为 0.0% ,复核通过率为 0.0% ,发布转化率为 100.0% 。当前主要阻塞集中在复核阻塞。当前样本已经以终态运行记录为主。 目前更适合继续扩大样本。 - - generic [ref=e530] - - generic [ref=e573] - - region "Notifications alt+T" \ No newline at end of file diff --git a/playwright-sceneapps-after-fix-path.yml b/playwright-sceneapps-after-fix-path.yml deleted file mode 100644 index 8a927c224..000000000 --- a/playwright-sceneapps-after-fix-path.yml +++ /dev/null @@ -1,79 +0,0 @@ -- generic [ref=e2]: - - generic [ref=e4]: - - complementary [ref=e5]: - - generic [ref=e6]: - - generic [ref=e7]: - - button "Lime Lime" [ref=e8] [cursor=pointer]: - - img "Lime" [ref=e10] - - generic [ref=e11]: Lime - - button "折叠导航栏" [ref=e12] [cursor=pointer]: - - img [ref=e13] - - button "搜索任务" [ref=e16] [cursor=pointer]: - - img [ref=e17] - - generic [ref=e20]: 搜索任务 - - generic [ref=e21]: - - generic [ref=e22]: - - generic [ref=e23]: 任务 - - button "新建任务" [ref=e24] [cursor=pointer]: - - img [ref=e25] - - generic [ref=e26]: 新建任务 - - button "生成" [ref=e27] [cursor=pointer]: - - img [ref=e28] - - generic [ref=e30]: 生成 - - generic [ref=e31]: - - generic [ref=e32]: 能力 - - button "我的方法" [ref=e33] [cursor=pointer]: - - img [ref=e34] - - generic [ref=e36]: 我的方法 - - button "创作场景" [active] [ref=e37] [cursor=pointer]: - - img [ref=e38] - - generic [ref=e42]: 创作场景 - - button "持续流程" [ref=e43] [cursor=pointer]: - - img [ref=e44] - - generic [ref=e46]: 持续流程 - - button "消息渠道" [ref=e47] [cursor=pointer]: - - img [ref=e48] - - generic [ref=e51]: 消息渠道 - - generic [ref=e52]: - - generic [ref=e53]: 资料 - - button "资料库" [ref=e54] [cursor=pointer]: - - img [ref=e55] - - generic [ref=e57]: 资料库 - - button "灵感库" [ref=e58] [cursor=pointer]: - - img [ref=e59] - - generic [ref=e71]: 灵感库 - - generic [ref=e72]: - - generic [ref=e73]: - - generic [ref=e74]: 系统 - - button "OpenClaw" [ref=e75] [cursor=pointer]: - - img [ref=e76] - - generic [ref=e79]: OpenClaw - - button "设置" [ref=e80] [cursor=pointer]: - - img [ref=e81] - - generic [ref=e84]: 设置 - - button "切换到深色模式" [ref=e86] [cursor=pointer]: - - img [ref=e87] - - main [ref=e93]: - - generic [ref=e751]: - - generic [ref=e752]: - - generic [ref=e753]: - - generic [ref=e754] - - button "刷新目录" [ref=e758] [cursor=pointer] - - generic [ref=e759]: - - generic [ref=e760] - - paragraph [ref=e764]: 集中查看交付合同、上下文基线和进入生成前的准备。 - - generic [ref=e765] - - generic [ref=e771]: - - generic [ref=e773]: - - generic [ref=e774] - - generic [ref=e782] - - generic [ref=e789] - - generic [ref=e803] - - generic [ref=e857] - - generic [ref=e944] - - generic [ref=e971]: - - generic [ref=e972] - - paragraph [ref=e977]: 基于最近 1 次真实运行,多模态组合场景的整包交付率为 0.0% ,复核通过率为 0.0% ,发布转化率为 100.0% 。当前主要阻塞集中在复核阻塞。当前样本已经以终态运行记录为主。 目前更适合继续扩大样本。 - - generic [ref=e978] - - generic [ref=e1021] - - region "Notifications alt+T" \ No newline at end of file diff --git a/playwright-sceneapps-after-open.md b/playwright-sceneapps-after-open.md deleted file mode 100644 index 02d99970e..000000000 --- a/playwright-sceneapps-after-open.md +++ /dev/null @@ -1,328 +0,0 @@ -- generic [ref=e2]: - - generic [ref=e4]: - - complementary [ref=e5]: - - generic [ref=e6]: - - generic [ref=e7]: - - button "Lime Lime" [ref=e8] [cursor=pointer]: - - img "Lime" [ref=e10] - - generic [ref=e11]: Lime - - button "折叠导航栏" [ref=e12] [cursor=pointer]: - - img [ref=e13] - - button "搜索任务" [ref=e16] [cursor=pointer]: - - img [ref=e17] - - generic [ref=e20]: 搜索任务 - - generic [ref=e21]: - - generic [ref=e22]: - - generic [ref=e23]: 任务 - - button "新建任务" [ref=e24] [cursor=pointer]: - - img [ref=e25] - - generic [ref=e26]: 新建任务 - - button "生成" [ref=e27] [cursor=pointer]: - - img [ref=e28] - - generic [ref=e30]: 生成 - - generic [ref=e31]: - - generic [ref=e32]: 能力 - - button "我的方法" [ref=e33] [cursor=pointer]: - - img [ref=e34] - - generic [ref=e36]: 我的方法 - - button "创作场景" [active] [ref=e37] [cursor=pointer]: - - img [ref=e38] - - generic [ref=e42]: 创作场景 - - button "持续流程" [ref=e43] [cursor=pointer]: - - img [ref=e44] - - generic [ref=e46]: 持续流程 - - button "消息渠道" [ref=e47] [cursor=pointer]: - - img [ref=e48] - - generic [ref=e51]: 消息渠道 - - generic [ref=e52]: - - generic [ref=e53]: 资料 - - button "资料库" [ref=e54] [cursor=pointer]: - - img [ref=e55] - - generic [ref=e57]: 资料库 - - button "灵感库" [ref=e58] [cursor=pointer]: - - img [ref=e59] - - generic [ref=e71]: 灵感库 - - generic [ref=e72]: - - generic [ref=e73]: - - generic [ref=e74]: 系统 - - button "OpenClaw" [ref=e75] [cursor=pointer]: - - img [ref=e76] - - generic [ref=e79]: OpenClaw - - button "设置" [ref=e80] [cursor=pointer]: - - img [ref=e81] - - generic [ref=e84]: 设置 - - button "切换到深色模式" [ref=e86] [cursor=pointer]: - - img [ref=e87] - - main [ref=e93]: - - generic [ref=e304]: - - generic [ref=e305]: - - generic [ref=e306]: - - generic [ref=e307]: - - generic [ref=e308]: CREATE SCENES - - heading "按创作场景组织完整结果链" [level=1] [ref=e309] - - paragraph [ref=e310]: 这里前台讲的是创作场景,不是内部 SceneApp 名词。每条场景都会带上参考素材、风格摘要、工具能力和交付合同,帮助你先完成选路与装配,再进入生成、结果交付和复盘。 - - button "刷新目录" [ref=e311] [cursor=pointer] - - generic [ref=e312]: - - generic [ref=e313]: - - button "场景目录" [ref=e314] [cursor=pointer] - - button "生成准备" [ref=e315] [cursor=pointer] - - button "治理复盘" [ref=e316] [cursor=pointer] - - paragraph [ref=e317]: 集中查看交付合同、上下文基线和进入生成前的准备。 - - generic [ref=e318]: - - generic [ref=e319]: 当前场景: - - generic [ref=e320]: 短视频编排 - - generic [ref=e321]: 把文本、线框图、配乐、剧本和短视频草稿收口成一条多模态结果链。 - - button "查看准备" [ref=e322] [cursor=pointer] - - button "查看治理" [ref=e323] [cursor=pointer] - - generic [ref=e324]: - - generic [ref=e326]: - - generic [ref=e327]: - - generic [ref=e328]: - - generic [ref=e329]: 多模态组合 - - heading "短视频编排" [level=2] [ref=e330] - - paragraph [ref=e331]: 把文本、线框图、配乐、剧本和短视频草稿收口成一条多模态结果链。 - - generic [ref=e332]: - - generic [ref=e333]: 多能力组合 - - generic [ref=e334]: 项目资料包 - - generic [ref=e335]: - - generic [ref=e336]: 从一句主题串起脚本、线框图、配乐方向和短视频草稿。 - - generic [ref=e337]: - - generic [ref=e338]: 产出:短视频项目包 - - generic [ref=e339]: 执行主链:云端 Scene - - generic [ref=e340]: 来源包:lime-core-sceneapps - - generic [ref=e341]: 版本:2026-04-15 - - generic [ref=e342]: - - generic [ref=e343]: - - generic [ref=e344]: 设计模式 - - generic [ref=e345]: - - generic [ref=e346]: 步骤链 - - generic [ref=e347]: 先补上下文 - - generic [ref=e348]: 结果生成 - - generic [ref=e349]: 质量复核 - - generic [ref=e350]: - - generic [ref=e351]: 启动前置 - - generic [ref=e352]: - - generic [ref=e353]: 需要主题、风格或脚本线索作为场景输入。 - - generic [ref=e354]: 需要项目目录承接线框图、脚本和媒体结果。 - - generic [ref=e355]: 需要可用的云端运行时来完成多模态媒体处理。 - - generic [ref=e356]: - - generic [ref=e357]: - - generic [ref=e358]: 交付合同 - - paragraph [ref=e359]: 这条 SceneApp 会把结果收口成一份可继续编辑的项目资料包,至少包含 任务简报、分镜 / 线框图、剧本、配乐建议、短视频草稿、复核意见。 - - generic [ref=e360]: - - generic [ref=e361]: 主结果:短视频项目包 - - generic [ref=e362]: 默认主件:任务简报 - - generic [ref=e363]: 查看方式:结果包查看 - - generic [ref=e364]: Artifact:story-video-artifacts - - generic [ref=e365]: - - generic [ref=e366]: 任务简报 - - generic [ref=e367]: 分镜 / 线框图 - - generic [ref=e368]: 剧本 - - generic [ref=e369]: 配乐建议 - - generic [ref=e370]: 短视频草稿 - - generic [ref=e371]: 复核意见 - - generic [ref=e372]: - - generic [ref=e373]: 组合步骤 - - generic [ref=e374]: - - generic [ref=e375]: 蓝图:story-video-blueprint - - generic [ref=e376]: 阶段数:6 - - generic [ref=e377]: - - generic [ref=e378]: - - generic [ref=e379]: 第 1 步 · 任务简报 - - generic [ref=e380]: 执行面:本机技能 - - generic [ref=e381]: - - generic [ref=e382]: 第 2 步 · 分镜 / 线框图 - - generic [ref=e383]: 执行面:本机技能 - - generic [ref=e384]: - - generic [ref=e385]: 第 3 步 · 剧本 - - generic [ref=e386]: 执行面:本机技能 - - generic [ref=e387]: - - generic [ref=e388]: 第 4 步 · 配乐建议 - - generic [ref=e389]: 执行面:云端 Scene - - generic [ref=e390]: - - generic [ref=e391]: 第 5 步 · 短视频草稿 - - generic [ref=e392]: 执行面:云端 Scene - - generic [ref=e393]: - - generic [ref=e394]: 第 6 步 · 复核意见 - - generic [ref=e395]: 执行面:本机技能 - - generic [ref=e396]: - - generic [ref=e397]: 评分口径 - - paragraph [ref=e398]: 经营上优先看整包是否交齐、是否通过复核,以及结果是否继续被打开编辑或发布。 - - generic [ref=e399]: Profile:story-video-scorecard - - generic [ref=e400]: - - generic [ref=e401]: 整包交付率 - - generic [ref=e402]: 复核通过率 - - generic [ref=e403]: 发布转化率 - - generic [ref=e404]: - - generic [ref=e405]: 重点关注 - - generic [ref=e406]: - - generic [ref=e407]: 整包不完整 - - generic [ref=e408]: 复核阻塞 - - generic [ref=e409]: 发布卡点 - - generic [ref=e410]: - - generic [ref=e411]: - - generic [ref=e412]: - - generic [ref=e413]: 执行预规划 - - generic [ref=e414]: 待补 1 项 - - paragraph [ref=e415]: 当前预规划已生成,但还有 1 项前置待补齐;补齐后会继续沿 云端 Scene 执行。 - - generic [ref=e416]: - - generic [ref=e417]: 仍待补齐 - - generic [ref=e419]: 需要可用的云端运行时来完成多模态媒体处理。 - - generic [ref=e420]: - - generic [ref=e421]: - - generic [ref=e422]: 活跃层 - - generic [ref=e423]: - - generic [ref=e424]: Skill - - generic [ref=e425]: Tool - - generic [ref=e426]: Memory - - generic [ref=e427]: Reference - - generic [ref=e428]: Taste - - generic [ref=e429]: 参考注入:1 条 - - generic [ref=e430]: 作用域:项目 849e36ff-8f64-45ed-ba51-aab6b8e182e4 - - generic [ref=e431]: - - generic [ref=e432]: 场景绑定 - - generic [ref=e433]: - - generic [ref=e434]: Story video suite - - generic [ref=e435]: Sceneapp service story video - - generic [ref=e436]: Story video blueprint - - generic [ref=e437]: - - generic [ref=e438]: 记忆引用 - - generic [ref=e439]: - - generic [ref=e440]: Workspace · 849e36ff-8f64-45ed-ba51-aab6b8e182e4 - - generic [ref=e441]: Project · 849e36ff-8f64-45ed-ba51-aab6b8e182e4 - - generic [ref=e442]: Memory profile · user_input - - generic [ref=e443]: - - generic [ref=e444]: 工具开放面 - - generic [ref=e445]: - - generic [ref=e446]: Cloud scene - - generic [ref=e447]: Native skill - - generic [ref=e448]: Workspace storage - - generic [ref=e449]: Artifact viewer - - generic [ref=e450]: - - generic [ref=e451]: 参考条目 - - generic [ref=e453]: - - generic [ref=e454]: - - generic [ref=e455]: 用户输入 - - generic [ref=e456]: 用户输入 - - generic [ref=e457]: 文本 - - generic [ref=e458]: 请围绕一个产品卖点,生成一版 30 秒短视频方案:先给脚本方向、镜头结构、线框图提示和配乐情绪。 - - generic [ref=e459]: 风格摘要:当前 TasteProfile 已在项目沉淀基础上,结合 1 条参考输入更新启发式摘要。 - - generic [ref=e460]: - - generic [ref=e461]: 偏好关键词 - - generic [ref=e462]: - - generic [ref=e463]: story-video - - generic [ref=e464]: mv-pipeline - - generic [ref=e465]: 短视频项目包 - - generic [ref=e466]: - - generic [ref=e467]: 避免方向 - - generic [ref=e469]: 偏离参考素材 - - generic [ref=e470]: - - generic [ref=e471]: 已装配 3 条 memory 引用。 - - generic [ref=e472]: 已从项目上下文恢复 1 条历史参考。 - - generic [ref=e473]: 本次新增 1 条参考输入,当前 planning 共带上 1 条参考。 - - generic [ref=e474]: 当前已复用项目级 TasteProfile,并按最新输入继续更新。 - - generic [ref=e476]: 当前 SceneApp 仍有未满足的启动前置条件。 - - generic [ref=e477]: - - generic [ref=e478]: Project Pack 规划 - - generic [ref=e479]: - - generic [ref=e480]: 交付形态:项目资料包 - - generic [ref=e481]: 完成策略:按必含部件判断整包完成度 - - generic [ref=e482]: 主件:任务简报 - - generic [ref=e483]: 查看方式:结果包查看 - - generic [ref=e484]: - - generic [ref=e485]: 任务简报 - - generic [ref=e486]: 分镜 / 线框图 - - generic [ref=e487]: 剧本 - - generic [ref=e488]: 配乐建议 - - generic [ref=e489]: 短视频草稿 - - generic [ref=e490]: 复核意见 - - generic [ref=e491]: - - generic [ref=e492]: 当前 SceneApp 以结果包作为默认交付单位。 - - generic [ref=e493]: 完整度将按 6 个必含部件判断。 - - generic [ref=e494]: 结果会优先回写到项目 849e36ff-8f64-45ed-ba51-aab6b8e182e4,便于继续编辑与复盘。 - - generic [ref=e495]: 结果包会连同参考与风格快照一起进入后续治理链。 - - generic [ref=e496]: 结果包可继续复用当前 viewer 主链打开与检查。 - - generic [ref=e497]: - - generic [ref=e498]: 启动输入 - - paragraph [ref=e499]: 这一步只负责补齐场景意图和上下文基线;真正执行会进入生成主执行面,继续复用 Agent 或自动化主链。 - - generic [ref=e500]: - - generic [ref=e501]: 项目工作区 - - button "📁 默认项目 默认" [ref=e502] [cursor=pointer]: - - generic [ref=e503]: - - generic [ref=e505]: 📁 - - generic [ref=e507]: - - generic [ref=e508]: 默认项目 - - generic [ref=e509]: 默认 - - img [ref=e511] - - generic [ref=e513]: - - generic [ref=e514]: 启动意图 - - textbox "请围绕一个产品卖点,生成一版 30 秒短视频方案:先给脚本方向、镜头结构、线框图提示和配乐情绪。" [ref=e515] - - generic [ref=e516]: - - generic [ref=e517]: 将使用内置起步稿启动 - - generic [ref=e518]: 请围绕一个产品卖点,生成一版 30 秒短视频方案:先给脚本方向、镜头结构、线框图提示和配乐情绪。 - - paragraph [ref=e519]: 写入当前场景基线会把这次显式带入的灵感对象、输入摘要和风格偏好沉淀到项目目录,供后续 planning 继续复用。 - - paragraph [ref=e520]: 先带入灵感对象或启动输入,再写入当前场景基线 - - generic [ref=e522]: - - button "写入当前场景基线" [disabled] - - button "进入生成" [ref=e523] [cursor=pointer] - - generic [ref=e524]: - - generic [ref=e525]: - - generic [ref=e526]: - - generic [ref=e527]: 经营评分 - - paragraph [ref=e528]: 用统一 scorecard 判断这个场景交付的结果是否值得继续放大、优化还是收口。 - - generic [ref=e529]: 适合继续启动 - - paragraph [ref=e530]: 基于最近 1 次真实运行,多模态组合场景的整包交付率为 0.0% ,复核通过率为 0.0% ,发布转化率为 100.0% 。当前主要阻塞集中在复核阻塞。当前样本已经以终态运行记录为主。 目前更适合继续扩大样本。 - - generic [ref=e531]: - - generic [ref=e532]: 当前经营口径 - - paragraph [ref=e533]: 经营上优先看整包是否交齐、是否通过复核,以及结果是否继续被打开编辑或发布。 - - generic [ref=e534]: 交付合同:项目资料包 - - generic [ref=e535]: 查看方式:结果包查看 - - generic [ref=e536]: 完成口径:按必含部件判断整包完成度 - - generic [ref=e537]: - - generic [ref=e538]: 任务简报 - - generic [ref=e539]: 分镜 / 线框图 - - generic [ref=e540]: 剧本 - - generic [ref=e541]: 配乐建议 - - generic [ref=e542]: 短视频草稿 - - generic [ref=e543]: 复核意见 - - generic [ref=e544]: Profile:story-video-scorecard - - generic [ref=e545]: - - generic [ref=e546]: 整包交付率 - - generic [ref=e547]: 复核通过率 - - generic [ref=e548]: 发布转化率 - - generic [ref=e549]: - - generic [ref=e550]: 整包不完整 - - generic [ref=e551]: 复核阻塞 - - generic [ref=e552]: 发布卡点 - - generic [ref=e553]: 当前主要阻塞:复核阻塞 - - generic [ref=e554]: - - generic [ref=e555]: 规划备注 - - generic [ref=e556]: - - generic [ref=e557]: 当前 SceneApp 以结果包作为默认交付单位。 - - generic [ref=e558]: 完整度将按 6 个必含部件判断。 - - generic [ref=e559]: 结果会优先回写到项目 849e36ff-8f64-45ed-ba51-aab6b8e182e4,便于继续编辑与复盘。 - - generic [ref=e560]: 结果包会连同参考与风格快照一起进入后续治理链。 - - generic [ref=e561]: 结果包可继续复用当前 viewer 主链打开与检查。 - - generic [ref=e562]: - - generic [ref=e563]: Planning 基线 - - generic [ref=e564]: 参考注入:1 条 - - generic [ref=e565]: 作用域:项目 849e36ff-8f64-45ed-ba51-aab6b8e182e4 - - generic [ref=e567]: 用户输入 · 复核阻塞 - - generic [ref=e568]: 风格摘要:当前 TasteProfile 已在项目沉淀基础上,结合 1 条参考输入更新启发式摘要。 - - generic [ref=e569]: 最近反馈:当前主要卡点是复核阻塞。经营上建议继续补样本。 - - generic [ref=e571]: 复核阻塞 - - generic [ref=e573]: 复核阻塞 - - generic [ref=e574]: - - article [ref=e575]: - - generic [ref=e576]: - - generic [ref=e577]: 整包交付率 - - generic [ref=e578]: "0" - - article [ref=e579]: - - generic [ref=e580]: - - generic [ref=e581]: 复核通过率 - - generic [ref=e582]: "0" - - article [ref=e583]: - - generic [ref=e584]: - - generic [ref=e585]: 发布转化率 - - generic [ref=e586]: "100" - - region "Notifications alt+T" \ No newline at end of file diff --git a/playwright-sceneapps-after-return.md b/playwright-sceneapps-after-return.md deleted file mode 100644 index fead3c403..000000000 --- a/playwright-sceneapps-after-return.md +++ /dev/null @@ -1,328 +0,0 @@ -- generic [ref=e2]: - - generic [ref=e4]: - - complementary [ref=e5]: - - generic [ref=e6]: - - generic [ref=e7]: - - button "Lime Lime" [ref=e8] [cursor=pointer]: - - img "Lime" [ref=e10] - - generic [ref=e11]: Lime - - button "折叠导航栏" [ref=e12] [cursor=pointer]: - - img [ref=e13] - - button "搜索任务" [ref=e16] [cursor=pointer]: - - img [ref=e17] - - generic [ref=e20]: 搜索任务 - - generic [ref=e21]: - - generic [ref=e22]: - - generic [ref=e23]: 任务 - - button "新建任务" [ref=e24] [cursor=pointer]: - - img [ref=e25] - - generic [ref=e26]: 新建任务 - - button "生成" [ref=e27] [cursor=pointer]: - - img [ref=e28] - - generic [ref=e30]: 生成 - - generic [ref=e31]: - - generic [ref=e32]: 能力 - - button "我的方法" [ref=e33] [cursor=pointer]: - - img [ref=e34] - - generic [ref=e36]: 我的方法 - - button "创作场景" [active] [ref=e37] [cursor=pointer]: - - img [ref=e38] - - generic [ref=e42]: 创作场景 - - button "持续流程" [ref=e43] [cursor=pointer]: - - img [ref=e44] - - generic [ref=e46]: 持续流程 - - button "消息渠道" [ref=e47] [cursor=pointer]: - - img [ref=e48] - - generic [ref=e51]: 消息渠道 - - generic [ref=e52]: - - generic [ref=e53]: 资料 - - button "资料库" [ref=e54] [cursor=pointer]: - - img [ref=e55] - - generic [ref=e57]: 资料库 - - button "灵感库" [ref=e58] [cursor=pointer]: - - img [ref=e59] - - generic [ref=e71]: 灵感库 - - generic [ref=e72]: - - generic [ref=e73]: - - generic [ref=e74]: 系统 - - button "OpenClaw" [ref=e75] [cursor=pointer]: - - img [ref=e76] - - generic [ref=e79]: OpenClaw - - button "设置" [ref=e80] [cursor=pointer]: - - img [ref=e81] - - generic [ref=e84]: 设置 - - button "切换到深色模式" [ref=e86] [cursor=pointer]: - - img [ref=e87] - - main [ref=e93]: - - generic [ref=e589]: - - generic [ref=e590]: - - generic [ref=e591]: - - generic [ref=e592]: - - generic [ref=e593]: CREATE SCENES - - heading "按创作场景组织完整结果链" [level=1] [ref=e594] - - paragraph [ref=e595]: 这里前台讲的是创作场景,不是内部 SceneApp 名词。每条场景都会带上参考素材、风格摘要、工具能力和交付合同,帮助你先完成选路与装配,再进入生成、结果交付和复盘。 - - button "刷新目录" [ref=e596] [cursor=pointer] - - generic [ref=e597]: - - generic [ref=e598]: - - button "场景目录" [ref=e599] [cursor=pointer] - - button "生成准备" [ref=e600] [cursor=pointer] - - button "治理复盘" [ref=e601] [cursor=pointer] - - paragraph [ref=e602]: 集中查看交付合同、上下文基线和进入生成前的准备。 - - generic [ref=e603]: - - generic [ref=e604]: 当前场景: - - generic [ref=e605]: 短视频编排 - - generic [ref=e606]: 把文本、线框图、配乐、剧本和短视频草稿收口成一条多模态结果链。 - - button "查看准备" [ref=e607] [cursor=pointer] - - button "查看治理" [ref=e608] [cursor=pointer] - - generic [ref=e609]: - - generic [ref=e611]: - - generic [ref=e612]: - - generic [ref=e613]: - - generic [ref=e614]: 多模态组合 - - heading "短视频编排" [level=2] [ref=e615] - - paragraph [ref=e616]: 把文本、线框图、配乐、剧本和短视频草稿收口成一条多模态结果链。 - - generic [ref=e617]: - - generic [ref=e618]: 多能力组合 - - generic [ref=e619]: 项目资料包 - - generic [ref=e620]: - - generic [ref=e621]: 从一句主题串起脚本、线框图、配乐方向和短视频草稿。 - - generic [ref=e622]: - - generic [ref=e623]: 产出:短视频项目包 - - generic [ref=e624]: 执行主链:云端 Scene - - generic [ref=e625]: 来源包:lime-core-sceneapps - - generic [ref=e626]: 版本:2026-04-15 - - generic [ref=e627]: - - generic [ref=e628]: - - generic [ref=e629]: 设计模式 - - generic [ref=e630]: - - generic [ref=e631]: 步骤链 - - generic [ref=e632]: 先补上下文 - - generic [ref=e633]: 结果生成 - - generic [ref=e634]: 质量复核 - - generic [ref=e635]: - - generic [ref=e636]: 启动前置 - - generic [ref=e637]: - - generic [ref=e638]: 需要主题、风格或脚本线索作为场景输入。 - - generic [ref=e639]: 需要项目目录承接线框图、脚本和媒体结果。 - - generic [ref=e640]: 需要可用的云端运行时来完成多模态媒体处理。 - - generic [ref=e641]: - - generic [ref=e642]: - - generic [ref=e643]: 交付合同 - - paragraph [ref=e644]: 这条 SceneApp 会把结果收口成一份可继续编辑的项目资料包,至少包含 任务简报、分镜 / 线框图、剧本、配乐建议、短视频草稿、复核意见。 - - generic [ref=e645]: - - generic [ref=e646]: 主结果:短视频项目包 - - generic [ref=e647]: 默认主件:任务简报 - - generic [ref=e648]: 查看方式:结果包查看 - - generic [ref=e649]: Artifact:story-video-artifacts - - generic [ref=e650]: - - generic [ref=e651]: 任务简报 - - generic [ref=e652]: 分镜 / 线框图 - - generic [ref=e653]: 剧本 - - generic [ref=e654]: 配乐建议 - - generic [ref=e655]: 短视频草稿 - - generic [ref=e656]: 复核意见 - - generic [ref=e657]: - - generic [ref=e658]: 组合步骤 - - generic [ref=e659]: - - generic [ref=e660]: 蓝图:story-video-blueprint - - generic [ref=e661]: 阶段数:6 - - generic [ref=e662]: - - generic [ref=e663]: - - generic [ref=e664]: 第 1 步 · 任务简报 - - generic [ref=e665]: 执行面:本机技能 - - generic [ref=e666]: - - generic [ref=e667]: 第 2 步 · 分镜 / 线框图 - - generic [ref=e668]: 执行面:本机技能 - - generic [ref=e669]: - - generic [ref=e670]: 第 3 步 · 剧本 - - generic [ref=e671]: 执行面:本机技能 - - generic [ref=e672]: - - generic [ref=e673]: 第 4 步 · 配乐建议 - - generic [ref=e674]: 执行面:云端 Scene - - generic [ref=e675]: - - generic [ref=e676]: 第 5 步 · 短视频草稿 - - generic [ref=e677]: 执行面:云端 Scene - - generic [ref=e678]: - - generic [ref=e679]: 第 6 步 · 复核意见 - - generic [ref=e680]: 执行面:本机技能 - - generic [ref=e681]: - - generic [ref=e682]: 评分口径 - - paragraph [ref=e683]: 经营上优先看整包是否交齐、是否通过复核,以及结果是否继续被打开编辑或发布。 - - generic [ref=e684]: Profile:story-video-scorecard - - generic [ref=e685]: - - generic [ref=e686]: 整包交付率 - - generic [ref=e687]: 复核通过率 - - generic [ref=e688]: 发布转化率 - - generic [ref=e689]: - - generic [ref=e690]: 重点关注 - - generic [ref=e691]: - - generic [ref=e692]: 整包不完整 - - generic [ref=e693]: 复核阻塞 - - generic [ref=e694]: 发布卡点 - - generic [ref=e695]: - - generic [ref=e696]: - - generic [ref=e697]: - - generic [ref=e698]: 执行预规划 - - generic [ref=e699]: 待补 1 项 - - paragraph [ref=e700]: 当前预规划已生成,但还有 1 项前置待补齐;补齐后会继续沿 云端 Scene 执行。 - - generic [ref=e701]: - - generic [ref=e702]: 仍待补齐 - - generic [ref=e704]: 需要可用的云端运行时来完成多模态媒体处理。 - - generic [ref=e705]: - - generic [ref=e706]: - - generic [ref=e707]: 活跃层 - - generic [ref=e708]: - - generic [ref=e709]: Skill - - generic [ref=e710]: Tool - - generic [ref=e711]: Memory - - generic [ref=e712]: Reference - - generic [ref=e713]: Taste - - generic [ref=e714]: 参考注入:1 条 - - generic [ref=e715]: 作用域:项目 849e36ff-8f64-45ed-ba51-aab6b8e182e4 - - generic [ref=e716]: - - generic [ref=e717]: 场景绑定 - - generic [ref=e718]: - - generic [ref=e719]: Story video suite - - generic [ref=e720]: Sceneapp service story video - - generic [ref=e721]: Story video blueprint - - generic [ref=e722]: - - generic [ref=e723]: 记忆引用 - - generic [ref=e724]: - - generic [ref=e725]: Workspace · 849e36ff-8f64-45ed-ba51-aab6b8e182e4 - - generic [ref=e726]: Project · 849e36ff-8f64-45ed-ba51-aab6b8e182e4 - - generic [ref=e727]: Memory profile · user_input - - generic [ref=e728]: - - generic [ref=e729]: 工具开放面 - - generic [ref=e730]: - - generic [ref=e731]: Cloud scene - - generic [ref=e732]: Native skill - - generic [ref=e733]: Workspace storage - - generic [ref=e734]: Artifact viewer - - generic [ref=e735]: - - generic [ref=e736]: 参考条目 - - generic [ref=e738]: - - generic [ref=e739]: - - generic [ref=e740]: 用户输入 - - generic [ref=e741]: 用户输入 - - generic [ref=e742]: 文本 - - generic [ref=e743]: 请围绕一个产品卖点,生成一版 30 秒短视频方案:先给脚本方向、镜头结构、线框图提示和配乐情绪。 - - generic [ref=e744]: 风格摘要:当前 TasteProfile 已在项目沉淀基础上,结合 1 条参考输入更新启发式摘要。 - - generic [ref=e745]: - - generic [ref=e746]: 偏好关键词 - - generic [ref=e747]: - - generic [ref=e748]: story-video - - generic [ref=e749]: mv-pipeline - - generic [ref=e750]: 短视频项目包 - - generic [ref=e751]: - - generic [ref=e752]: 避免方向 - - generic [ref=e754]: 偏离参考素材 - - generic [ref=e755]: - - generic [ref=e756]: 已装配 3 条 memory 引用。 - - generic [ref=e757]: 已从项目上下文恢复 1 条历史参考。 - - generic [ref=e758]: 本次新增 1 条参考输入,当前 planning 共带上 1 条参考。 - - generic [ref=e759]: 当前已复用项目级 TasteProfile,并按最新输入继续更新。 - - generic [ref=e761]: 当前 SceneApp 仍有未满足的启动前置条件。 - - generic [ref=e762]: - - generic [ref=e763]: Project Pack 规划 - - generic [ref=e764]: - - generic [ref=e765]: 交付形态:项目资料包 - - generic [ref=e766]: 完成策略:按必含部件判断整包完成度 - - generic [ref=e767]: 主件:任务简报 - - generic [ref=e768]: 查看方式:结果包查看 - - generic [ref=e769]: - - generic [ref=e770]: 任务简报 - - generic [ref=e771]: 分镜 / 线框图 - - generic [ref=e772]: 剧本 - - generic [ref=e773]: 配乐建议 - - generic [ref=e774]: 短视频草稿 - - generic [ref=e775]: 复核意见 - - generic [ref=e776]: - - generic [ref=e777]: 当前 SceneApp 以结果包作为默认交付单位。 - - generic [ref=e778]: 完整度将按 6 个必含部件判断。 - - generic [ref=e779]: 结果会优先回写到项目 849e36ff-8f64-45ed-ba51-aab6b8e182e4,便于继续编辑与复盘。 - - generic [ref=e780]: 结果包会连同参考与风格快照一起进入后续治理链。 - - generic [ref=e781]: 结果包可继续复用当前 viewer 主链打开与检查。 - - generic [ref=e782]: - - generic [ref=e783]: 启动输入 - - paragraph [ref=e784]: 这一步只负责补齐场景意图和上下文基线;真正执行会进入生成主执行面,继续复用 Agent 或自动化主链。 - - generic [ref=e785]: - - generic [ref=e786]: 项目工作区 - - button "📁 默认项目 默认" [ref=e787] [cursor=pointer]: - - generic [ref=e788]: - - generic [ref=e790]: 📁 - - generic [ref=e792]: - - generic [ref=e793]: 默认项目 - - generic [ref=e794]: 默认 - - img [ref=e796] - - generic [ref=e798]: - - generic [ref=e799]: 启动意图 - - textbox "请围绕一个产品卖点,生成一版 30 秒短视频方案:先给脚本方向、镜头结构、线框图提示和配乐情绪。" [ref=e800] - - generic [ref=e801]: - - generic [ref=e802]: 将使用内置起步稿启动 - - generic [ref=e803]: 请围绕一个产品卖点,生成一版 30 秒短视频方案:先给脚本方向、镜头结构、线框图提示和配乐情绪。 - - paragraph [ref=e804]: 写入当前场景基线会把这次显式带入的灵感对象、输入摘要和风格偏好沉淀到项目目录,供后续 planning 继续复用。 - - paragraph [ref=e805]: 先带入灵感对象或启动输入,再写入当前场景基线 - - generic [ref=e807]: - - button "写入当前场景基线" [disabled] - - button "进入生成" [ref=e808] [cursor=pointer] - - generic [ref=e809]: - - generic [ref=e810]: - - generic [ref=e811]: - - generic [ref=e812]: 经营评分 - - paragraph [ref=e813]: 用统一 scorecard 判断这个场景交付的结果是否值得继续放大、优化还是收口。 - - generic [ref=e814]: 适合继续启动 - - paragraph [ref=e815]: 基于最近 1 次真实运行,多模态组合场景的整包交付率为 0.0% ,复核通过率为 0.0% ,发布转化率为 100.0% 。当前主要阻塞集中在复核阻塞。当前样本已经以终态运行记录为主。 目前更适合继续扩大样本。 - - generic [ref=e816]: - - generic [ref=e817]: 当前经营口径 - - paragraph [ref=e818]: 经营上优先看整包是否交齐、是否通过复核,以及结果是否继续被打开编辑或发布。 - - generic [ref=e819]: 交付合同:项目资料包 - - generic [ref=e820]: 查看方式:结果包查看 - - generic [ref=e821]: 完成口径:按必含部件判断整包完成度 - - generic [ref=e822]: - - generic [ref=e823]: 任务简报 - - generic [ref=e824]: 分镜 / 线框图 - - generic [ref=e825]: 剧本 - - generic [ref=e826]: 配乐建议 - - generic [ref=e827]: 短视频草稿 - - generic [ref=e828]: 复核意见 - - generic [ref=e829]: Profile:story-video-scorecard - - generic [ref=e830]: - - generic [ref=e831]: 整包交付率 - - generic [ref=e832]: 复核通过率 - - generic [ref=e833]: 发布转化率 - - generic [ref=e834]: - - generic [ref=e835]: 整包不完整 - - generic [ref=e836]: 复核阻塞 - - generic [ref=e837]: 发布卡点 - - generic [ref=e838]: 当前主要阻塞:复核阻塞 - - generic [ref=e839]: - - generic [ref=e840]: 规划备注 - - generic [ref=e841]: - - generic [ref=e842]: 当前 SceneApp 以结果包作为默认交付单位。 - - generic [ref=e843]: 完整度将按 6 个必含部件判断。 - - generic [ref=e844]: 结果会优先回写到项目 849e36ff-8f64-45ed-ba51-aab6b8e182e4,便于继续编辑与复盘。 - - generic [ref=e845]: 结果包会连同参考与风格快照一起进入后续治理链。 - - generic [ref=e846]: 结果包可继续复用当前 viewer 主链打开与检查。 - - generic [ref=e847]: - - generic [ref=e848]: Planning 基线 - - generic [ref=e849]: 参考注入:1 条 - - generic [ref=e850]: 作用域:项目 849e36ff-8f64-45ed-ba51-aab6b8e182e4 - - generic [ref=e852]: 用户输入 · 复核阻塞 - - generic [ref=e853]: 风格摘要:当前 TasteProfile 已在项目沉淀基础上,结合 1 条参考输入更新启发式摘要。 - - generic [ref=e854]: 最近反馈:当前主要卡点是复核阻塞。经营上建议继续补样本。 - - generic [ref=e856]: 复核阻塞 - - generic [ref=e858]: 复核阻塞 - - generic [ref=e859]: - - article [ref=e860]: - - generic [ref=e861]: - - generic [ref=e862]: 整包交付率 - - generic [ref=e863]: "0" - - article [ref=e864]: - - generic [ref=e865]: - - generic [ref=e866]: 复核通过率 - - generic [ref=e867]: "0" - - article [ref=e868]: - - generic [ref=e869]: - - generic [ref=e870]: 发布转化率 - - generic [ref=e871]: "100" - - region "Notifications alt+T" \ No newline at end of file diff --git a/playwright-sceneapps-current-deep.yml b/playwright-sceneapps-current-deep.yml deleted file mode 100644 index 2656b5670..000000000 --- a/playwright-sceneapps-current-deep.yml +++ /dev/null @@ -1,178 +0,0 @@ -- generic [ref=e2]: - - generic [ref=e4]: - - complementary [ref=e5]: - - generic [ref=e6]: - - generic [ref=e7]: - - button "Lime Lime" [ref=e8] [cursor=pointer]: - - img "Lime" [ref=e10] - - generic [ref=e11]: Lime - - button "折叠导航栏" [ref=e12] [cursor=pointer]: - - img [ref=e13] - - button "搜索任务" [ref=e16] [cursor=pointer]: - - img [ref=e17] - - generic [ref=e20]: 搜索任务 - - generic [ref=e21]: - - generic [ref=e22]: - - generic [ref=e23]: 任务 - - button "新建任务" [ref=e24] [cursor=pointer]: - - img [ref=e25] - - generic [ref=e26]: 新建任务 - - button "生成" [ref=e27] [cursor=pointer]: - - img [ref=e28] - - generic [ref=e30]: 生成 - - generic [ref=e31]: - - generic [ref=e32]: 能力 - - button "我的方法" [ref=e33] [cursor=pointer]: - - img [ref=e34] - - generic [ref=e36]: 我的方法 - - button "创作场景" [ref=e37] [cursor=pointer]: - - img [ref=e38] - - generic [ref=e42]: 创作场景 - - button "持续流程" [ref=e43] [cursor=pointer]: - - img [ref=e44] - - generic [ref=e46]: 持续流程 - - button "消息渠道" [ref=e47] [cursor=pointer]: - - img [ref=e48] - - generic [ref=e51]: 消息渠道 - - generic [ref=e52]: - - generic [ref=e53]: 资料 - - button "资料库" [ref=e54] [cursor=pointer]: - - img [ref=e55] - - generic [ref=e57]: 资料库 - - button "灵感库" [ref=e58] [cursor=pointer]: - - img [ref=e59] - - generic [ref=e71]: 灵感库 - - generic [ref=e72]: - - generic [ref=e73]: - - generic [ref=e74]: 系统 - - button "OpenClaw" [ref=e75] [cursor=pointer]: - - img [ref=e76] - - generic [ref=e79]: OpenClaw - - button "设置" [ref=e80] [cursor=pointer]: - - img [ref=e81] - - generic [ref=e84]: 设置 - - button "切换到深色模式" [ref=e86] [cursor=pointer]: - - img [ref=e87] - - main [ref=e93]: - - generic [ref=e107]: - - generic [ref=e110]: - - generic [ref=e111]: - - generic [ref=e112]: 创作 - - generic [ref=e114]: - - button "📁 默认项目 默认" [ref=e115] [cursor=pointer]: - - generic [ref=e116] - - img [ref=e123] - - button "打开设置" [ref=e126] [cursor=pointer]: - - img [ref=e127] - - generic [ref=e130]: - - generic [ref=e131]: - - paragraph [ref=e132]: 青柠一下,灵感即来 - - paragraph [ref=e133]: 说一句目标,剩下的交给 Lime。 - - paragraph [ref=e134]: 文案、图片、视频、搜索和网页任务,会围绕同一个目标持续推进。跑通过的方法会沉淀成常用做法、偏好和项目上下文,下次不用重新开始。 - - generic [ref=e135]: - - generic [ref=e136]: 通用对话 - - generic [ref=e137]: 对话内开工 - - generic [ref=e140]: - - generic [ref=e141]: - - button "添加图片" [ref=e142] [cursor=pointer]: - - img [ref=e143] - - textbox "有什么我可以帮你的?" [ref=e148] - - generic [ref=e149]: - - button "展开输入框" [ref=e150] [cursor=pointer]: - - img [ref=e151] - - button "开始语音输入" [ref=e153] [cursor=pointer]: - - img [ref=e154] - - button "发送" [disabled] [ref=e157]: - - img [ref=e158] - - generic [ref=e162]: - - button "展开高级设置" [ref=e163] [cursor=pointer]: - - img [ref=e166] - - generic [ref=e169]: 高级设置 - - img [ref=e170] - - generic "当前模型:Custom-a32774c6-6fd0-433b-8b81-e95340e08793 / glm-5.1" [ref=e172]: - - generic [ref=e173]: 当前模型 - - generic [ref=e174]: glm-5.1 - - generic [ref=e175]: - - generic [ref=e176]: - - generic [ref=e177]: - - generic [ref=e178]: - - generic [ref=e179]: 创作场景 - - paragraph [ref=e180]: 不是单个技能,而是一条完整结果链。先挑一个场景,Lime 会把合适的能力和交付合同组合起来。 - - generic [ref=e181]: - - button "继续最近场景" [ref=e182] [cursor=pointer] - - button "查看全部场景" [ref=e183] [cursor=pointer] - - generic [ref=e184]: - - generic [ref=e185]: - - button "短视频编排" [ref=e186] [cursor=pointer] - - generic [ref=e187]: / - - button "每日趋势摘要" [ref=e189] [cursor=pointer] - - generic [ref=e190]: - - generic [ref=e192]: - - generic [ref=e193]: 继续上次做法 - - generic [ref=e194]: 最近跑通过的结果模板和常用做法会留在这里,下一次不用重新开始。 - - generic [ref=e195]: 你最近跑通过的结果模板和方法,会出现在这里。 - - generic [ref=e196]: - - generic [ref=e198]: - - generic [ref=e199]: 结果模板 - - generic [ref=e200]: 先选你想拿到什么结果,具体由 Lime 在当前任务里分发对应能力。 - - generic [ref=e201]: - - button "网页研究简报" [ref=e203] [cursor=pointer]: - - generic [ref=e204]: 网页研究简报 - - generic [ref=e205]: - - generic [ref=e206]: "|" - - button "内容主稿生成" [ref=e207] [cursor=pointer] - - generic [ref=e209]: - - generic [ref=e210]: "|" - - button "演示提纲草案" [ref=e211] [cursor=pointer] - - generic [ref=e213]: - - generic [ref=e214]: "|" - - button "网页登录与采集" [ref=e215] [cursor=pointer] - - generic [ref=e217]: - - generic [ref=e218]: "|" - - button "复制轮播帖" [ref=e219] [cursor=pointer] - - generic [ref=e221]: - - generic [ref=e222]: "|" - - button "复制视频脚本" [ref=e223] [cursor=pointer] - - generic [ref=e225]: - - article [ref=e226]: - - generic [ref=e227]: - - img [ref=e229] - - generic [ref=e231]: 沉淀能力 - - generic [ref=e232]: - - generic [ref=e233]: - - generic [ref=e234]: 我的方法 - - button "我的方法说明" [ref=e236] - - generic [ref=e240]: 29 套做法可直接复用 - - img "方法能力卡占位图" [ref=e243] - - article [ref=e244]: - - generic [ref=e245]: - - img [ref=e247] - - generic [ref=e250]: 沉淀能力 - - generic [ref=e251]: - - generic [ref=e252]: - - generic [ref=e253]: 持续流程 - - button "持续流程说明" [ref=e255] - - generic [ref=e259]: 重复任务可持续复用 - - img "持续流程能力卡占位图" [ref=e262] - - article [ref=e263]: - - generic [ref=e264]: - - img [ref=e266] - - generic [ref=e270]: 支撑能力 - - generic [ref=e271]: - - generic [ref=e272]: - - generic [ref=e273]: 任务拆分 - - button "任务拆分说明" [ref=e275] - - generic [ref=e279]: 复杂任务可拆分并行推进 - - img "任务拆分能力卡占位图" [ref=e282] - - article [ref=e283]: - - generic [ref=e284]: - - img [ref=e286] - - generic [ref=e289]: 支撑能力 - - generic [ref=e290]: - - generic [ref=e291]: - - generic [ref=e292]: 浏览器接入 - - button "浏览器接入说明" [ref=e294] - - generic [ref=e298]: 网页登录与网页执行 - - button "连接浏览器" [ref=e300] [cursor=pointer]: - - img "浏览器接入能力卡占位图" [ref=e301] - - region "Notifications alt+T" \ No newline at end of file diff --git a/playwright-sceneapps-home.yml b/playwright-sceneapps-home.yml deleted file mode 100644 index 542dc9243..000000000 --- a/playwright-sceneapps-home.yml +++ /dev/null @@ -1,100 +0,0 @@ -- generic [ref=e2]: - - generic [ref=e14]: - - complementary [ref=e15]: - - generic [ref=e16]: - - generic [ref=e17]: - - button "Lime Lime" [ref=e18] [cursor=pointer]: - - img "Lime" [ref=e20] - - generic [ref=e21]: Lime - - button "折叠导航栏" [ref=e22] [cursor=pointer]: - - img [ref=e23] - - button "搜索任务" [ref=e26] [cursor=pointer]: - - img [ref=e27] - - generic [ref=e30]: 搜索任务 - - generic [ref=e31]: - - generic [ref=e32]: - - generic [ref=e33]: 任务 - - button "新建任务" [ref=e34] [cursor=pointer]: - - img [ref=e35] - - generic [ref=e36]: 新建任务 - - button "生成" [ref=e37] [cursor=pointer]: - - img [ref=e38] - - generic [ref=e40]: 生成 - - generic [ref=e41]: - - generic [ref=e42]: 能力 - - button "我的方法" [ref=e43] [cursor=pointer]: - - img [ref=e44] - - generic [ref=e46]: 我的方法 - - button "创作场景" [ref=e47] [cursor=pointer]: - - img [ref=e48] - - generic [ref=e52]: 创作场景 - - button "持续流程" [ref=e53] [cursor=pointer]: - - img [ref=e54] - - generic [ref=e56]: 持续流程 - - button "消息渠道" [ref=e57] [cursor=pointer]: - - img [ref=e58] - - generic [ref=e61]: 消息渠道 - - generic [ref=e62]: - - generic [ref=e63]: 资料 - - button "资料库" [ref=e64] [cursor=pointer]: - - img [ref=e65] - - generic [ref=e67]: 资料库 - - button "灵感库" [ref=e68] [cursor=pointer]: - - img [ref=e69] - - generic [ref=e81]: 灵感库 - - generic [ref=e82]: - - generic [ref=e83]: - - generic [ref=e84]: 系统 - - button "OpenClaw" [ref=e85] [cursor=pointer]: - - img [ref=e86] - - generic [ref=e89]: OpenClaw - - button "设置" [ref=e90] [cursor=pointer]: - - img [ref=e91] - - generic [ref=e94]: 设置 - - button "切换到深色模式" [ref=e96] [cursor=pointer]: - - img [ref=e97] - - main [ref=e103]: - - generic [ref=e117]: - - generic [ref=e120]: - - generic [ref=e121]: - - generic [ref=e122]: 创作 - - generic [ref=e124] - - generic [ref=e140]: - - generic [ref=e141] - - generic [ref=e145] - - generic [ref=e150]: - - generic [ref=e151]: - - button "添加图片" [ref=e152] [cursor=pointer] - - textbox "有什么我可以帮你的?" [ref=e158] - - generic [ref=e159] - - generic [ref=e172]: - - button "展开高级设置" [ref=e173] [cursor=pointer] - - generic "当前模型:Custom-a32774c6-6fd0-433b-8b81-e95340e08793 / glm-5.1" [ref=e182] - - generic [ref=e185]: - - generic [ref=e186]: - - generic [ref=e187] - - generic [ref=e194] - - generic [ref=e200]: - - generic [ref=e202] - - generic [ref=e205]: 你最近跑通过的结果模板和方法,会出现在这里。 - - generic [ref=e206]: - - generic [ref=e208] - - generic [ref=e211] - - generic [ref=e235]: - - article [ref=e236]: - - generic [ref=e237] - - generic [ref=e242] - - img "方法能力卡占位图" [ref=e253] - - article [ref=e254]: - - generic [ref=e255] - - generic [ref=e261] - - img "持续流程能力卡占位图" [ref=e272] - - article [ref=e273]: - - generic [ref=e274] - - generic [ref=e281] - - img "任务拆分能力卡占位图" [ref=e292] - - article [ref=e293]: - - generic [ref=e294] - - generic [ref=e300] - - button "连接浏览器" [ref=e310] [cursor=pointer] - - region "Notifications alt+T" \ No newline at end of file diff --git a/playwright-snapshot-sceneapps-return-before.md b/playwright-snapshot-sceneapps-return-before.md deleted file mode 100644 index 59157b337..000000000 --- a/playwright-snapshot-sceneapps-return-before.md +++ /dev/null @@ -1,191 +0,0 @@ -- generic [ref=e2]: - - generic [ref=e4]: - - complementary [ref=e5]: - - generic [ref=e6]: - - generic [ref=e7]: - - button "Lime Lime" [ref=e8] [cursor=pointer]: - - img "Lime" [ref=e10] - - generic [ref=e11]: Lime - - button "折叠导航栏" [ref=e12] [cursor=pointer]: - - img [ref=e13] - - button "搜索任务" [ref=e16] [cursor=pointer]: - - img [ref=e17] - - generic [ref=e20]: 搜索任务 - - generic [ref=e21]: - - generic [ref=e22]: - - generic [ref=e23]: 任务 - - button "新建任务" [ref=e24] [cursor=pointer]: - - img [ref=e25] - - generic [ref=e26]: 新建任务 - - button "生成" [ref=e27] [cursor=pointer]: - - img [ref=e28] - - generic [ref=e30]: 生成 - - generic [ref=e31]: - - generic [ref=e32]: 能力 - - button "我的方法" [ref=e33] [cursor=pointer]: - - img [ref=e34] - - generic [ref=e36]: 我的方法 - - button "创作场景" [ref=e37] [cursor=pointer]: - - img [ref=e38] - - generic [ref=e42]: 创作场景 - - button "持续流程" [ref=e43] [cursor=pointer]: - - img [ref=e44] - - generic [ref=e46]: 持续流程 - - button "消息渠道" [ref=e47] [cursor=pointer]: - - img [ref=e48] - - generic [ref=e51]: 消息渠道 - - generic [ref=e52]: - - generic [ref=e53]: 资料 - - button "资料库" [ref=e54] [cursor=pointer]: - - img [ref=e55] - - generic [ref=e57]: 资料库 - - button "灵感库" [ref=e58] [cursor=pointer]: - - img [ref=e59] - - generic [ref=e71]: 灵感库 - - generic [ref=e72]: - - generic [ref=e73]: - - generic [ref=e74]: 系统 - - button "OpenClaw" [ref=e75] [cursor=pointer]: - - img [ref=e76] - - generic [ref=e79]: OpenClaw - - button "设置" [ref=e80] [cursor=pointer]: - - img [ref=e81] - - generic [ref=e84]: 设置 - - button "切换到深色模式" [ref=e86] [cursor=pointer]: - - img [ref=e87] - - main [ref=e93]: - - generic [ref=e107]: - - generic [ref=e110]: - - generic [ref=e111]: - - generic [ref=e112]: 创作 - - generic [ref=e114]: - - button "📁 默认项目 默认" [ref=e115] [cursor=pointer]: - - generic [ref=e116]: - - generic [ref=e118]: 📁 - - generic [ref=e119]: - - generic [ref=e120]: 默认项目 - - generic [ref=e121]: 默认 - - img [ref=e123] - - button "打开设置" [ref=e126] [cursor=pointer]: - - img [ref=e127] - - generic [ref=e130]: - - generic [ref=e131]: - - paragraph [ref=e132]: 青柠一下,灵感即来 - - paragraph [ref=e133]: 说一句目标,剩下的交给 Lime。 - - paragraph [ref=e134]: 文案、图片、视频、搜索和网页任务,会围绕同一个目标持续推进。跑通过的方法会沉淀成常用做法、偏好和项目上下文,下次不用重新开始。 - - generic [ref=e135]: - - generic [ref=e136]: 通用对话 - - generic [ref=e137]: 对话内开工 - - generic [ref=e140]: - - generic [ref=e141]: - - button "添加图片" [ref=e142] [cursor=pointer]: - - img [ref=e143] - - textbox "有什么我可以帮你的?" [ref=e148] - - generic [ref=e149]: - - button "展开输入框" [ref=e150] [cursor=pointer]: - - img [ref=e151] - - button "开始语音输入" [ref=e153] [cursor=pointer]: - - img [ref=e154] - - button "发送" [disabled] [ref=e157]: - - img [ref=e158] - - generic [ref=e162]: - - button "展开高级设置" [ref=e163] [cursor=pointer]: - - img [ref=e166] - - generic [ref=e169]: 高级设置 - - img [ref=e170] - - generic "当前模型:Custom-a32774c6-6fd0-433b-8b81-e95340e08793 / glm-5.1" [ref=e172]: - - generic [ref=e173]: 当前模型 - - generic [ref=e174]: glm-5.1 - - generic [ref=e175]: - - generic [ref=e176]: - - generic [ref=e177]: - - generic [ref=e178]: - - generic [ref=e179]: 创作场景 - - paragraph [ref=e180]: 不是单个技能,而是一条完整结果链。先挑一个场景,Lime 会把合适的能力和交付合同组合起来。 - - generic [ref=e181]: - - button "继续最近场景" [ref=e182] [cursor=pointer] - - button "查看全部场景" [ref=e183] [cursor=pointer] - - generic [ref=e184]: - - generic [ref=e185]: - - button "短视频编排" [ref=e186] [cursor=pointer] - - generic [ref=e187]: / - - button "每日趋势摘要" [ref=e189] [cursor=pointer] - - generic [ref=e190]: - - generic [ref=e192]: - - generic [ref=e193]: 继续上次做法 - - generic [ref=e194]: 最近跑通过的结果模板和常用做法会留在这里,下一次不用重新开始。 - - generic [ref=e195]: 你最近跑通过的结果模板和方法,会出现在这里。 - - generic [ref=e196]: - - generic [ref=e198]: - - generic [ref=e199]: 结果模板 - - generic [ref=e200]: 先选你想拿到什么结果,具体由 Lime 在当前任务里分发对应能力。 - - generic [ref=e201]: - - button "网页研究简报" [ref=e203] [cursor=pointer]: - - generic [ref=e204]: 网页研究简报 - - generic [ref=e205]: - - generic [ref=e206]: "|" - - button "内容主稿生成" [ref=e207] [cursor=pointer]: - - generic [ref=e208]: 内容主稿生成 - - generic [ref=e209]: - - generic [ref=e210]: "|" - - button "演示提纲草案" [ref=e211] [cursor=pointer]: - - generic [ref=e212]: 演示提纲草案 - - generic [ref=e213]: - - generic [ref=e214]: "|" - - button "网页登录与采集" [ref=e215] [cursor=pointer]: - - generic [ref=e216]: 网页登录与采集 - - generic [ref=e217]: - - generic [ref=e218]: "|" - - button "复制轮播帖" [ref=e219] [cursor=pointer]: - - generic [ref=e220]: 复制轮播帖 - - generic [ref=e221]: - - generic [ref=e222]: "|" - - button "复制视频脚本" [ref=e223] [cursor=pointer]: - - generic [ref=e224]: 复制视频脚本 - - generic [ref=e225]: - - article [ref=e226]: - - generic [ref=e227]: - - img [ref=e229] - - generic [ref=e231]: 沉淀能力 - - generic [ref=e232]: - - generic [ref=e233]: - - generic [ref=e234]: 我的方法 - - button "我的方法说明" [ref=e236]: - - img [ref=e237] - - generic [ref=e240]: 29 套做法可直接复用 - - img "方法能力卡占位图" [ref=e243] - - article [ref=e244]: - - generic [ref=e245]: - - img [ref=e247] - - generic [ref=e250]: 沉淀能力 - - generic [ref=e251]: - - generic [ref=e252]: - - generic [ref=e253]: 持续流程 - - button "持续流程说明" [ref=e255]: - - img [ref=e256] - - generic [ref=e259]: 重复任务可持续复用 - - img "持续流程能力卡占位图" [ref=e262] - - article [ref=e263]: - - generic [ref=e264]: - - img [ref=e266] - - generic [ref=e270]: 支撑能力 - - generic [ref=e271]: - - generic [ref=e272]: - - generic [ref=e273]: 任务拆分 - - button "任务拆分说明" [ref=e275]: - - img [ref=e276] - - generic [ref=e279]: 复杂任务可拆分并行推进 - - img "任务拆分能力卡占位图" [ref=e282] - - article [ref=e283]: - - generic [ref=e284]: - - img [ref=e286] - - generic [ref=e289]: 支撑能力 - - generic [ref=e290]: - - generic [ref=e291]: - - generic [ref=e292]: 浏览器接入 - - button "浏览器接入说明" [ref=e294]: - - img [ref=e295] - - generic [ref=e298]: 网页登录与网页执行 - - button "连接浏览器" [ref=e300] [cursor=pointer]: - - img "浏览器接入能力卡占位图" [ref=e301] - - region "Notifications alt+T" \ No newline at end of file diff --git a/public/logo-v6.svg b/public/logo-v6.svg new file mode 100644 index 000000000..601da2250 --- /dev/null +++ b/public/logo-v6.svg @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/verify-gui-smoke.mjs b/scripts/verify-gui-smoke.mjs index a4051a35b..2733ea19a 100644 --- a/scripts/verify-gui-smoke.mjs +++ b/scripts/verify-gui-smoke.mjs @@ -23,6 +23,7 @@ const ISOLATED_GUI_SMOKE_TARGET_DIR = path.join( os.tmpdir(), "lime-gui-smoke-target", ); +const GUI_SMOKE_TARGET_REBUILD_PREFIX = "rebuild"; const GUI_SMOKE_TEMP_CONFIG_BASENAME_PREFIX = "lime-gui-smoke-tauri-"; const GUI_SMOKE_COLD_TIMEOUT_MS = 1_800_000; const GUI_SMOKE_WARM_TIMEOUT_MS = 600_000; @@ -98,6 +99,69 @@ function resolveDefaultTimeoutMs(cargoTargetDir) { : GUI_SMOKE_COLD_TIMEOUT_MS; } +function listSqliteBuildOutputDirs(targetDir) { + const buildDir = path.join(targetDir, "debug", "build"); + if (!fs.existsSync(buildDir)) { + return []; + } + + return fs + .readdirSync(buildDir, { withFileTypes: true }) + .filter( + (entry) => + entry.isDirectory() && entry.name.startsWith("libsqlite3-sys-"), + ) + .map((entry) => path.join(buildDir, entry.name, "out")) + .filter((outDir) => fs.existsSync(outDir) && fs.statSync(outDir).isDirectory()) + .sort(); +} + +function listCorruptedSqliteBindingOutputs(targetDir) { + return listSqliteBuildOutputDirs(targetDir) + .filter((outDir) => !fs.existsSync(path.join(outDir, "bindgen.rs"))) + .map((outDir) => ({ + outDir, + relativeOutDir: path.relative(targetDir, outDir) || outDir, + })); +} + +function allocateFreshCargoTargetDir(targetDir) { + const parentDir = path.dirname(targetDir); + const baseName = path.basename(targetDir); + const suffix = `${GUI_SMOKE_TARGET_REBUILD_PREFIX}-${Date.now()}-${process.pid}`; + return path.join(parentDir, `${baseName}-${suffix}`); +} + +function normalizeCargoTargetDir(parsedOptions) { + const normalizedOptions = { + ...parsedOptions, + cargoTargetDir: path.resolve(parsedOptions.cargoTargetDir), + cargoTargetDirRequested: path.resolve(parsedOptions.cargoTargetDir), + cargoTargetDirFallbackReason: "", + corruptedSqliteBindingOutputs: [], + }; + const corruptedOutputs = listCorruptedSqliteBindingOutputs( + normalizedOptions.cargoTargetDir, + ); + + if (corruptedOutputs.length > 0) { + normalizedOptions.cargoTargetDir = allocateFreshCargoTargetDir( + normalizedOptions.cargoTargetDir, + ); + normalizedOptions.cargoTargetDirFallbackReason = + "detected-corrupted-sqlite-bindings"; + normalizedOptions.corruptedSqliteBindingOutputs = corruptedOutputs; + } + + if (!normalizedOptions.timeoutExplicit) { + normalizedOptions.timeoutMs = resolveDefaultTimeoutMs( + normalizedOptions.cargoTargetDir, + ); + } + + return normalizedOptions; +} + const DEFAULTS = { appUrl: "http://127.0.0.1:1420/", healthUrl: DEFAULT_HEALTH_URL, @@ -147,7 +211,7 @@ Lime GUI 冒烟入口 } function parseArgs(argv) { - const options = { ...DEFAULTS }; + const options = { ...DEFAULTS, timeoutExplicit: false }; let invokeUrlExplicit = false; for (let index = 0; index < argv.length; index += 1) { @@ -174,6 +238,7 @@ function parseArgs(argv) { if (arg === "--timeout-ms" && argv[index + 1]) { options.timeoutMs = Number(argv[index + 1]); + options.timeoutExplicit = true; index += 1; continue; } @@ -1190,10 +1255,22 @@ async function main() { throw new Error("当前 Node 运行时不支持 fetch,请使用 Node 18+"); } - const options = parseArgs(process.argv.slice(2)); + const parsedOptions = parseArgs(process.argv.slice(2)); + const options = normalizeCargoTargetDir(parsedOptions); const startupMode = await resolveStartupMode(options); const startedByScript = startupMode.shouldStart; + if (options.cargoTargetDirFallbackReason) { + const corruptedDirList = options.corruptedSqliteBindingOutputs + .map((item) => item.relativeOutDir) + .join(", "); + console.warn( + `[verify:gui-smoke] 检测到损坏的 sqlite 构建缓存(缺少 bindgen.rs):${corruptedDirList}`, + ); + console.warn( + `[verify:gui-smoke] 为避免复用旧半成品 target,Cargo target 已切换到新的独立目录:${options.cargoTargetDir}`, + ); + } console.log(`[verify:gui-smoke] Cargo target: ${options.cargoTargetDir}`); const handleSignal = async (signal) => { diff --git a/src-tauri/crates/aster-rust/crates/aster/src/providers/anthropic.rs b/src-tauri/crates/aster-rust/crates/aster/src/providers/anthropic.rs index 9b9104dc7..2bf03ca40 100644 --- a/src-tauri/crates/aster-rust/crates/aster/src/providers/anthropic.rs +++ b/src-tauri/crates/aster-rust/crates/aster/src/providers/anthropic.rs @@ -76,6 +76,7 @@ pub struct AnthropicProvider { api_client: ApiClient, model: ModelConfig, supports_streaming: bool, + automatic_prompt_cache: bool, name: String, } @@ -99,6 +100,7 @@ impl AnthropicProvider { }; let auth = resolve_anthropic_auth(&host, api_key); + let automatic_prompt_cache = supports_automatic_prompt_cache_for_host(&host); let api_client = ApiClient::new(host, auth)?.with_header("anthropic-version", ANTHROPIC_API_VERSION)?; @@ -107,6 +109,7 @@ impl AnthropicProvider { api_client, model, supports_streaming: true, + automatic_prompt_cache, name: Self::metadata().name, }) } @@ -120,6 +123,7 @@ impl AnthropicProvider { .get_secret(&config.api_key_env) .map_err(|_| anyhow::anyhow!("Missing API key: {}", config.api_key_env))?; + let automatic_prompt_cache = supports_automatic_prompt_cache_for_host(&config.base_url); let auth = resolve_anthropic_auth(&config.base_url, api_key); let api_client = ApiClient::new(config.base_url, auth)? @@ -129,10 +133,36 @@ impl AnthropicProvider { api_client, model, supports_streaming: config.supports_streaming.unwrap_or(true), + automatic_prompt_cache, name: config.name.clone(), }) } + fn strip_cache_control_markers(value: &mut Value) { + match value { + Value::Object(map) => { + map.remove("cache_control"); + for nested in map.values_mut() { + Self::strip_cache_control_markers(nested); + } + } + Value::Array(items) => { + for item in items { + Self::strip_cache_control_markers(item); + } + } + _ => {} + } + } + + fn normalize_payload_for_runtime(&self, payload: &mut Value) { + if self.automatic_prompt_cache { + return; + } + + Self::strip_cache_control_markers(payload); + } + fn get_conditional_headers(&self) -> Vec<(&str, &str)> { let mut headers = Vec::new(); @@ -246,7 +276,8 @@ impl Provider for AnthropicProvider { messages: &[Message], tools: &[Tool], ) -> Result<(Message, ProviderUsage), ProviderError> { - let payload = create_request(model_config, system, messages, tools)?; + let mut payload = create_request(model_config, system, messages, tools)?; + self.normalize_payload_for_runtime(&mut payload); let response = self .with_retry(|| async { self.post(&payload).await }) @@ -301,6 +332,7 @@ impl Provider for AnthropicProvider { tools: &[Tool], ) -> Result { let mut payload = create_request(&self.model, system, messages, tools)?; + self.normalize_payload_for_runtime(&mut payload); payload .as_object_mut() .unwrap() @@ -339,10 +371,26 @@ impl Provider for AnthropicProvider { } } +fn supports_automatic_prompt_cache_for_host(host: &str) -> bool { + let normalized_host = normalize_anthropic_host(host); + if normalized_host.is_empty() { + return true; + } + + normalized_host.contains("api.anthropic.com") || should_use_bearer_auth_for_anthropic_host(host) +} + #[cfg(test)] mod tests { - use super::{resolve_anthropic_auth, should_use_bearer_auth_for_anthropic_host}; + use super::{ + resolve_anthropic_auth, should_use_bearer_auth_for_anthropic_host, + supports_automatic_prompt_cache_for_host, AnthropicProvider, + }; + use crate::conversation::message::Message; + use crate::model::ModelConfig; use crate::providers::api_client::AuthMethod; + use crate::providers::formats::anthropic::create_request; + use rmcp::model::{CallToolRequestParam, ErrorCode, ErrorData, Tool}; #[test] fn test_known_official_anthropic_compatible_hosts_use_bearer_auth() { @@ -376,4 +424,86 @@ mod tests { _ => panic!("expected x-api-key auth"), } } + + #[test] + fn test_official_or_known_compatible_hosts_keep_automatic_prompt_cache() { + assert!(supports_automatic_prompt_cache_for_host( + "https://api.anthropic.com" + )); + assert!(supports_automatic_prompt_cache_for_host( + "https://api.minimaxi.com/anthropic" + )); + } + + #[test] + fn test_unknown_compatible_host_disables_automatic_prompt_cache() { + assert!(!supports_automatic_prompt_cache_for_host( + "https://example.com/anthropic" + )); + } + + #[test] + fn test_strip_cache_control_markers_for_non_automatic_runtime() { + let model_config = ModelConfig::new("claude-sonnet-4-5").expect("valid anthropic model"); + let messages = vec![ + Message::user().with_text("请输出结构化结果"), + Message::assistant().with_tool_request( + "tool_1", + Ok(CallToolRequestParam { + name: "StructuredOutput".into(), + arguments: Some(rmcp::object!({ + "answer": "draft" + })), + }), + ), + Message::user().with_tool_response( + "tool_1", + Err(ErrorData::new( + ErrorCode::INVALID_PARAMS, + "Validation failed".to_string(), + None, + )), + ), + ]; + let tools = vec![Tool::new( + "StructuredOutput".to_string(), + "Return the final JSON object".to_string(), + rmcp::object!({ + "type": "object", + "properties": { + "answer": { "type": "string" } + }, + "required": ["answer"] + }), + )]; + + let mut payload = + create_request(&model_config, "你必须输出 JSON。", &messages, &tools).expect("request"); + + assert_eq!( + payload["messages"][2]["content"][0]["cache_control"]["type"], + "ephemeral" + ); + assert_eq!(payload["tools"][0]["cache_control"]["type"], "ephemeral"); + assert_eq!(payload["system"][0]["cache_control"]["type"], "ephemeral"); + + AnthropicProvider::strip_cache_control_markers(&mut payload); + + assert!(payload["messages"][2]["content"][0] + .get("cache_control") + .is_none()); + assert!(payload["tools"][0].get("cache_control").is_none()); + assert!(payload["system"][0].get("cache_control").is_none()); + assert_eq!(payload["messages"][2]["content"][0]["type"], "tool_result"); + assert_eq!( + payload["messages"][2]["content"][0]["tool_use_id"], + "tool_1" + ); + assert_eq!( + payload["messages"][2]["content"][0]["content"], + "Error: -32602: Validation failed" + ); + assert_eq!(payload["messages"][2]["content"][0]["is_error"], true); + assert_eq!(payload["messages"][1]["content"][0]["id"], "tool_1"); + } } diff --git a/src-tauri/icons/128x128.png b/src-tauri/icons/128x128.png index 0e69114b4..d9a9c2f76 100644 Binary files a/src-tauri/icons/128x128.png and b/src-tauri/icons/128x128.png differ diff --git a/src-tauri/icons/128x128@2x.png b/src-tauri/icons/128x128@2x.png index 5034aa258..5498e3fb3 100644 Binary files a/src-tauri/icons/128x128@2x.png and b/src-tauri/icons/128x128@2x.png differ diff --git a/src-tauri/icons/32x32.png b/src-tauri/icons/32x32.png index f5ecb7cf8..cc831f637 100644 Binary files a/src-tauri/icons/32x32.png and b/src-tauri/icons/32x32.png differ diff --git a/src-tauri/icons/64x64.png b/src-tauri/icons/64x64.png index 82f7fcc11..1fedcf685 100644 Binary files a/src-tauri/icons/64x64.png and b/src-tauri/icons/64x64.png differ diff --git a/src-tauri/icons/Square107x107Logo.png b/src-tauri/icons/Square107x107Logo.png index bb33cbfad..4814ff644 100644 Binary files a/src-tauri/icons/Square107x107Logo.png and b/src-tauri/icons/Square107x107Logo.png differ diff --git a/src-tauri/icons/Square142x142Logo.png b/src-tauri/icons/Square142x142Logo.png index a970e4b7d..e5f09dd91 100644 Binary files a/src-tauri/icons/Square142x142Logo.png and b/src-tauri/icons/Square142x142Logo.png differ diff --git a/src-tauri/icons/Square150x150Logo.png b/src-tauri/icons/Square150x150Logo.png index 2c9033fe1..7997e02b5 100644 Binary files a/src-tauri/icons/Square150x150Logo.png and b/src-tauri/icons/Square150x150Logo.png differ diff --git a/src-tauri/icons/Square284x284Logo.png b/src-tauri/icons/Square284x284Logo.png index 94c90c187..e837560d9 100644 Binary files a/src-tauri/icons/Square284x284Logo.png and b/src-tauri/icons/Square284x284Logo.png differ diff --git a/src-tauri/icons/Square30x30Logo.png b/src-tauri/icons/Square30x30Logo.png index d3385285e..552bf5ed3 100644 Binary files a/src-tauri/icons/Square30x30Logo.png and b/src-tauri/icons/Square30x30Logo.png differ diff --git a/src-tauri/icons/Square310x310Logo.png b/src-tauri/icons/Square310x310Logo.png index e06de5243..847574511 100644 Binary files a/src-tauri/icons/Square310x310Logo.png and b/src-tauri/icons/Square310x310Logo.png differ diff --git a/src-tauri/icons/Square44x44Logo.png b/src-tauri/icons/Square44x44Logo.png index dabfb1be6..dd2e4b302 100644 Binary files a/src-tauri/icons/Square44x44Logo.png and b/src-tauri/icons/Square44x44Logo.png differ diff --git a/src-tauri/icons/Square71x71Logo.png b/src-tauri/icons/Square71x71Logo.png index b89bd8c3b..ca2b2fa21 100644 Binary files a/src-tauri/icons/Square71x71Logo.png and b/src-tauri/icons/Square71x71Logo.png differ diff --git a/src-tauri/icons/Square89x89Logo.png b/src-tauri/icons/Square89x89Logo.png index a37d4c726..6498cd4f5 100644 Binary files a/src-tauri/icons/Square89x89Logo.png and b/src-tauri/icons/Square89x89Logo.png differ diff --git a/src-tauri/icons/StoreLogo.png b/src-tauri/icons/StoreLogo.png index 6cf2b2fa5..83a27512e 100644 Binary files a/src-tauri/icons/StoreLogo.png and b/src-tauri/icons/StoreLogo.png differ diff --git a/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png index 1d02909a5..514188977 100644 Binary files a/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png and b/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png differ diff --git a/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png index da7d4eabb..f0fb4d706 100644 Binary files a/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png and b/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png index 1d02909a5..6dc94f4ff 100644 Binary files a/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png and b/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png differ diff --git a/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png index 14922128d..4f527e6f2 100644 Binary files a/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png and b/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png differ diff --git a/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png index 29d63640a..07ff2aeae 100644 Binary files a/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png and b/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png index 14922128d..613576963 100644 Binary files a/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png and b/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png differ diff --git a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png index 9a9752501..a53d3edb0 100644 Binary files a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png and b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png differ diff --git a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png index 4db4b14e6..988fad3c6 100644 Binary files a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png and b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png index 9a9752501..a63d5054c 100644 Binary files a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png and b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png index db5ac6ed5..b20d37bc6 100644 Binary files a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png and b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png index dc0624752..8b0770677 100644 Binary files a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png and b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png index db5ac6ed5..1e10444e9 100644 Binary files a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png and b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png index 0db6eb9ba..f236d4f52 100644 Binary files a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png and b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png index 3e32c52a3..ff896c109 100644 Binary files a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png and b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png index 0db6eb9ba..24d254527 100644 Binary files a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png and b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/src-tauri/icons/android/values/ic_launcher_background.xml b/src-tauri/icons/android/values/ic_launcher_background.xml index c8472d041..ea9c223a6 100644 --- a/src-tauri/icons/android/values/ic_launcher_background.xml +++ b/src-tauri/icons/android/values/ic_launcher_background.xml @@ -1,4 +1,4 @@ - #f7f9d7 + #fff \ No newline at end of file diff --git a/src-tauri/icons/icon.icns b/src-tauri/icons/icon.icns index 5f5cbfa59..a00bb169a 100644 Binary files a/src-tauri/icons/icon.icns and b/src-tauri/icons/icon.icns differ diff --git a/src-tauri/icons/icon.ico b/src-tauri/icons/icon.ico index da949997c..c706b6872 100644 Binary files a/src-tauri/icons/icon.ico and b/src-tauri/icons/icon.ico differ diff --git a/src-tauri/icons/icon.png b/src-tauri/icons/icon.png index 6c43e5485..086bc9e5b 100644 Binary files a/src-tauri/icons/icon.png and b/src-tauri/icons/icon.png differ diff --git a/src-tauri/icons/ios/AppIcon-20x20@1x.png b/src-tauri/icons/ios/AppIcon-20x20@1x.png index 93a743d78..502630e0c 100644 Binary files a/src-tauri/icons/ios/AppIcon-20x20@1x.png and b/src-tauri/icons/ios/AppIcon-20x20@1x.png differ diff --git a/src-tauri/icons/ios/AppIcon-20x20@2x-1.png b/src-tauri/icons/ios/AppIcon-20x20@2x-1.png index a920a23e3..a00daa77a 100644 Binary files a/src-tauri/icons/ios/AppIcon-20x20@2x-1.png and b/src-tauri/icons/ios/AppIcon-20x20@2x-1.png differ diff --git a/src-tauri/icons/ios/AppIcon-20x20@2x.png b/src-tauri/icons/ios/AppIcon-20x20@2x.png index a920a23e3..a00daa77a 100644 Binary files a/src-tauri/icons/ios/AppIcon-20x20@2x.png and b/src-tauri/icons/ios/AppIcon-20x20@2x.png differ diff --git a/src-tauri/icons/ios/AppIcon-20x20@3x.png b/src-tauri/icons/ios/AppIcon-20x20@3x.png index a5c53911f..089919e7c 100644 Binary files a/src-tauri/icons/ios/AppIcon-20x20@3x.png and b/src-tauri/icons/ios/AppIcon-20x20@3x.png differ diff --git a/src-tauri/icons/ios/AppIcon-29x29@1x.png b/src-tauri/icons/ios/AppIcon-29x29@1x.png index f88aa483a..350ffa1ad 100644 Binary files a/src-tauri/icons/ios/AppIcon-29x29@1x.png and b/src-tauri/icons/ios/AppIcon-29x29@1x.png differ diff --git a/src-tauri/icons/ios/AppIcon-29x29@2x-1.png b/src-tauri/icons/ios/AppIcon-29x29@2x-1.png index 622502906..7273a5f71 100644 Binary files a/src-tauri/icons/ios/AppIcon-29x29@2x-1.png and b/src-tauri/icons/ios/AppIcon-29x29@2x-1.png differ diff --git a/src-tauri/icons/ios/AppIcon-29x29@2x.png b/src-tauri/icons/ios/AppIcon-29x29@2x.png index 622502906..7273a5f71 100644 Binary files a/src-tauri/icons/ios/AppIcon-29x29@2x.png and b/src-tauri/icons/ios/AppIcon-29x29@2x.png differ diff --git a/src-tauri/icons/ios/AppIcon-29x29@3x.png b/src-tauri/icons/ios/AppIcon-29x29@3x.png index 0b243aa93..593aae51c 100644 Binary files a/src-tauri/icons/ios/AppIcon-29x29@3x.png and b/src-tauri/icons/ios/AppIcon-29x29@3x.png differ diff --git a/src-tauri/icons/ios/AppIcon-40x40@1x.png b/src-tauri/icons/ios/AppIcon-40x40@1x.png index a920a23e3..a00daa77a 100644 Binary files a/src-tauri/icons/ios/AppIcon-40x40@1x.png and b/src-tauri/icons/ios/AppIcon-40x40@1x.png differ diff --git a/src-tauri/icons/ios/AppIcon-40x40@2x-1.png b/src-tauri/icons/ios/AppIcon-40x40@2x-1.png index 629827469..1be42579a 100644 Binary files a/src-tauri/icons/ios/AppIcon-40x40@2x-1.png and b/src-tauri/icons/ios/AppIcon-40x40@2x-1.png differ diff --git a/src-tauri/icons/ios/AppIcon-40x40@2x.png b/src-tauri/icons/ios/AppIcon-40x40@2x.png index 629827469..1be42579a 100644 Binary files a/src-tauri/icons/ios/AppIcon-40x40@2x.png and b/src-tauri/icons/ios/AppIcon-40x40@2x.png differ diff --git a/src-tauri/icons/ios/AppIcon-40x40@3x.png b/src-tauri/icons/ios/AppIcon-40x40@3x.png index 9c893a6ef..7154475ef 100644 Binary files a/src-tauri/icons/ios/AppIcon-40x40@3x.png and b/src-tauri/icons/ios/AppIcon-40x40@3x.png differ diff --git a/src-tauri/icons/ios/AppIcon-512@2x.png b/src-tauri/icons/ios/AppIcon-512@2x.png index 110f754f7..873d8cd14 100644 Binary files a/src-tauri/icons/ios/AppIcon-512@2x.png and b/src-tauri/icons/ios/AppIcon-512@2x.png differ diff --git a/src-tauri/icons/ios/AppIcon-60x60@2x.png b/src-tauri/icons/ios/AppIcon-60x60@2x.png index 9c893a6ef..7154475ef 100644 Binary files a/src-tauri/icons/ios/AppIcon-60x60@2x.png and b/src-tauri/icons/ios/AppIcon-60x60@2x.png differ diff --git a/src-tauri/icons/ios/AppIcon-60x60@3x.png b/src-tauri/icons/ios/AppIcon-60x60@3x.png index eb261c98e..e05906a21 100644 Binary files a/src-tauri/icons/ios/AppIcon-60x60@3x.png and b/src-tauri/icons/ios/AppIcon-60x60@3x.png differ diff --git a/src-tauri/icons/ios/AppIcon-76x76@1x.png b/src-tauri/icons/ios/AppIcon-76x76@1x.png index 7266b6b2c..71ff9bf83 100644 Binary files a/src-tauri/icons/ios/AppIcon-76x76@1x.png and b/src-tauri/icons/ios/AppIcon-76x76@1x.png differ diff --git a/src-tauri/icons/ios/AppIcon-76x76@2x.png b/src-tauri/icons/ios/AppIcon-76x76@2x.png index 3c2fc3b86..a3e4d694c 100644 Binary files a/src-tauri/icons/ios/AppIcon-76x76@2x.png and b/src-tauri/icons/ios/AppIcon-76x76@2x.png differ diff --git a/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png b/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png index 36ac2b1e5..1e2ced2fd 100644 Binary files a/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png and b/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png differ diff --git a/src-tauri/tauri.conf.headless.json b/src-tauri/tauri.conf.headless.json index 9e4a3cc5b..42d3bed82 100644 --- a/src-tauri/tauri.conf.headless.json +++ b/src-tauri/tauri.conf.headless.json @@ -2,7 +2,7 @@ "$schema": "https://schema.tauri.app/config/2", "productName": "Lime", "version": "1.14.0", - "identifier": "com.limecloud.lime", + "identifier": "com.limecloud.lime.headless", "build": { "beforeDevCommand": "npm run dev:web-bridge", "devUrl": "http://127.0.0.1:1420", diff --git a/src/components/AppPageContent.test.tsx b/src/components/AppPageContent.test.tsx index 8d08ed1ef..977696a4d 100644 --- a/src/components/AppPageContent.test.tsx +++ b/src/components/AppPageContent.test.tsx @@ -11,6 +11,13 @@ const latestAgentChatProps = vi.hoisted( value: null as Record | null, }) as { value: Record | null }, ); +const agentChatLifecycle = vi.hoisted( + () => + ({ + mounts: 0, + unmounts: 0, + }) as { mounts: number; unmounts: number }, +); const latestSkillsWorkspaceProps = vi.hoisted( () => ({ @@ -40,6 +47,15 @@ const sceneAppsLifecycle = vi.hoisted( vi.mock("./agent/chat", () => ({ AgentChatPage: (props: Record) => { latestAgentChatProps.value = props; + + useEffect(() => { + agentChatLifecycle.mounts += 1; + + return () => { + agentChatLifecycle.unmounts += 1; + }; + }, []); + return
; }, })); @@ -160,6 +176,8 @@ describe("AppPageContent", () => { beforeEach(() => { vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true); latestAgentChatProps.value = null; + agentChatLifecycle.mounts = 0; + agentChatLifecycle.unmounts = 0; latestSkillsWorkspaceProps.value = null; latestMemoryPageProps.value = null; latestSceneAppsPageProps.value = null; @@ -305,6 +323,130 @@ describe("AppPageContent", () => { }); }); + it("agent 页面应把 initialInputCapability 透传给 AgentChatPage", async () => { + const pageParams: AgentPageParams = { + agentEntry: "new-task", + projectId: "project-3", + theme: "general", + initialInputCapability: { + capabilityRoute: { + kind: "installed_skill", + skillKey: "local:writer", + skillName: "写作助手", + }, + requestKey: 20260418, + }, + }; + + renderContent("agent", pageParams); + await flushEffects(); + + expect(latestAgentChatProps.value).toMatchObject({ + projectId: "project-3", + agentEntry: "new-task", + initialInputCapability: { + capabilityRoute: { + kind: "installed_skill", + skillKey: "local:writer", + skillName: "写作助手", + }, + requestKey: 20260418, + }, + }); + }); + + it("agent 页面切换 initialInputCapability 时应重建 AgentChatPage 实例", async () => { + const rendered = renderContentWithNavigationState({ + currentPage: "agent", + pageParams: { + agentEntry: "new-task", + projectId: "project-3", + theme: "general", + initialInputCapability: { + capabilityRoute: { + kind: "installed_skill", + skillKey: "local:writer", + skillName: "写作助手", + }, + requestKey: 20260418, + }, + } satisfies AgentPageParams, + }); + await flushEffects(); + + expect(agentChatLifecycle.mounts).toBe(1); + expect(agentChatLifecycle.unmounts).toBe(0); + + rendered.rerender({ + currentPage: "agent", + pageParams: { + agentEntry: "new-task", + projectId: "project-3", + theme: "general", + initialInputCapability: { + capabilityRoute: { + kind: "installed_skill", + skillKey: "local:analyst", + skillName: "分析助手", + }, + requestKey: 20260419, + }, + } satisfies AgentPageParams, + }); + await flushEffects(); + + expect(agentChatLifecycle.mounts).toBe(2); + expect(agentChatLifecycle.unmounts).toBe(1); + }); + + it("agent 页面切换结果模板 initialInputCapability 时也应重建 AgentChatPage 实例", async () => { + const rendered = renderContentWithNavigationState({ + currentPage: "agent", + pageParams: { + agentEntry: "new-task", + projectId: "project-3", + theme: "general", + initialInputCapability: { + capabilityRoute: { + kind: "curated_task", + taskId: "daily-trend-briefing", + taskTitle: "每日趋势摘要", + prompt: + "请先给我做一版每日趋势摘要:围绕当前主题梳理最近值得关注的趋势、热点内容方向、代表案例、用户正在关心的问题,以及最值得立即开工的 3 个选题。", + }, + requestKey: 20260418, + }, + } satisfies AgentPageParams, + }); + await flushEffects(); + + expect(agentChatLifecycle.mounts).toBe(1); + expect(agentChatLifecycle.unmounts).toBe(0); + + rendered.rerender({ + currentPage: "agent", + pageParams: { + agentEntry: "new-task", + projectId: "project-3", + theme: "general", + initialInputCapability: { + capabilityRoute: { + kind: "curated_task", + taskId: "social-post-starter", + taskTitle: "内容主稿生成", + prompt: + "请先帮我起草一版内容首稿:明确目标受众、标题方向、正文结构、核心观点和可继续扩写的角度,并给我一版适合继续打磨的正文。", + }, + requestKey: 20260419, + }, + } satisfies AgentPageParams, + }); + await flushEffects(); + + expect(agentChatLifecycle.mounts).toBe(2); + expect(agentChatLifecycle.unmounts).toBe(1); + }); + it("agent 页面应把创作场景执行摘要与自动发送 metadata 透传给 AgentChatPage", async () => { const pageParams: AgentPageParams = { agentEntry: "claw", diff --git a/src/components/AppPageContent.tsx b/src/components/AppPageContent.tsx index 07c55993f..cc1cb7e9b 100644 --- a/src/components/AppPageContent.tsx +++ b/src/components/AppPageContent.tsx @@ -84,6 +84,26 @@ const SkillsWorkspacePage = lazy(loadSkillsWorkspacePage); const BrowserRuntimeWorkspace = lazy(loadBrowserRuntimeWorkspace); const AgentChatPage = lazy(loadAgentChatPage); +function serializeInitialInputCapabilityKey( + params: AgentPageParams, +): string { + const route = params.initialInputCapability?.capabilityRoute; + if (!route) { + return "::0"; + } + + const routeKey = + route.kind === "installed_skill" + ? route.skillKey + : route.kind === "builtin_command" + ? route.commandKey + : route.kind === "runtime_scene" + ? route.sceneKey + : route.taskId; + + return `${route.kind}:${routeKey}:${params.initialInputCapability?.requestKey ?? 0}`; +} + interface AppPageContentProps { currentPage: Page; pageParams: PageParams; @@ -195,7 +215,7 @@ export function AppPageContent({ const content = (
- Lime + Lime Lime , diff --git a/src/components/Modal.test.tsx b/src/components/Modal.test.tsx index 9f6ad4423..a9c47169a 100644 --- a/src/components/Modal.test.tsx +++ b/src/components/Modal.test.tsx @@ -114,6 +114,8 @@ describe("Modal", () => { ) as HTMLDivElement | null; expect(overlay?.className).toContain("overflow-y-auto"); + expect(overlay?.className).toContain("backdrop-blur-[2px]"); + expect(overlay?.className).not.toContain("bg-black/50"); expect(dialog?.className).toContain("max-h-[calc(100vh-2rem)]"); expect(dialog?.className).toContain("flex-col"); expect(body?.className).toContain("flex-1"); diff --git a/src/components/Modal.tsx b/src/components/Modal.tsx index fd76179f6..fe2837a81 100644 --- a/src/components/Modal.tsx +++ b/src/components/Modal.tsx @@ -146,7 +146,7 @@ export function Modal({ return createPortal(
diff --git a/src/components/SplashScreen.tsx b/src/components/SplashScreen.tsx index fdffeac79..8a1a043e6 100644 --- a/src/components/SplashScreen.tsx +++ b/src/components/SplashScreen.tsx @@ -260,7 +260,7 @@ export function SplashScreen({ - + 青柠一下,灵感即来 diff --git a/src/components/agent/chat/AgentChatWorkspace.tsx b/src/components/agent/chat/AgentChatWorkspace.tsx index 2006d3b46..8645081c9 100644 --- a/src/components/agent/chat/AgentChatWorkspace.tsx +++ b/src/components/agent/chat/AgentChatWorkspace.tsx @@ -168,6 +168,10 @@ import { useWorkspaceCanvasTaskFileSync } from "./workspace/useWorkspaceCanvasTa import { useWorkspaceGeneralResourceSync } from "./workspace/useWorkspaceGeneralResourceSync"; import { useWorkspaceArtifactWorkbenchActions } from "./workspace/useWorkspaceArtifactWorkbenchActions"; import { useSceneAppExecutionSummaryRuntime } from "./workspace/useSceneAppExecutionSummaryRuntime"; +import { + buildSceneAppExecutionContentPostEntries, + type SceneAppExecutionContentPostEntry, +} from "./workspace/sceneAppExecutionContentPosts"; import { useWorkspaceImageWorkbenchActionRuntime, type SubmitImageWorkbenchAgentCommandParams, @@ -245,7 +249,9 @@ import { } from "./agentChatWorkspaceShared"; import type { AgentChatWorkspaceProps } from "./agentChatWorkspaceContract"; import { extractCreationReplayMetadata } from "./utils/creationReplayMetadata"; +import { buildCreationReplaySurfaceModel } from "./utils/creationReplaySurface"; import { buildMessageInspirationDraft } from "./utils/messageInspirationDraft"; +import { recordCuratedTaskRecommendationSignalFromMemory } from "./utils/curatedTaskRecommendationSignals"; import { buildSkillsPageParamsFromMessage } from "./utils/skillScaffoldDraft"; import { AutomationJobDialog } from "@/components/settings-v2/system/automation/AutomationJobDialog"; import { shouldAutoSelectGeneralArtifact } from "./workspace/generalArtifactAutoSelection"; @@ -404,6 +410,7 @@ export function AgentChatWorkspace({ initialSessionName, entryBannerMessage, initialPendingServiceSkillLaunch, + initialInputCapability, initialProjectFileOpenTarget, onInitialUserPromptConsumed, newChatAt, @@ -726,6 +733,10 @@ export function AgentChatWorkspace({ () => extractCreationReplayMetadata(initialRequestMetadata), [initialRequestMetadata], ); + const initialCreationReplaySurface = useMemo( + () => buildCreationReplaySurfaceModel(initialCreationReplay), + [initialCreationReplay], + ); useEffect(() => { setActiveContentTarget(projectId, contentId, canvasState?.type ?? null); @@ -3849,6 +3860,15 @@ export function AgentChatWorkspace({ sessionId, isSending, }); + const sceneAppExecutionContentPostEntries = useMemo( + () => + buildSceneAppExecutionContentPostEntries({ + taskFiles, + sessionFiles, + artifacts, + }), + [artifacts, sessionFiles, taskFiles], + ); const [sceneAppReviewDecisionDialogOpen, setSceneAppReviewDecisionDialogOpen] = useState(false); const [sceneAppReviewDecisionTemplate, setSceneAppReviewDecisionTemplate] = @@ -4265,6 +4285,70 @@ export function AgentChatWorkspace({ }, [_onNavigate, projectId, sceneAppExecutionSummaryState?.summary], ); + const handleOpenSceneAppExecutionContentPost = useCallback( + (entry: SceneAppExecutionContentPostEntry) => { + if (entry.source.kind === "task_file") { + handleTaskFileClick(entry.source.file); + return; + } + + if (entry.source.kind === "artifact") { + handleArtifactClick(entry.source.artifact); + return; + } + + void (async () => { + try { + const matchedTaskFile = taskFiles.find((file) => + doesWorkspaceFileCandidateMatch(file.name, entry.pathLabel), + ); + if (matchedTaskFile) { + handleTaskFileClick(matchedTaskFile); + return; + } + + const matchedArtifact = artifacts.find((artifact) => + doesWorkspaceFileCandidateMatch( + resolveArtifactProtocolFilePath(artifact), + entry.pathLabel, + ), + ); + if (matchedArtifact) { + handleArtifactClick(matchedArtifact); + return; + } + + const matchedSessionFile = sessionFiles.find((file) => + doesWorkspaceFileCandidateMatch(file.name, entry.pathLabel), + ); + if (!matchedSessionFile) { + toast.error("当前发布产物已不存在,暂时无法打开。"); + return; + } + + const content = await readSessionFile(matchedSessionFile.name); + if (typeof content !== "string" || !content.trim()) { + toast.info("该发布产物当前没有可直接预览的正文内容。"); + return; + } + + handleWorkspaceFileClick(matchedSessionFile.name, content); + } catch (error) { + console.error("[AgentChatPage] 打开发布产物失败:", error); + toast.error("打开发布产物失败,请稍后重试。"); + } + })(); + }, + [ + artifacts, + handleArtifactClick, + handleTaskFileClick, + handleWorkspaceFileClick, + readSessionFile, + sessionFiles, + taskFiles, + ], + ); const sceneAppExecutionSummaryCard = useMemo( () => ( 0} onPromptAction={handleRunSceneAppExecutionPromptAction} /> @@ -4299,6 +4385,7 @@ export function AgentChatWorkspace({ [ canOpenSceneAppExecutionHumanReview, handleApplySceneAppExecutionQuickReview, + handleOpenSceneAppExecutionContentPost, handleOpenSceneAppExecutionDetail, handleOpenSceneAppExecutionHumanReview, handleOpenSceneAppExecutionGovernance, @@ -4311,6 +4398,7 @@ export function AgentChatWorkspace({ queuedTurns.length, sceneAppReviewDecisionLoading, sceneAppReviewDecisionSaving, + sceneAppExecutionContentPostEntries, sceneAppExecutionSummaryState, ], ); @@ -4839,7 +4927,11 @@ export function AgentChatWorkspace({ } void createUnifiedMemory(draft.request) - .then(() => { + .then((memory) => { + recordCuratedTaskRecommendationSignalFromMemory(memory, { + projectId, + sessionId, + }); toast.success("已保存到灵感库", { description: `${draft.categoryLabel} · ${draft.title}`, }); @@ -4849,7 +4941,7 @@ export function AgentChatWorkspace({ toast.error("保存到灵感库失败,请稍后重试"); }); }, - [initialCreationReplay, sessionId], + [initialCreationReplay, projectId, sessionId], ); const inputbarScene = useWorkspaceInputbarSceneRuntime({ @@ -4929,6 +5021,7 @@ export function AgentChatWorkspace({ skillsLoading: combinedSkillsLoading, onSelectServiceSkill: workspaceServiceSkillEntryActions.handleServiceSkillSelect, + initialInputCapability, setChatToolPreferences, handleNavigateToSkillSettings, handleRefreshSkills, @@ -4967,6 +5060,10 @@ export function AgentChatWorkspace({ shellChromeRuntime.shouldShowGeneralWorkbenchFloatingInputOverlay, handleActivateTeamWorkbench, chatToolPreferences: effectiveChatToolPreferences, + defaultCuratedTaskReferenceMemoryIds: + initialCreationReplaySurface?.defaultReferenceMemoryIds, + defaultCuratedTaskReferenceEntries: + initialCreationReplaySurface?.defaultReferenceEntries, }); const canvasScene = useWorkspaceCanvasSceneRuntime({ @@ -5034,6 +5131,7 @@ export function AgentChatWorkspace({ text: string, sendExecutionStrategy?: "react" | "code_orchestrated" | "auto", images?: MessageImage[], + sendOptions?: HandleSendOptions, ) => { void handleSend( images || [], @@ -5041,6 +5139,8 @@ export function AgentChatWorkspace({ effectiveChatToolPreferences.thinking, text, sendExecutionStrategy, + undefined, + sendOptions, ); }, [ @@ -5069,6 +5169,7 @@ export function AgentChatWorkspace({ handleToggleHarnessPanel: contextHarnessRuntime.handleToggleHarnessPanel, entryBannerVisible, entryBannerMessage, + creationReplaySurface: initialCreationReplaySurface, sceneAppExecutionSummaryCard, serviceSkillExecutionCard, contextWorkspaceEnabled: contextWorkspace.generalWorkbenchEnabled, diff --git a/src/components/agent/chat/agentChatWorkspaceContract.ts b/src/components/agent/chat/agentChatWorkspaceContract.ts index 40a627672..97536c191 100644 --- a/src/components/agent/chat/agentChatWorkspaceContract.ts +++ b/src/components/agent/chat/agentChatWorkspaceContract.ts @@ -3,6 +3,7 @@ import type { MessageImage } from "./types"; import type { StepStatus } from "@/lib/workspace/workbenchContract"; import type { Page, PageParams } from "@/types/page"; import type { + AgentInitialInputCapabilityParams, AgentPendingServiceSkillLaunchParams, AgentProjectFileOpenTarget, AgentSiteSkillLaunchParams, @@ -55,5 +56,6 @@ export interface AgentChatWorkspaceProps { openBrowserAssistOnMount?: boolean; initialSiteSkillLaunch?: AgentSiteSkillLaunchParams; initialPendingServiceSkillLaunch?: AgentPendingServiceSkillLaunchParams; + initialInputCapability?: AgentInitialInputCapabilityParams; initialProjectFileOpenTarget?: AgentProjectFileOpenTarget; } diff --git a/src/components/agent/chat/components/AgentThreadMemoryPrefetchPreview.test.tsx b/src/components/agent/chat/components/AgentThreadMemoryPrefetchPreview.test.tsx index 16326753b..8d5c4aa4c 100644 --- a/src/components/agent/chat/components/AgentThreadMemoryPrefetchPreview.test.tsx +++ b/src/components/agent/chat/components/AgentThreadMemoryPrefetchPreview.test.tsx @@ -58,7 +58,7 @@ describe("AgentThreadMemoryPrefetchPreview", () => { durable_memories: [], team_memory_entries: [], latest_compaction: null, - prompt: null, + prompt: "【运行时记忆召回】补上本轮风险摘要。", }, }); @@ -70,6 +70,10 @@ describe("AgentThreadMemoryPrefetchPreview", () => { expect(panel?.textContent).toContain("记忆命中预演"); expect(panel?.textContent).toContain("规则 1"); expect(panel?.textContent).toContain("会话 已命中"); + const promptBlock = container.querySelector("pre"); + expect(promptBlock?.className).toContain("border-sky-100"); + expect(promptBlock?.className).not.toContain("bg-slate-950"); + expect(promptBlock?.textContent).toContain("【运行时记忆召回】"); }); it("error 状态应保留 amber 提醒色", () => { diff --git a/src/components/agent/chat/components/AgentThreadMemoryPrefetchPreview.tsx b/src/components/agent/chat/components/AgentThreadMemoryPrefetchPreview.tsx index 146650c69..21beefa0f 100644 --- a/src/components/agent/chat/components/AgentThreadMemoryPrefetchPreview.tsx +++ b/src/components/agent/chat/components/AgentThreadMemoryPrefetchPreview.tsx @@ -21,6 +21,8 @@ const EMERALD_OUTLINE_BADGE_CLASS_NAME = "border-emerald-200 bg-white text-emerald-700"; const SLATE_PANEL_CLASS_NAME = "border-slate-200/80 bg-white"; const SLATE_TITLE_CLASS_NAME = "text-slate-700"; +const MEMORY_PROMPT_SURFACE_CLASS_NAME = + "overflow-x-auto rounded-lg border border-sky-100 bg-[linear-gradient(180deg,rgba(248,255,254,0.98)_0%,rgba(255,255,255,0.98)_55%,rgba(240,249,255,0.96)_100%)] px-3 py-2 text-xs leading-6 text-slate-700 shadow-sm shadow-sky-950/5"; const DURABLE_CATEGORY_LABELS: Record = { identity: "风格", @@ -379,7 +381,7 @@ export function AgentThreadMemoryPrefetchPreview({ emptyText="当前没有返回组装后的运行时记忆片段。" > {result.prompt ? ( -
+                
                   {truncateText(result.prompt, 500)}
                 
) : null} diff --git a/src/components/agent/chat/components/CanvasWorkbenchLayout.test.tsx b/src/components/agent/chat/components/CanvasWorkbenchLayout.test.tsx index 5a03a4bd3..21a66168c 100644 --- a/src/components/agent/chat/components/CanvasWorkbenchLayout.test.tsx +++ b/src/components/agent/chat/components/CanvasWorkbenchLayout.test.tsx @@ -1360,12 +1360,12 @@ describe("CanvasWorkbenchLayout", () => { renderPreview, teamView: { enabled: true, - title: "任务工作台", + title: "生成工作台", subtitle: "任务进行时", badges: [ { key: "team-runtime", - label: "任务工作台", + label: "生成工作台", tone: "accent", }, { @@ -1401,7 +1401,7 @@ describe("CanvasWorkbenchLayout", () => { ).not.toBeNull(); expect( container.querySelector( - 'button[aria-label="切换画布标签-任务工作台"]', + 'button[aria-label="切换画布标签-生成工作台"]', ), ).not.toBeNull(); expect(renderPreview).toHaveBeenCalled(); @@ -1441,7 +1441,7 @@ describe("CanvasWorkbenchLayout", () => { renderPreview, teamView: { enabled: true, - title: "任务工作台", + title: "生成工作台", subtitle: "任务进行时", autoFocusToken: 1, renderPreview: () =>
unused-team-preview
, diff --git a/src/components/agent/chat/components/CanvasWorkbenchLayout.tsx b/src/components/agent/chat/components/CanvasWorkbenchLayout.tsx index 2e7db56e7..ce470478f 100644 --- a/src/components/agent/chat/components/CanvasWorkbenchLayout.tsx +++ b/src/components/agent/chat/components/CanvasWorkbenchLayout.tsx @@ -1438,7 +1438,7 @@ export const CanvasWorkbenchLayout = memo(function CanvasWorkbenchLayout({ } return { kind: "team-workbench", - title: teamView.title || "任务工作台", + title: teamView.title || "生成工作台", }; }, [teamView]); @@ -1582,7 +1582,7 @@ export const CanvasWorkbenchLayout = memo(function CanvasWorkbenchLayout({ label: teamView.tabLabel?.trim() || teamView.title?.trim() || - "任务工作台", + "生成工作台", badge: teamView.tabBadge?.trim() || teamView.triggerState?.label?.trim() || @@ -2029,7 +2029,7 @@ export const CanvasWorkbenchLayout = memo(function CanvasWorkbenchLayout({
{teamView?.panelCopy?.emptyText || - "当前没有可展示的任务工作台。"} + "当前没有可展示的生成工作台。"}
); diff --git a/src/components/agent/chat/components/ChatSidebar.test.tsx b/src/components/agent/chat/components/ChatSidebar.test.tsx index 07ec043d0..d44c1393b 100644 --- a/src/components/agent/chat/components/ChatSidebar.test.tsx +++ b/src/components/agent/chat/components/ChatSidebar.test.tsx @@ -299,6 +299,30 @@ describe("ChatSidebar", () => { expect(container.textContent).toContain("更早记录"); }); + it("生成侧栏 continuation fallback 应使用打开现场口径", async () => { + const container = renderSidebar({ + contextVariant: "task-center", + currentTopicId: null, + topics: [ + { + ...defaultTopics[0], + id: "topic-draft", + title: "待整理现场", + updatedAt: new Date(), + status: "draft", + lastPreview: "先补齐创作需求,再继续生成。", + sourceSessionId: "topic-draft", + }, + ], + }); + + await act(async () => { + await Promise.resolve(); + }); + + expect(container.textContent).toContain("打开现场"); + }); + it("子任务和任务列表应处于同一滚动区域", () => { const container = renderSidebar({ childSubagentSessions: [ diff --git a/src/components/agent/chat/components/ChatSidebar.tsx b/src/components/agent/chat/components/ChatSidebar.tsx index 3e6934237..628994c74 100644 --- a/src/components/agent/chat/components/ChatSidebar.tsx +++ b/src/components/agent/chat/components/ChatSidebar.tsx @@ -261,7 +261,7 @@ function resolveTaskCenterContinuationActionLabel( if (item.status === "running") { return "查看进展"; } - return "打开任务"; + return "打开现场"; } function areProjectNameMapsEqual( @@ -1300,7 +1300,7 @@ export const ChatSidebar: React.FC = ({

- 返回主线程,查看完整任务视图和原始上下文。 + 返回主线程,查看完整进展和原始上下文。

diff --git a/src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx b/src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx new file mode 100644 index 000000000..99a4ff4eb --- /dev/null +++ b/src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx @@ -0,0 +1,466 @@ +import { useEffect, useMemo, useState } from "react"; +import { ArrowRight, Check, LoaderCircle, Sparkles } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Textarea } from "@/components/ui/textarea"; +import { + hasFilledAllCuratedTaskRequiredInputs, + resolveCuratedTaskInputValues, + type CuratedTaskInputValues, + type CuratedTaskTemplateItem, +} from "@/components/agent/chat/utils/curatedTaskTemplates"; +import { listUnifiedMemories } from "@/lib/api/unifiedMemory"; +import { cn } from "@/lib/utils"; +import { + buildCuratedTaskReferenceEntries, + mergeCuratedTaskReferenceEntries, + normalizeCuratedTaskReferenceMemoryIds, + type CuratedTaskReferenceEntry, + type CuratedTaskReferenceSelection, +} from "@/components/agent/chat/utils/curatedTaskReferenceSelection"; + +interface CuratedTaskLauncherDialogProps { + open: boolean; + task: CuratedTaskTemplateItem | null; + initialInputValues?: CuratedTaskInputValues | null; + initialReferenceMemoryIds?: string[] | null; + initialReferenceEntries?: CuratedTaskReferenceEntry[] | null; + onOpenChange: (open: boolean) => void; + onConfirm: ( + task: CuratedTaskTemplateItem, + inputValues: CuratedTaskInputValues, + referenceSelection: CuratedTaskReferenceSelection, + ) => void; +} + +const MAX_REFERENCE_SELECTION_COUNT = 3; + +export function CuratedTaskLauncherDialog({ + open, + task, + initialInputValues, + initialReferenceMemoryIds, + initialReferenceEntries, + onOpenChange, + onConfirm, +}: CuratedTaskLauncherDialogProps) { + const [inputValues, setInputValues] = useState({}); + const [referenceEntries, setReferenceEntries] = useState< + CuratedTaskReferenceEntry[] + >([]); + const [selectedReferenceMemoryIds, setSelectedReferenceMemoryIds] = useState< + string[] + >([]); + const [isReferenceEntriesLoading, setIsReferenceEntriesLoading] = + useState(false); + const [referenceEntriesError, setReferenceEntriesError] = useState< + string | null + >(null); + + useEffect(() => { + if (!task || !open) { + setInputValues({}); + return; + } + + setInputValues( + resolveCuratedTaskInputValues({ + task, + inputValues: initialInputValues, + }), + ); + }, [initialInputValues, open, task]); + + useEffect(() => { + if (!task || !open) { + setReferenceEntries([]); + setSelectedReferenceMemoryIds([]); + setIsReferenceEntriesLoading(false); + setReferenceEntriesError(null); + return; + } + + const seededReferenceEntries = mergeCuratedTaskReferenceEntries( + initialReferenceEntries ?? [], + ); + const seededReferenceMemoryIds = + normalizeCuratedTaskReferenceMemoryIds([ + ...(initialReferenceMemoryIds ?? []), + ...seededReferenceEntries.map((entry) => entry.id), + ]) ?? []; + + setReferenceEntries(seededReferenceEntries); + setSelectedReferenceMemoryIds( + seededReferenceMemoryIds, + ); + setIsReferenceEntriesLoading(true); + setReferenceEntriesError(null); + + let cancelled = false; + + void listUnifiedMemories({ + archived: false, + sort_by: "updated_at", + order: "desc", + limit: 12, + }) + .then((memories) => { + if (cancelled) { + return; + } + + setReferenceEntries( + mergeCuratedTaskReferenceEntries([ + ...seededReferenceEntries, + ...buildCuratedTaskReferenceEntries(memories), + ]), + ); + }) + .catch(() => { + if (cancelled) { + return; + } + + setReferenceEntries([]); + setReferenceEntriesError("暂时没拿到灵感库,仍然可以直接进入生成。"); + }) + .finally(() => { + if (cancelled) { + return; + } + + setIsReferenceEntriesLoading(false); + }); + + return () => { + cancelled = true; + }; + }, [initialReferenceEntries, initialReferenceMemoryIds, open, task]); + + const isLaunchDisabled = useMemo(() => { + if (!task) { + return true; + } + + return !hasFilledAllCuratedTaskRequiredInputs({ + task, + inputValues, + }); + }, [inputValues, task]); + + const selectedReferenceEntries = useMemo(() => { + const referenceEntryMap = new Map( + referenceEntries.map((entry) => [entry.id, entry]), + ); + + return selectedReferenceMemoryIds + .map((id) => referenceEntryMap.get(id)) + .filter((entry): entry is CuratedTaskReferenceEntry => Boolean(entry)); + }, [referenceEntries, selectedReferenceMemoryIds]); + + const missingSelectedReferenceCount = + selectedReferenceMemoryIds.length - selectedReferenceEntries.length; + + const handleValueChange = (key: string, value: string) => { + setInputValues((current) => ({ + ...current, + [key]: value, + })); + }; + + const handleToggleReferenceEntry = (entryId: string) => { + setSelectedReferenceMemoryIds((current) => { + if (current.includes(entryId)) { + return current.filter((id) => id !== entryId); + } + + if (current.length >= MAX_REFERENCE_SELECTION_COUNT) { + return current; + } + + return [...current, entryId]; + }); + }; + + const handleConfirm = () => { + if (!task || isLaunchDisabled) { + return; + } + + onConfirm(task, inputValues, { + referenceMemoryIds: selectedReferenceMemoryIds, + referenceEntries: selectedReferenceEntries, + }); + }; + + return ( + + + {task ? ( +
+ +
+ + {task.badge} + + + {task.requiredInputFields.length} 项必填 + + + {task.outputHint} + +
+
+ + {task.title} + + + 先补最少启动信息,再统一进入生成主执行面。{task.summary} + +
+
+ +
+
+ {task.requiredInputFields.map((field) => { + const fieldId = `curated-task-${task.id}-${field.key}`; + const value = inputValues[field.key] ?? ""; + const commonClassName = + "mt-2 rounded-[18px] border-slate-200 bg-slate-50 focus-visible:ring-emerald-300"; + + return ( +
+
+ + {field.helperText ? ( +
+ {field.helperText} +
+ ) : null} + {field.type === "textarea" ? ( +