From 7851c34bed84c86cd9474cdd472fdbc3e386eba4 Mon Sep 17 00:00:00 2001 From: coso Date: Mon, 16 Feb 2026 20:58:55 +0800 Subject: [PATCH] release: v0.68.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Features - 版本升级至 0.68.0 ## Fixes - 修复 EmptyState 组件标题排版问题 - 修复"开始生成"按钮文字换行问题 - 修复加载历史对话失败问题 - 修复 parse_message_content 保留 ContentPart 结构 - 修复 convert_agent_message 添加 reasoning_content 处理 - 修复 WorkspaceType::from_str 命名冲突,重命名为 parse ## Code Quality - 修复所有 clippy 警告 - 修复 manual_flatten 警告 - 修复 ptr_arg 警告(使用 &Path 替代 &PathBuf) - 修复 manual_clamp 警告 - 修复 match_single_binding 警告 - 所有测试通过 (174 passed) --- README.md | 128 ++++-- docs/README.md | 65 ++- docs/content/01.introduction/1.overview.md | 79 ++-- .../content/01.introduction/2.installation.md | 12 +- docs/content/01.introduction/3.quickstart.md | 116 ++---- docs/content/02.user-guide/1.dashboard.md | 93 ++--- docs/content/02.user-guide/10.prompts.md | 158 ++----- docs/content/02.user-guide/11.skills.md | 186 ++------- docs/content/02.user-guide/12.settings.md | 149 ++----- docs/content/02.user-guide/13.plugins.md | 64 ++- docs/content/02.user-guide/14.resources.md | 65 +++ .../02.user-guide/15.image-generation.md | 60 +++ docs/content/02.user-guide/2.monitoring.md | 110 ++--- .../02.user-guide/3.credential-pool.md | 137 ++---- .../02.user-guide/4.configuration-example.md | 389 +++--------------- docs/content/02.user-guide/4.smart-routing.md | 152 ++----- docs/content/02.user-guide/5.resilience.md | 155 ++----- .../02.user-guide/6.config-management.md | 180 ++------ docs/content/02.user-guide/7.config-switch.md | 160 ++----- docs/content/02.user-guide/8.api-server.md | 165 ++------ docs/content/02.user-guide/9.mcp.md | 186 ++------- docs/content/03.providers/1.overview.md | 130 ++---- docs/content/03.providers/10.vertex-ai.md | 4 + docs/content/03.providers/2.kiro-claude.md | 4 + docs/content/03.providers/3.gemini-cli.md | 4 + docs/content/03.providers/4.qwen.md | 4 + docs/content/03.providers/5.openai-custom.md | 4 + docs/content/03.providers/6.claude-custom.md | 4 + docs/content/03.providers/7.codex.md | 4 + docs/content/03.providers/8.iflow.md | 4 + docs/content/03.providers/9.gemini-api-key.md | 4 + docs/content/04.api-reference/1.overview.md | 110 ++--- docs/content/04.api-reference/2.openai-api.md | 4 + docs/content/04.api-reference/3.claude-api.md | 4 + .../04.api-reference/4.management-api.md | 4 + .../content/04.api-reference/5.amp-cli-api.md | 4 + .../05.troubleshooting/1.common-issues.md | 165 +++----- .../05.troubleshooting/2.credential-errors.md | 151 ++----- .../05.troubleshooting/3.connection-issues.md | 188 ++------- .../06.development/5.plugin-development.md | 256 +----------- docs/content/08.open-platform/1.overview.md | 74 ++-- docs/content/08.open-platform/2.plugins.md | 128 ++---- .../08.open-platform/3.plugin-development.md | 235 ++--------- docs/content/08.open-platform/4.connect.md | 180 ++------ .../08.open-platform/5.connect-integration.md | 250 ++--------- .../08.open-platform/6.connect-webhook.md | 212 ++-------- docs/content/index.md | 169 ++------ docs/product-overview.md | 309 ++++---------- docs/three-stage-workflow-guide.md | 348 ---------------- src-tauri/Cargo.lock | 44 +- src-tauri/Cargo.toml | 6 +- src-tauri/crates/agent/src/aster_state.rs | 52 ++- src-tauri/crates/agent/src/session_store.rs | 53 ++- src-tauri/crates/core/Cargo.toml | 3 + src-tauri/crates/core/src/content/manager.rs | 2 +- .../crates/core/src/database/dao/agent.rs | 20 +- .../crates/core/src/database/migration.rs | 16 +- src-tauri/crates/core/src/database/mod.rs | 11 + src-tauri/crates/core/src/models/anthropic.rs | 144 +------ src-tauri/crates/core/src/models/openai.rs | 233 +---------- .../crates/core/src/workspace/manager.rs | 6 +- src-tauri/crates/core/src/workspace/types.rs | 51 +-- src-tauri/crates/memory/src/feedback.rs | 2 +- src-tauri/crates/memory/src/search.rs | 5 +- .../providers/src/converter/cw_to_openai.rs | 3 + .../services/src/project_context_builder.rs | 2 +- src-tauri/src/commands/unified_chat_cmd.rs | 180 +++++--- src-tauri/src/commands/workspace_cmd.rs | 2 +- src-tauri/test_serialize.rs | 20 + .../agent/chat/components/EmptyState.tsx | 5 +- .../agent/chat/hooks/useAsterAgentChat.ts | 3 +- 71 files changed, 1715 insertions(+), 4914 deletions(-) create mode 100644 docs/content/02.user-guide/14.resources.md create mode 100644 docs/content/02.user-guide/15.image-generation.md delete mode 100644 docs/three-stage-workflow-guide.md create mode 100644 src-tauri/test_serialize.rs diff --git a/README.md b/README.md index 049374cd7..8c6c919fd 100644 --- a/README.md +++ b/README.md @@ -2,23 +2,98 @@ # ProxyCast 🚀 -**AI Agent 创作工具平台** +**创作类 AI Agent 平台** -[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) -[![Tauri](https://img.shields.io/badge/Tauri-2.0-blue.svg)](https://tauri.app/) -[![React](https://img.shields.io/badge/React-18-61dafb.svg)](https://react.dev/) -[![Rust](https://img.shields.io/badge/Rust-1.70+-orange.svg)](https://www.rust-lang.org/) +一句话:把灵感、写作、出图、改稿、沉淀放进同一个工作台,让创作从“想到”直接走到“可发布”。 --- -## ✨ 核心特性 +## 👋 这是什么 -- **多 Provider 统一管理** - 支持 Kiro、Gemini、通义千问、Antigravity、Vertex AI 等多种 AI 服务 -- **智能凭证管理** - 自动检测凭证变化、Token 自动刷新、配额超限自动切换 -- **完整 API 兼容** - 支持 OpenAI Chat API 和 Anthropic Messages API -- **友好图形界面** - Dashboard 监控、Provider 管理、日志查看 +ProxyCast 是面向普通创作者的 AI Agent 平台。 +你不需要先懂复杂设置,只要带着一个想法进来,就可以在同一处完成: +- 和 Agent 对话定方向 +- 生成内容与素材 +- 继续迭代修改 +- 把结果沉淀成可复用资产 + +--- + +## 🧩 支持的创作主题 + +你可以按创作目标选择主题,也可以跨主题组合使用。 + +1. **通用对话**:灵感发散、问题梳理、快速头脑风暴 +2. **社媒内容**:选题、标题、正文、多平台改写 +3. **图文海报**:主视觉文案、配图方向、海报内容生成 +4. **歌词曲谱**:歌词起稿、段落续写、风格改编 +5. **知识探索**:知识点拆解、结构化总结、学习卡片 +6. **计划规划**:目标分解、执行节奏、阶段复盘 +7. **办公文档**:报告、方案、邮件、会议纪要整理 +8. **短视频**:脚本结构、分镜思路、口播文案生成 +9. **小说创作**:设定、章节推进、人物对白与续写 + +--- + +## 📖 创作场景(不止一种) + +### 场景 1:社媒日更 +- 场景:每天都要稳定发内容,但选题和表达容易重复。 +- 动作:先让 Agent 给出 3 个方向,再选一个生成多版文案与配图思路。 +- 结果:当天可直接发布,同时保留素材供后续复用。 + +### 场景 2:短视频起号 +- 场景:有想法但脚本总是“有点散”。 +- 动作:用主题工作流先拆结构,再生成口播稿和镜头节奏。 +- 结果:从模糊创意变成可拍摄脚本,沟通成本显著降低。 + +### 场景 3:小说连载 +- 场景:长期连载容易设定冲突、节奏断档。 +- 动作:在同一项目里持续积累世界观、人物设定和章节草稿。 +- 结果:剧情连贯性更强,更新更稳定。 + +### 场景 4:活动海报与图文 +- 场景:活动上线前要快速产出多套视觉方向。 +- 动作:先生成文案方向,再出图并按参考图持续迭代。 +- 结果:方案选择更快,历史版本可追溯、可复用。 + +### 场景 5:歌词创作 +- 场景:有旋律或主题,但歌词总卡在中段。 +- 动作:让 Agent 先给主副歌框架,再逐段续写与改写。 +- 结果:成稿速度更快,风格更统一。 + +### 场景 6:知识内容输出 +- 场景:学了很多但难以整理成可分享内容。 +- 动作:把资料整理成结构化要点,再输出为卡片或长文。 +- 结果:输入和输出形成闭环,知识更容易长期积累。 + +### 场景 7:计划执行 +- 场景:目标很大,但每天不知道先做什么。 +- 动作:把目标拆成周计划与日任务,并按进度复盘调整。 +- 结果:执行路径清晰,可持续推进。 + +### 场景 8:办公写作 +- 场景:报告、邮件、方案反复改,耗时高。 +- 动作:先生成初稿,再按受众快速改成不同版本。 +- 结果:沟通更顺,交付更快。 + +--- + +## 🎨 3 步开始创作 + +1. **选主题**:按目标进入对应创作主题 +2. **给输入**:一句需求、一个方向或一份素材都可以 +3. **持续迭代**:边聊边改边沉淀,最终得到可发布结果 + +--- + +## ❤️ 为什么好用 + +- **一个地方完成全流程**:从想法到成品不用来回切工具 +- **结果自动沉淀**:历史对话、素材、版本都可回看 +- **越用越顺手**:每个项目都有自己的上下文记忆 --- @@ -37,29 +112,29 @@ brew install --cask proxycast 从 [Releases](https://github.com/aiclientproxy/proxycast/releases) 下载对应平台安装包。 -### 使用 +--- -1. 启动 ProxyCast -2. 加载凭证 - Provider 管理页面点击"一键读取凭证" -3. 启动服务 - Dashboard 点击"启动服务器" -4. 配置客户端: - ``` - API Base URL: http://localhost:8999/v1 - API Key: 启动时自动生成(设置页查看) - ``` +## 🧭 适合谁 + +- 自媒体创作者 +- 短视频团队 +- 小说与剧情创作者 +- 运营与品牌内容团队 +- 需要长期沉淀创作资产的个人与小团队 --- -## 🛠️ 开发构建 +## 📚 文档与开发(可选) + +如果你是开发者,可查看: +- 项目文档:`docs/aiprompts/` +- Agent 指南:`AGENTS.md` + +开发命令: ```bash -# 安装依赖 npm install - -# 开发模式 npm run tauri dev - -# 构建发布 npm run tauri build ``` @@ -71,4 +146,5 @@ npm run tauri build ## ⚠️ 免责声明 -本项目仅供学习研究使用,用户需自行承担使用风险。本项目不提供 AI 模型服务,所有服务由第三方提供商提供。 +本项目仅供学习研究使用,用户需自行承担使用风险。 +本项目不直接提供 AI 模型服务,模型能力由第三方提供商提供。 diff --git a/docs/README.md b/docs/README.md index 769c15a70..c6e9a7bd3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,50 +1,37 @@ # docs - +## 目录定位 -## 架构说明 +`docs/` 是 ProxyCast 文档中心,分为两类受众: -项目文档目录,包含技术规格、操作指南、AI Agent 文档和文档站点配置。 -使用 Nuxt Content 构建文档站点。 +- 普通创作者:优先阅读 `content/` 下的入门与用户指南 +- 开发者与维护者:阅读 `aiprompts/`、`develop/`、`tests/` 等工程文档 -## 文件索引 +文档站基于 Nuxt Content 构建。 -- `aiprompts/` - AI Agent 模块文档(参考 aster-rust 模式) -- `content/` - 文档内容(Markdown) -- `develop/` - 开发文档 -- `images/` - 文档图片资源 -- `plugins/` - 插件文档 -- `prd/` - 产品需求文档 -- `tests/` - 测试文档 -- `TECH_SPEC.md` - 技术规格文档 -- `LLM_FLOW_MONITOR_SPEC.md` - LLM 流量监控规格 -- `ops.md` - 运维操作指南 -- `plugin-ui-design.md` - 插件 UI 设计文档 -- `three-stage-workflow-guide.md` - 三阶段工作流指南 -- `app.config.ts` - Nuxt 应用配置 -- `nuxt.config.ts` - Nuxt 框架配置 -- `package.json` - 文档站点依赖 +## 目录索引 -## aiprompts 文档索引 +- `content/`:对外文档站正文(产品介绍、用户指南、进阶能力) +- `aiprompts/`:模块级工程文档(前后端组件、服务、命令、数据层) +- `develop/`:开发流程与协作规范 +- `plugins/`:插件与扩展相关文档 +- `tests/`:测试策略与用例文档 +- `images/`:文档图片资源 +- `TECH_SPEC.md`:技术规格文档 +- `ops.md`:运维与发布说明 +- `app.config.ts` / `nuxt.config.ts` / `package.json`:文档站配置 -AI Agent 专用文档,提供模块级别的详细说明: +## 当前叙事基线 -- `overview.md` - 项目架构概览 -- `providers.md` - Provider 系统 -- `credential-pool.md` - 凭证池管理 -- `converter.md` - 协议转换 -- `server.md` - HTTP 服务器 -- `flow-monitor.md` - 流量监控 -- `components.md` - 组件系统 -- `hooks.md` - React Hooks -- `services.md` - 业务服务 -- `commands.md` - Tauri 命令 -- `mcp.md` - MCP 服务器 -- `lib.md` - 工具库 -- `plugins.md` - 插件系统 -- `database.md` - 数据库层 -- `terminal.md` - 内置终端 +对外文档(`content/`)默认采用以下口径: -## 更新提醒 +1. 主叙事是“创作类 AI Agent 平台”,不再以“代理服务”作为首页主线 +2. 先讲创作流程与场景,再讲模型连接和 API 兼容 +3. 首页与入门页优先覆盖九大创作主题与资源沉淀能力 -任何文件变更后,请更新此文档和相关的上级文档。 +## 维护原则 + +1. 先读后写:更新章节前先核对真实功能实现 +2. 用户优先:首屏文案避免工程术语堆叠 +3. 分层清晰:用户文档与工程文档分开表达 +4. 同步更新:功能改动后同步修正文档入口页与对应章节 diff --git a/docs/content/01.introduction/1.overview.md b/docs/content/01.introduction/1.overview.md index 04779e1de..fbff1d01d 100644 --- a/docs/content/01.introduction/1.overview.md +++ b/docs/content/01.introduction/1.overview.md @@ -1,73 +1,56 @@ --- title: 概述 -description: ProxyCast 项目介绍和核心价值 +description: 了解 ProxyCast 如何支持从灵感到发布的完整创作流程 navigation: icon: i-heroicons-home --- # ProxyCast 概述 -ProxyCast 是一款基于 Tauri 2.0 的跨平台桌面应用,让你可以**把 AI 客户端的订阅额度用到任何地方**。 +ProxyCast 是一款创作类 AI Agent 桌面应用。 +它把对话、内容生成、图片创作、项目管理、资源沉淀放到同一个工作台里。 ::alert{type="warning"} -**免责声明**: 本工具仅限于个人合法使用,严禁用于非法盈利目的。初衷是帮助用户充分利用已订阅的 AI 服务 Token。[查看完整声明](/legal/disclaimer) +**免责声明**: 请在合法合规前提下使用本产品。[查看完整声明](/legal/disclaimer) :: -## 核心价值 +## 你可以用它做什么 -你是否有以下困扰? +### 九大创作主题 -- 订阅了 Kiro、Claude Code 等 AI 编程助手,但只能在特定 IDE 中使用 -- 想在其他工具(如 Cursor、Continue、自定义脚本)中使用已有的 AI 额度 -- 需要管理多个 AI 服务的凭证,频繁切换很麻烦 +- 通用对话 +- 社媒内容 +- 图文海报 +- 歌词曲谱 +- 知识探索 +- 计划规划 +- 办公文档 +- 短视频 +- 小说创作 -ProxyCast 解决这些问题:将你的 AI 客户端凭证转换为标准的 OpenAI/Claude 兼容 API,让任何支持 OpenAI 接口的工具都能使用你的订阅额度。 +### 创作全流程 -## 支持的 Provider +1. 用 Agent 把想法变成清晰方向 +2. 生成文案、脚本或结构化草稿 +3. 按需要生成图片并继续迭代 +4. 把结果沉淀到项目和资源库,方便长期复用 -| Provider | 类型 | 认证方式 | 说明 | -|----------|------|----------|------| -| Kiro Claude | OAuth | 自动刷新 | AWS Kiro IDE 的 Claude 凭证 | -| Gemini CLI | OAuth | 自动刷新 | Google Gemini CLI 凭证 | -| Qwen (通义千问) | OAuth | 自动刷新 | 阿里云通义千问凭证 | -| OpenAI Custom | API Key | 手动配置 | 自定义 OpenAI 兼容服务 | -| Claude Custom | API Key | 手动配置 | 自定义 Claude 兼容服务 | +### 一站式工作台 -## 核心特性 - -### 🔑 凭证池管理 -- 支持多个 Provider 凭证的统一管理 -- 自动检测和加载本地凭证文件 -- OAuth Token 自动刷新机制 - -### ⚖️ 智能路由 -- 基于模型名称的请求路由 -- 负载均衡和优先级配置 -- 健康检查和自动故障转移 - -### 🛡️ 容错机制 -- 可配置的重试策略 -- 超时控制和熔断器 -- 多 Provider 故障转移 - -### 🔄 协议转换 -- OpenAI Chat Completions API 兼容 -- Claude Messages API 兼容 -- 自动格式转换 - -### 📊 监控统计 -- 实时请求统计 -- Token 使用追踪 -- 详细的请求日志 +- AI 对话与创作在同一处完成 +- 项目隔离上下文,避免内容串线 +- 资源按文档/图片/语音/视频分类管理 +- 支持参考图参与图片生成与编辑链路 ## 使用场景 -1. **IDE 集成**: 在 Cursor、Continue 等编辑器中使用 Kiro/Claude Code 额度 -2. **脚本调用**: 在 Python/Node.js 脚本中调用 AI API -3. **多账户管理**: 统一管理多个 AI 服务账户 -4. **团队共享**: 通过配置导出分享 Provider 设置 +1. **自媒体创作**:每天稳定产出选题、文案、配图 +2. **短视频团队**:快速完成脚本与分镜草稿 +3. **小说连载**:持续积累设定、章节与角色信息 +4. **品牌运营**:统一管理活动素材与历史版本 ## 下一步 - [安装指南](/introduction/installation) - 下载并安装 ProxyCast -- [快速开始](/introduction/quickstart) - 5 分钟内完成首次 API 调用 +- [快速开始](/introduction/quickstart) - 3 步完成首次创作 +- [首页与工作台](/user-guide/dashboard) - 熟悉核心入口 diff --git a/docs/content/01.introduction/2.installation.md b/docs/content/01.introduction/2.installation.md index 76a86f1f8..3e0356cd0 100644 --- a/docs/content/01.introduction/2.installation.md +++ b/docs/content/01.introduction/2.installation.md @@ -1,6 +1,6 @@ --- title: 安装指南 -description: 下载并安装 ProxyCast +description: 下载、安装并验证 ProxyCast 可正常启动 navigation: icon: i-heroicons-arrow-down-tray --- @@ -16,7 +16,7 @@ navigation: ## 下载 -从 GitHub Tags 下载最新版本: +从 GitHub Releases/Tags 下载最新版本安装包: [下载 ProxyCast](https://github.com/aiclientproxy/proxycast/tags) @@ -49,9 +49,9 @@ navigation: 启动 ProxyCast 后,你应该看到: -1. 系统托盘图标出现 -2. 主窗口显示仪表盘 -3. 服务状态显示"已停止"(首次启动) +1. 主窗口正常打开 +2. 左侧出现主要入口(AI Agent、项目、资源、图片生成等) +3. 可以进入设置页并看到版本信息 ## 常见安装问题 @@ -68,4 +68,4 @@ xattr -cr /Applications/ProxyCast.app ## 下一步 -安装完成后,继续阅读 [快速开始](/introduction/quickstart) 配置你的第一个 Provider。 +安装完成后,继续阅读 [快速开始](/introduction/quickstart),用 3 步完成第一次创作。 diff --git a/docs/content/01.introduction/3.quickstart.md b/docs/content/01.introduction/3.quickstart.md index 55f1aee9d..896742278 100644 --- a/docs/content/01.introduction/3.quickstart.md +++ b/docs/content/01.introduction/3.quickstart.md @@ -1,116 +1,64 @@ --- title: 快速开始 -description: 5 分钟内完成首次 API 调用 +description: 3 步完成首次创作并沉淀到项目资源库 navigation: icon: i-heroicons-rocket-launch --- # 快速开始 -本指南帮助你在 5 分钟内完成 ProxyCast 的基本配置和首次 API 调用。 +本指南帮助你在几分钟内完成第一次完整创作流程。 ## 前置准备 确保你已经: - [x] 安装了 ProxyCast -- [x] 拥有至少一个 AI 客户端的有效订阅(Kiro、Gemini CLI、Qwen 等) +- [x] 可以正常打开应用主界面 -## 步骤 1: 启动 ProxyCast +## 步骤 1:选择创作主题与项目 -1. 启动 ProxyCast 应用 -2. 主窗口会显示仪表盘界面 +1. 启动 ProxyCast,进入 AI Agent 或项目入口 +2. 选择你的主题方向(如社媒、短视频、小说) +3. 新建项目,作为本次创作的工作空间 -## 步骤 2: 加载凭证 +## 步骤 2:输入需求并生成内容 -ProxyCast 会自动检测本地的 AI 客户端凭证文件。 +1. 用一句话描述你的目标 +2. 让 Agent 先给结构,再生成首稿 +3. 如需视觉内容,进入图片生成功能继续产出与迭代 -### 凭证文件位置 +## 步骤 3:沉淀到资源库 -| Provider | 凭证路径 | -|----------|----------| -| Kiro Claude | `~/.kiro/credentials.json` | -| Gemini CLI | `~/.config/gemini-cli/oauth_creds.json` | -| Qwen | `~/.config/qwen/credentials.json` | +1. 将文档、图片等结果保存到当前项目资源库 +2. 在资源页按分类查看(文档/图片/语音/视频) +3. 下次创作直接复用历史素材和上下文 -### 手动添加凭证 +## 一个最小创作示例 -如果自动检测未找到凭证: +1. 主题:`短视频` +2. 输入:`做一条 30 秒“高效晨间复盘”口播内容` +3. 产出: + - 3 个开场钩子 + - 1 版结构化口播稿 + - 1 组配图提示词或参考图改写结果 -1. 进入 **凭证池** 页面 -2. 点击 **添加凭证** -3. 选择 Provider 类型 -4. 输入凭证信息或选择凭证文件 +## 常见问题 -## 步骤 3: 启动 API Server +### 我可以只用对话,不做图片吗? -1. 在仪表盘点击 **启动服务** -2. 服务状态变为"运行中" -3. 记下 API 地址(默认 `http://127.0.0.1:8999`) +可以。你可以只用 AI Agent 完成文本创作和项目沉淀。 -## 步骤 4: 测试 API +### 我可以直接改图吗? -### 使用内置测试面板 +可以。上传参考图后,若所选模型支持编辑接口,会自动走编辑链路。 -1. 在仪表盘找到 **API 测试** 区域 -2. 输入测试消息 -3. 点击发送,查看响应 +### 我还需要 API 接入能力怎么办? -### 使用 curl 测试 - -**OpenAI 格式:** - -```bash -curl http://127.0.0.1:8999/v1/chat/completions \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer your-api-key" \ - -d '{ - "model": "claude-sonnet-4-20250514", - "messages": [{"role": "user", "content": "Hello!"}] - }' -``` - -**Claude 格式:** - -```bash -curl http://127.0.0.1:8999/v1/messages \ - -H "Content-Type: application/json" \ - -H "x-api-key: your-api-key" \ - -H "anthropic-version: 2023-06-01" \ - -d '{ - "model": "claude-sonnet-4-20250514", - "max_tokens": 1024, - "messages": [{"role": "user", "content": "Hello!"}] - }' -``` - -## 步骤 5: 集成到其他工具 - -### Cursor 配置 - -在 Cursor 设置中配置 OpenAI API: - -- API Base URL: `http://127.0.0.1:8999/v1` -- API Key: 你在 ProxyCast 中设置的 API Key - -### Continue 配置 - -编辑 `~/.continue/config.json`: - -```json -{ - "models": [{ - "title": "ProxyCast Claude", - "provider": "openai", - "model": "claude-sonnet-4-20250514", - "apiBase": "http://127.0.0.1:8999/v1", - "apiKey": "your-api-key" - }] -} -``` +可以继续阅读 [API Server](/user-guide/api-server) 和 [API 参考](/api-reference/overview)。 ## 下一步 -- [仪表盘](/user-guide/dashboard) - 了解仪表盘功能 -- [凭证池](/user-guide/credential-pool) - 管理多个凭证 -- [智能路由](/user-guide/smart-routing) - 配置请求路由规则 +- [首页与工作台](/user-guide/dashboard) - 理解核心导航 +- [资源库](/user-guide/resources) - 管理创作资产 +- [图片生成与编辑](/user-guide/image-generation) - 深入图片链路 diff --git a/docs/content/02.user-guide/1.dashboard.md b/docs/content/02.user-guide/1.dashboard.md index c0d820de7..67b5031af 100644 --- a/docs/content/02.user-guide/1.dashboard.md +++ b/docs/content/02.user-guide/1.dashboard.md @@ -1,75 +1,58 @@ --- -title: 仪表盘 -description: 监控和控制代理服务 +title: 首页与工作台 +description: 首页与创作工作台总览 navigation: icon: i-heroicons-chart-bar --- -# 仪表盘 +# 首页与工作台 -仪表盘是 ProxyCast 的主界面,提供服务状态监控和快速操作入口。 +首页是你进入 ProxyCast 后的主入口。 +建议把它理解为“创作操作台”,而不是单一功能面板。 -## 服务状态 +## 左侧核心入口 -仪表盘顶部显示当前服务状态: +- **AI Agent**:对话、任务推进、内容初稿 +- **项目**:按创作目标管理长期内容 +- **资源**:统一查看文档、图片、语音、视频 +- **图片生成**:生成图片、参考图编辑、结果回流资源库 +- **设置**:调整主题、模块开关、连接与高级选项 -| 状态 | 说明 | -|------|------| -| 🟢 运行中 | API Server 正在运行,可以接收请求 | -| 🔴 已停止 | API Server 未启动 | -| 🟡 启动中 | 服务正在初始化 | +## 推荐工作方式 -## 控制按钮 +1. 先在项目中选择一个创作主题 +2. 在 AI Agent 中完成结构和首稿 +3. 需要视觉时进入图片生成 +4. 回到资源库统一管理结果 -- **启动服务**: 启动 API Server -- **停止服务**: 停止 API Server -- **重启服务**: 重新启动服务 +## 创作主题 -## API 信息 +当前支持的主题包括: -服务运行时显示: +- 通用对话 +- 社媒内容 +- 图文海报 +- 歌词曲谱 +- 知识探索 +- 计划规划 +- 办公文档 +- 短视频 +- 小说创作 -- **API 地址**: 本地 API 端点(如 `http://127.0.0.1:8999`) -- **API Key**: 当前配置的访问密钥 -- **复制按钮**: 一键复制 API 地址或 Key +## 常见操作 -## API 测试面板 +### 新建一个创作项目 -内置的 API 测试工具: +1. 进入项目页 +2. 选择主题并创建项目 +3. 开始持续沉淀对话与素材 -1. **消息输入**: 输入测试消息 -2. **模型选择**: 选择要使用的模型 -3. **发送请求**: 点击发送测试请求 -4. **响应显示**: 查看 AI 响应结果 +### 从资源继续创作 -### 测试示例 +1. 在资源页选中历史文档或图片 +2. 跳转到 AI Agent 继续改写或扩展 +3. 将新结果再次沉淀回资源库 -``` -用户: Hello, how are you? -助手: I'm doing well, thank you for asking! How can I help you today? -``` +### 只看某类素材 -## 请求统计 - -实时统计信息: - -- **总请求数**: 累计处理的请求数量 -- **成功率**: 请求成功百分比 -- **平均延迟**: 请求平均响应时间 -- **Token 使用**: 累计 Token 消耗 - -## 凭证状态 - -显示当前可用的凭证: - -| 字段 | 说明 | -|------|------| -| Provider | 凭证类型 | -| 状态 | 有效/过期/错误 | -| 剩余额度 | 可用额度(如支持) | - -## 快捷操作 - -- **打开设置**: 进入设置页面 -- **查看日志**: 打开请求日志 -- **刷新凭证**: 重新加载凭证文件 +在资源页切换分类视图,可只看文档、图片、语音或视频。 diff --git a/docs/content/02.user-guide/10.prompts.md b/docs/content/02.user-guide/10.prompts.md index 653b7dc05..f76195b89 100644 --- a/docs/content/02.user-guide/10.prompts.md +++ b/docs/content/02.user-guide/10.prompts.md @@ -1,150 +1,50 @@ --- -title: Prompts 管理 -description: 提示词存储和管理 +title: 提示词模板 +description: 管理可复用提示词,提升稳定产出效率 navigation: icon: i-heroicons-document-text --- -# Prompts 管理 +# 提示词模板 -Prompts 功能帮助你存储、组织和复用常用的提示词模板。 +提示词模板用于把“经常重复的表达方式”沉淀下来,减少每次从零开始。 -## 提示词存储 +## 模板结构建议 -### 创建提示词 +每个模板建议包含: -1. 进入 **Prompts** 页面 -2. 点击 **新建提示词** -3. 填写提示词信息: +- 名称(便于检索) +- 使用场景(何时用) +- 模板正文(可复用) +- 变量占位(可选) -| 字段 | 说明 | -|------|------| -| 名称 | 提示词标识名称 | -| 描述 | 提示词用途说明 | -| 内容 | 提示词正文 | -| 标签 | 分类标签 | +## 示例:短视频口播模板 -### 提示词示例 - -```yaml -name: "代码审查" -description: "审查代码质量和最佳实践" -content: | - 请审查以下代码,关注: - 1. 代码质量和可读性 - 2. 潜在的 bug 和安全问题 - 3. 性能优化建议 - 4. 最佳实践遵循情况 - - 请提供具体的改进建议。 -tags: - - 代码 - - 审查 +```text +你是一名内容策划。 +请基于主题「{{topic}}」生成一段 {{duration}} 秒口播稿,要求: +1. 开头 3 秒有抓力 +2. 中段给出 3 个关键点 +3. 结尾有明确行动引导 +语气风格:{{tone}} ``` -## 组织方式 +## 推荐组织方式 -### 文件夹分类 +- 按主题分类:社媒、短视频、小说、办公 +- 按阶段分类:灵感、初稿、润色、发布 +- 统一标签:例如 `#高频`、`#可复用` -创建文件夹组织提示词: +## 使用建议 -- 📁 代码相关 - - 代码审查 - - 代码重构 - - 单元测试 -- 📁 写作相关 - - 文档撰写 - - 邮件回复 -- 📁 翻译相关 - - 中英翻译 - - 技术翻译 +### 一次只优化一个模板 -### 标签系统 +避免同时改太多模板,难以判断效果。 -使用标签快速筛选: +### 模板要留“可变空间” -- `#代码` - 代码相关提示词 -- `#写作` - 写作相关提示词 -- `#常用` - 常用提示词 +把固定规则写清楚,把创意部分留给变量。 -### 搜索功能 +### 和项目结合 -支持按以下条件搜索: - -- 名称 -- 描述 -- 内容 -- 标签 - -## 注入请求 - -### 系统提示词 - -将提示词作为系统消息注入: - -```json -{ - "model": "claude-sonnet-4-20250514", - "messages": [ - {"role": "system", "content": "你是一个代码审查专家..."}, - {"role": "user", "content": "请审查这段代码..."} - ] -} -``` - -### 使用方式 - -1. **手动复制**: 复制提示词内容到请求 -2. **快捷插入**: 在 API 测试面板选择提示词 -3. **自动注入**: 配置默认系统提示词 - -### 配置默认提示词 - -1. 进入 **设置** > **API Server** -2. 选择 **默认系统提示词** -3. 所有请求自动注入该提示词 - -## 变量支持 - -### 定义变量 - -在提示词中使用变量: - -``` -请将以下 {{source_lang}} 文本翻译成 {{target_lang}}: - -{{content}} -``` - -### 使用变量 - -调用时替换变量值: - -```json -{ - "prompt": "翻译模板", - "variables": { - "source_lang": "英文", - "target_lang": "中文", - "content": "Hello, world!" - } -} -``` - -## 导入导出 - -### 导出提示词 - -1. 选择要导出的提示词 -2. 点击 **导出** -3. 保存为 `.json` 或 `.yaml` 文件 - -### 导入提示词 - -1. 点击 **导入** -2. 选择提示词文件 -3. 确认导入 - -### 分享提示词 - -导出的提示词文件可以分享给他人使用。 +在项目中沉淀效果好的模板,后续同类任务可直接复用。 diff --git a/docs/content/02.user-guide/11.skills.md b/docs/content/02.user-guide/11.skills.md index 1ef9c6403..f07414092 100644 --- a/docs/content/02.user-guide/11.skills.md +++ b/docs/content/02.user-guide/11.skills.md @@ -1,171 +1,55 @@ --- -title: Skills 技能 -description: 可扩展的技能模块系统 +title: 技能工作流 +description: 把常见任务封装成可复用的 AI 技能 navigation: icon: i-heroicons-sparkles --- -# Skills 技能 +# 技能工作流 -Skills 是预定义的 AI 交互模式,封装了特定任务的提示词、参数和工具配置。 +技能可以理解为“可复用的任务卡片”: -## 技能定义 +- 预设目标 +- 预设风格 +- 预设步骤 -### 什么是技能 +这样每次执行同类任务时,不必重复手工组织提示。 -技能是一个完整的 AI 交互配置包,包含: +## 技能适合做什么 -- 系统提示词 -- 参数配置 -- 工具绑定 -- 输出格式 +- 固定流程写作(如周报、复盘、活动文案) +- 固定结构产出(如短视频脚本、小说章节骨架) +- 固定标准检查(如发布前检查清单) -### 技能示例 +## 技能卡建议字段 + +- 名称:明确任务类型 +- 描述:写清输入与输出 +- 系统指令:定义角色与规则 +- 参数:控制风格与长度 +- 输出格式:约束结果结构 + +## 示例:活动文案技能 ```yaml -name: "代码解释器" -description: "解释代码功能和逻辑" +name: "活动文案生成" +description: "根据主题生成活动预热文案与发布文案" system_prompt: | - 你是一个代码解释专家。请详细解释用户提供的代码: - 1. 代码的整体功能 - 2. 关键逻辑的解释 - 3. 使用的设计模式 - 4. 潜在的改进点 -parameters: - temperature: 0.3 - max_tokens: 2000 -output_format: markdown + 你是一名品牌内容策划,输出要简洁、有行动感。 +output_format: "markdown" ``` -## 创建技能 +## 组合为流程 -### 新建技能 +你可以把多个技能串成流程,例如: -1. 进入 **Skills** 页面 -2. 点击 **新建技能** -3. 配置技能信息 +1. 选题拆解 +2. 初稿生成 +3. 风格统一 +4. 发布前检查 -### 配置选项 +## 团队使用建议 -| 字段 | 说明 | -|------|------| -| 名称 | 技能标识名称 | -| 描述 | 技能用途说明 | -| 系统提示词 | 技能的核心提示词 | -| 参数 | 模型参数配置 | -| 工具 | 绑定的 MCP 工具 | -| 输出格式 | 期望的输出格式 | - -## 参数配置 - -### 模型参数 - -| 参数 | 说明 | 默认值 | -|------|------|--------| -| temperature | 创造性程度 | 0.7 | -| max_tokens | 最大输出长度 | 4096 | -| top_p | 采样范围 | 1.0 | -| presence_penalty | 重复惩罚 | 0 | - -### 参数模板 - -为不同场景预设参数: - -```yaml -# 精确任务 -precise: - temperature: 0.1 - top_p: 0.9 - -# 创意任务 -creative: - temperature: 0.9 - top_p: 1.0 - -# 代码生成 -coding: - temperature: 0.2 - max_tokens: 8000 -``` - -## 应用技能 - -### 在 API 测试中使用 - -1. 打开 **API 测试** 面板 -2. 点击 **选择技能** -3. 选择要使用的技能 -4. 输入用户消息 -5. 发送请求 - -### 通过 API 调用 - -```bash -curl http://127.0.0.1:8999/v1/chat/completions \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer your-api-key" \ - -d '{ - "model": "claude-sonnet-4-20250514", - "skill": "代码解释器", - "messages": [ - {"role": "user", "content": "解释这段代码: function add(a, b) { return a + b; }"} - ] - }' -``` - -### 技能链 - -组合多个技能形成工作流: - -```yaml -name: "代码审查流程" -steps: - - skill: "代码分析" - - skill: "安全检查" - - skill: "性能评估" - - skill: "改进建议" -``` - -## 内置技能 - -### 代码相关 - -| 技能 | 说明 | -|------|------| -| 代码解释 | 解释代码功能 | -| 代码审查 | 审查代码质量 | -| 代码重构 | 提供重构建议 | -| Bug 修复 | 分析和修复 bug | - -### 写作相关 - -| 技能 | 说明 | -|------|------| -| 文档撰写 | 撰写技术文档 | -| 邮件回复 | 生成邮件回复 | -| 内容总结 | 总结长文内容 | - -### 翻译相关 - -| 技能 | 说明 | -|------|------| -| 通用翻译 | 中英互译 | -| 技术翻译 | 技术文档翻译 | - -## 技能管理 - -### 编辑技能 - -1. 点击技能的 **编辑** 按钮 -2. 修改配置 -3. 保存更改 - -### 删除技能 - -1. 点击 **删除** 按钮 -2. 确认删除 - -### 导入导出 - -- **导出**: 将技能导出为 `.yaml` 文件 -- **导入**: 从文件导入技能 +1. 共享高频技能模板 +2. 每个技能指定维护人 +3. 定期清理低使用技能,保持列表可维护 diff --git a/docs/content/02.user-guide/12.settings.md b/docs/content/02.user-guide/12.settings.md index 238a0793a..38d0e443e 100644 --- a/docs/content/02.user-guide/12.settings.md +++ b/docs/content/02.user-guide/12.settings.md @@ -1,141 +1,60 @@ --- title: 设置 -description: 应用设置和偏好管理 +description: 管理应用偏好、导航模块和进阶系统选项 navigation: icon: i-heroicons-cog-6-tooth --- # 设置 -设置页面用于配置 ProxyCast 的各项参数和偏好。 +设置页用于管理你的创作体验与系统行为。 -## 通用设置 +## 通用 -### 应用行为 +常见选项: -| 选项 | 说明 | -|------|------| -| 开机自启动 | 系统启动时自动运行 ProxyCast | -| 启动时运行服务 | 应用启动时自动启动 API Server | -| 最小化到托盘 | 关闭窗口时最小化到系统托盘 | -| 显示托盘图标 | 在系统托盘显示图标 | +- 主题模式(浅色 / 深色 / 跟随系统) +- 语言选择 +- 启动行为(开机自启动、最小化到托盘) +- 声音反馈开关 -### 更新设置 +## 创作与导航偏好 -| 选项 | 说明 | -|------|------| -| 自动检查更新 | 定期检查新版本 | -| 自动下载更新 | 有新版本时自动下载 | -| 更新通知 | 有更新时显示通知 | +你可以按使用习惯定制入口: -## 认证目录 +- 启用或停用创作主题(如社媒、短视频、小说) +- 启用或停用导航模块(如 AI Agent、项目、图片生成、终端、工具、插件) -### 默认凭证路径 +这样可以让侧边栏更聚焦,减少干扰。 -ProxyCast 默认扫描以下路径: +## 连接与系统 -| Provider | 默认路径 | -|----------|----------| -| Kiro | `~/.kiro/credentials.json` | -| Gemini CLI | `~/.config/gemini-cli/oauth_creds.json` | -| Qwen | `~/.config/qwen/credentials.json` | +系统相关设置在这里管理: -### 自定义路径 +- 连接与网络代理 +- 安全与证书 +- 存储目录与配额 +- 外部工具联动 +- 实验室与开发者选项 -添加自定义凭证扫描路径: +## 关于与版本 -1. 进入 **设置** > **认证目录** -2. 点击 **添加路径** -3. 选择目录或文件 -4. 指定 Provider 类型 +在“关于”标签页可以查看: -### 路径配置 +- 当前版本号 +- 更新检查入口 +- 相关项目信息 -```yaml -auth_dirs: - - path: "~/.kiro" - provider: kiro - pattern: "credentials*.json" - - path: "/custom/path" - provider: gemini - pattern: "*.json" -``` +## 建议配置 -## 偏好管理 +### 个人创作者 -### 主题设置 +- 保留:AI Agent、项目、资源、图片生成 +- 关闭:暂时不用的高级模块 +- 目的:让工作台聚焦在“日常产出” -| 选项 | 说明 | -|------|------| -| 浅色模式 | 使用浅色主题 | -| 深色模式 | 使用深色主题 | -| 跟随系统 | 跟随系统主题设置 | +### 团队协作 -### 语言设置 - -支持的语言: - -- 简体中文 -- English - -### 通知设置 - -| 选项 | 说明 | -|------|------| -| 服务状态通知 | 服务启动/停止时通知 | -| 错误通知 | 发生错误时通知 | -| 凭证过期通知 | 凭证即将过期时通知 | - -## 数据管理 - -### 数据存储位置 - -ProxyCast 数据存储在: - -| 平台 | 路径 | -|------|------| -| macOS | `~/Library/Application Support/ProxyCast` | -| Windows | `%APPDATA%\ProxyCast` | - -### 清除数据 - -| 选项 | 说明 | -|------|------| -| 清除日志 | 删除所有请求日志 | -| 清除统计 | 重置统计数据 | -| 清除缓存 | 清除应用缓存 | -| 重置设置 | 恢复默认设置 | - -::alert{type="warning"} -清除数据操作不可恢复,请谨慎操作。 -:: - -## 高级设置 - -### 日志级别 - -| 级别 | 说明 | -|------|------| -| Error | 仅记录错误 | -| Warn | 记录警告和错误 | -| Info | 记录一般信息 | -| Debug | 记录调试信息 | -| Trace | 记录所有信息 | - -### 代理设置 - -配置网络代理: - -| 选项 | 说明 | -|------|------| -| HTTP 代理 | HTTP 代理地址 | -| HTTPS 代理 | HTTPS 代理地址 | -| 不代理地址 | 不使用代理的地址列表 | - -### 性能设置 - -| 选项 | 默认值 | 说明 | -|------|--------|------| -| 最大并发请求 | 10 | 同时处理的最大请求数 | -| 请求队列大小 | 100 | 等待队列的最大长度 | -| 日志保留天数 | 30 | 日志文件保留时间 | +- 统一主题配置 +- 固定项目命名规则 +- 约定资源标签方式 diff --git a/docs/content/02.user-guide/13.plugins.md b/docs/content/02.user-guide/13.plugins.md index 37e0a4d80..978cdaeac 100644 --- a/docs/content/02.user-guide/13.plugins.md +++ b/docs/content/02.user-guide/13.plugins.md @@ -1,35 +1,28 @@ +--- +title: 插件中心 +description: 安装和管理扩展插件,按需扩展创作能力 +navigation: + icon: i-heroicons-puzzle-piece +--- + # 插件中心 ::alert{type="info"} -📢 本文档已迁移至开放平台。请访问 [开放平台 - 插件中心](/open-platform/plugins) 获取最新内容。 +📢 插件属于进阶能力。若你只做日常创作,可先跳过本页。 :: -ProxyCast 支持通过插件扩展功能。插件中心提供插件的安装、管理和配置。 +插件中心用于扩展 ProxyCast 的能力,例如新增工具、接入外部流程、扩展特定场景工作流。 ## 访问插件中心 点击左侧导航栏的「插件中心」进入插件管理页面。 -## 功能概览 +## 你能做什么 -### 推荐插件 - -插件中心会显示推荐的插件列表,点击「一键安装」即可快速安装。 - -### 已安装插件 - -显示所有已安装的插件,包括: -- 插件名称和版本 -- 安装来源(本地/URL/GitHub) -- 启用/禁用状态 -- 卸载按钮 - -### 已加载插件 - -显示当前运行中的插件状态: -- 执行次数 -- 错误次数 -- 最后执行时间 +- 浏览推荐插件并一键安装 +- 通过本地文件或 URL 安装插件包 +- 管理启用状态与卸载 +- 查看插件加载与执行状态 ## 安装插件 @@ -56,22 +49,19 @@ ProxyCast 支持通过插件扩展功能。插件中心提供插件的安装、 3. 选择本地的 `.zip` 文件 4. 点击「安装」 -## 使用插件 +## 使用建议 -安装完成后,插件会根据类型出现在不同位置: +### 从小处开始 -### 工具类插件 +先安装 1 到 2 个高频插件,观察是否真正提升你的创作效率,再决定是否扩展更多插件。 -工具类插件会出现在「工具箱」页面: +### 明确用途 -1. 点击左侧导航栏的「工具」 -2. 在工具列表中找到已安装的插件 -3. 点击「打开工具」使用 +每个插件都应对应明确目的,例如: -### 其他类型插件 - -- **Hook 插件**: 自动在请求/响应时执行 -- **侧边栏插件**: 出现在主侧边栏(规划中) +- 扩展素材处理 +- 增加内容生成模板 +- 对接外部工作流 ## 管理插件 @@ -87,13 +77,11 @@ ProxyCast 支持通过插件扩展功能。插件中心提供插件的安装、 卸载会删除插件文件和配置,但不会删除插件产生的数据。 -## 二进制组件 +## 进阶阅读 -部分功能需要安装额外的二进制组件: - -- **aster-server**: AI Agent 框架,提供 Agent 对话能力 - -在「二进制组件」区域可以查看和管理这些组件。 +- [开放平台 - 总览](/open-platform/overview) +- [开放平台 - 插件中心](/open-platform/plugins) +- [开放平台 - 插件开发](/open-platform/plugin-development) ## 常见问题 diff --git a/docs/content/02.user-guide/14.resources.md b/docs/content/02.user-guide/14.resources.md new file mode 100644 index 000000000..df0245cf1 --- /dev/null +++ b/docs/content/02.user-guide/14.resources.md @@ -0,0 +1,65 @@ +--- +title: 资源库 +description: 管理项目中的文档、图片、语音和视频素材 +navigation: + icon: i-heroicons-folder-open +--- + +# 资源库 + +资源库是 ProxyCast 的创作资产中心。 +它和项目绑定,用来长期沉淀你的创作结果。 + +## 资源分类 + +资源页支持按分类查看: + +- 全部 +- 文档 +- 图片 +- 语音 +- 视频 + +当你只想找图或找文档时,直接切换分类即可。 + +## 常见操作 + +### 新建与上传 + +1. 选择左侧资源库(项目) +2. 新建文件夹或新建文档 +3. 上传本地文件到当前目录 + +### 搜索与排序 + +- 支持按名称、描述、标签搜索 +- 支持按更新时间、创建时间、名称排序 + +### 重命名与删除 + +在资源列表的操作菜单中,可对资源进行重命名、删除等操作。 + +## 资源与创作联动 + +### 从图片生成回流资源库 + +在图片生成页选择目标资源库后,成功生成的图片可自动写入当前项目。 + +### 从资源继续对话创作 + +在资源页选中素材后,可继续进入 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 new file mode 100644 index 000000000..513494d81 --- /dev/null +++ b/docs/content/02.user-guide/15.image-generation.md @@ -0,0 +1,60 @@ +--- +title: 图片生成与编辑 +description: 通过文本与参考图完成图片生成、编辑与资产沉淀 +navigation: + icon: i-heroicons-photo +--- + +# 图片生成与编辑 + +图片生成页用于完成从“文字描述”到“可用图片素材”的全过程。 + +## 基本流程 + +1. 选择模型与参数(尺寸、比例、数量) +2. 输入提示词 +3. 可选上传参考图 +4. 生成后选图并沉淀到资源库 + +## 参考图与编辑 + +### 上传参考图 + +可上传参考图作为创作输入,帮助模型更贴近目标风格或构图。 + +### 编辑链路 + +当模型支持图片编辑接口时,系统会优先尝试编辑端点; +若不可用,会自动回退到可用生成端点,尽量保障出图成功率。 + +## 历史记录 + +历史区域会保存你的生成记录,支持: + +- 查看单张或批次结果 +- 重新选择目标图继续迭代 +- 将历史结果补录到资源库 + +## 与资源库联动 + +### 目标资源库 + +生成前可指定目标资源库(项目),用于自动沉淀图片资产。 + +### 补录历史 + +如果历史图片尚未入库,可使用“补录历史到资源库”进行批量回填。 + +## 实用建议 + +### 先定方向再出图 + +先在 AI Agent 里明确画面目标,再进入图片生成功能,会减少无效尝试。 + +### 一次只改一个变量 + +每轮仅调整一个维度(提示词、比例、参考图),更容易稳定收敛到理想结果。 + +### 把可用版本及时入库 + +选中可用图片后尽快入库,方便后续在资源页检索和复用。 diff --git a/docs/content/02.user-guide/2.monitoring.md b/docs/content/02.user-guide/2.monitoring.md index 3a922c86e..3fdc530f9 100644 --- a/docs/content/02.user-guide/2.monitoring.md +++ b/docs/content/02.user-guide/2.monitoring.md @@ -1,103 +1,61 @@ --- -title: 监控中心 -description: 请求统计和性能监控 +title: 创作数据与监控 +description: 查看创作产出趋势、调用状态与问题定位信息 navigation: icon: i-heroicons-eye --- -# 监控中心 +# 创作数据与监控 -监控中心提供详细的请求统计、性能指标和日志查看功能。 +监控页帮助你回答三个问题: -## 监控界面 +1. 最近创作是否稳定 +2. 哪些任务成功率更高 +3. 出现异常时该从哪里排查 -### 概览面板 +## 你能看到什么 -显示关键指标的实时数据: +### 概览指标 -- **请求总数**: 今日/本周/本月请求量 -- **成功率**: 请求成功百分比 -- **平均延迟**: 响应时间统计 -- **活跃凭证**: 当前可用凭证数量 +常见指标包括: -### 图表展示 +- 请求总量与成功率 +- 平均响应耗时 +- 活跃连接数量 +- 近期错误趋势 -- **请求趋势图**: 按时间显示请求量变化 -- **延迟分布图**: 响应时间分布 -- **Provider 使用占比**: 各 Provider 请求比例 +### 趋势视图 -## 请求统计 +你可以按时间查看: -### 按 Provider 统计 +- 调用量变化 +- 成功率变化 +- 延迟波动 -| Provider | 请求数 | 成功率 | 平均延迟 | -|----------|--------|--------|----------| -| Kiro Claude | 1,234 | 99.2% | 1.2s | -| Gemini CLI | 567 | 98.5% | 0.8s | -| Qwen | 890 | 99.0% | 1.0s | +这能帮助你判断问题是偶发,还是持续性异常。 -### 按模型统计 +## 日志排查 -查看每个模型的使用情况: +当某次生成失败时,优先看请求日志: -- 请求次数 -- Token 消耗 -- 平均响应时间 +1. 找到失败时间点 +2. 查看模型与请求参数 +3. 对照错误信息定位问题(超时、认证、限流等) -## Token 使用追踪 +## 对创作者最有用的用法 -### 使用量统计 +### 判断工作流是否健康 -| 指标 | 说明 | -|------|------| -| 输入 Token | 请求消息的 Token 数 | -| 输出 Token | 响应消息的 Token 数 | -| 总计 Token | 输入 + 输出 | +如果成功率持续下降,建议先减少并发任务,确认连接状态后再恢复批量生成。 -### 按时间段查看 +### 对比不同创作任务 -- 今日使用量 -- 本周使用量 -- 本月使用量 -- 自定义时间范围 +同样是生成任务,不同主题的耗时差异可能很大。通过趋势图可以更快选择稳定方案。 -## 请求日志 +### 复盘高峰时段 -### 日志列表 +高峰期(例如集中出图)出现波动时,可根据日志回看是否需要拆分任务批次。 -每条日志包含: +## 数据导出 -| 字段 | 说明 | -|------|------| -| 时间 | 请求时间戳 | -| 模型 | 请求的模型名称 | -| Provider | 实际使用的 Provider | -| 状态 | 成功/失败 | -| 延迟 | 响应时间 | -| Token | Token 使用量 | - -### 日志过滤 - -支持按以下条件过滤: - -- 时间范围 -- Provider -- 模型 -- 状态(成功/失败) - -### 日志详情 - -点击日志条目查看详细信息: - -- 完整请求内容 -- 完整响应内容 -- 错误信息(如有) -- 请求头信息 - -## 导出数据 - -支持导出统计数据: - -- CSV 格式 -- JSON 格式 -- 自定义时间范围 +如果你需要做团队复盘,可导出统计数据用于周报或复盘记录。 diff --git a/docs/content/02.user-guide/3.credential-pool.md b/docs/content/02.user-guide/3.credential-pool.md index 45f758d9a..c7e0a5075 100644 --- a/docs/content/02.user-guide/3.credential-pool.md +++ b/docs/content/02.user-guide/3.credential-pool.md @@ -1,130 +1,55 @@ --- -title: 凭证池 -description: 管理多个 AI 服务凭证 +title: 模型连接与账号 +description: 管理模型连接方式与多账号状态(进阶) navigation: icon: i-heroicons-key --- -# 凭证池 +# 模型连接与账号 -凭证池用于管理多个 AI 服务凭证,支持负载均衡和故障转移。 +::alert{type="info"} +这是进阶页。普通创作者可直接使用默认连接能力,按需再回来配置。 +:: -## 池管理界面 +该页面用于管理模型连接与账号状态,适合以下场景: -### 凭证列表 +- 你有多个账号需要统一管理 +- 你需要手动添加 API Key +- 你希望在连接异常时快速排查 -显示所有已添加的凭证: - -| 字段 | 说明 | -|------|------| -| 名称 | 凭证标识名称 | -| Provider | 凭证类型 | -| 状态 | 有效/过期/错误 | -| 优先级 | 负载均衡优先级 | -| 操作 | 编辑/删除/测试 | - -### 状态指示 - -- 🟢 **有效**: 凭证可正常使用 -- 🟡 **即将过期**: Token 即将过期,需要刷新 -- 🔴 **已过期**: Token 已过期 -- ⚪ **未验证**: 尚未验证凭证有效性 - -## 添加凭证 +## 常见连接方式 ### 自动检测 -ProxyCast 会自动检测以下位置的凭证: +应用会尝试检测本地常见凭证文件,检测成功后可直接使用。 -``` -~/.kiro/credentials.json # Kiro Claude -~/.config/gemini-cli/oauth_creds.json # Gemini CLI -~/.config/qwen/credentials.json # Qwen -``` +### 手动添加 -点击 **刷新凭证** 重新扫描。 +如果自动检测失败,可手动添加: -### 从文件加载 +1. 选择连接类型 +2. 填写必要凭证信息 +3. 保存后执行连接测试 -1. 点击 **添加凭证** -2. 选择 **从文件加载** -3. 选择凭证文件 -4. 确认 Provider 类型 +## 账号状态说明 -### 手动输入 +- 可用:可正常调用 +- 即将过期:建议尽快刷新 +- 已失效:需重新登录或更新凭证 +- 未验证:建议先执行测试 -1. 点击 **添加凭证** -2. 选择 **手动输入** -3. 选择 Provider 类型 -4. 填写凭证信息: +## 多账号使用建议 -**OAuth 类型 (Kiro/Gemini/Qwen):** -- Access Token -- Refresh Token -- 过期时间 +### 日常创作 -**API Key 类型 (OpenAI/Claude Custom):** -- API Key -- Base URL(可选) +保留 1 到 2 个稳定账号即可,优先保证可用性。 -## 负载均衡配置 +### 高强度创作 -### 策略选择 +如果你需要长时间连续生成,可配置多个账号做冗余,降低单点失败影响。 -| 策略 | 说明 | -|------|------| -| 轮询 (Round Robin) | 依次使用每个凭证 | -| 优先级 (Priority) | 按优先级顺序使用 | -| 随机 (Random) | 随机选择凭证 | -| 最少使用 (Least Used) | 优先使用请求数最少的凭证 | +## 安全建议 -### 优先级设置 - -为每个凭证设置优先级(1-100): - -- 数值越小优先级越高 -- 相同优先级按策略选择 -- 优先级为 0 表示禁用 - -### 健康检查 - -启用健康检查后: - -- 定期验证凭证有效性 -- 自动跳过失效凭证 -- 凭证恢复后自动重新启用 - -配置选项: - -| 选项 | 默认值 | 说明 | -|------|--------|------| -| 检查间隔 | 60s | 健康检查频率 | -| 失败阈值 | 3 | 连续失败次数后标记为不健康 | -| 恢复阈值 | 1 | 成功次数后恢复健康状态 | - -## 凭证操作 - -### 测试凭证 - -点击 **测试** 按钮验证凭证: - -1. 发送测试请求 -2. 显示测试结果 -3. 更新凭证状态 - -### 刷新 Token - -对于 OAuth 凭证: - -- 自动刷新:Token 过期前自动刷新 -- 手动刷新:点击 **刷新** 按钮 - -### 删除凭证 - -1. 点击 **删除** 按钮 -2. 确认删除操作 -3. 凭证从池中移除 - -::alert{type="warning"} -删除凭证不会删除本地凭证文件,只是从 ProxyCast 中移除。 -:: +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 index eae3c1cc7..d322dce46 100644 --- a/docs/content/02.user-guide/4.configuration-example.md +++ b/docs/content/02.user-guide/4.configuration-example.md @@ -1,342 +1,79 @@ --- -title: 完整配置示例 -description: ProxyCast 完整 YAML 配置示例 +title: 进阶配置示例 +description: 按创作场景选择配置思路(示例) navigation: icon: i-heroicons-document-text --- -# 完整配置示例 +# 进阶配置示例 -本文档提供 ProxyCast 的完整 YAML 配置示例,包含所有新增功能。 +::alert{type="info"} +本页示例用于说明配置思路,不要求你逐字段照抄。具体字段以应用设置界面为准。 +:: -## 基础配置 +## 示例 1:个人创作者(推荐起步) + +目标:少配置、快开始。 ```yaml -# 服务器配置 -server: +profile: "solo-creator" +navigation: + enabled: + - agent + - projects + - resources + - image-gen +themes: + enabled: + - social-media + - video + - novel +``` + +适用:自媒体、短视频、小说日更。 + +## 示例 2:团队协作 + +目标:统一入口和主题,降低沟通成本。 + +```yaml +profile: "team-content" +navigation: + enabled: + - agent + - projects + - resources + - tools +themes: + enabled: + - social-media + - poster + - document +resource: + naming: "project-date-version" +``` + +适用:品牌运营、活动策划、小团队协作。 + +## 示例 3:进阶接入 + +目标:在保留创作工作台的同时开放 API 给外部工具。 + +```yaml +profile: "creator-plus-api" +api_server: + enabled: true host: "127.0.0.1" port: 8999 - api_key: "your-api-key" - - # TLS/HTTPS 配置 - tls: - enable: false - cert_path: "/path/to/cert.pem" - key_path: "/path/to/key.pem" - -# 注意:当前版本暂不支持 TLS。启用后服务将无法启动,请使用反向代理做 TLS 终止。 - -# 全局代理 URL(支持 socks5/http/https) -proxy_url: "socks5://127.0.0.1:1080" - -# 认证目录(存储 OAuth Token 文件) -auth_dir: "~/.proxycast/auth" -``` - -## 远程管理配置 - -```yaml -# 远程管理 API 配置 -remote_management: - # 是否允许远程访问(非 localhost) - allow_remote: false - # 管理 API 密钥(为空时禁用管理 API) - secret_key: "your-secret-key" - # 是否禁用控制面板 - disable_control_panel: false -``` - -## 配额超限配置 - -```yaml -# 配额超限自动切换策略 -quota_exceeded: - # 是否自动切换到下一个凭证 - switch_project: true - # 是否尝试使用预览模型 - switch_preview_model: true - # 冷却时间(秒) - cooldown_seconds: 300 -``` - -## Amp CLI 集成配置 - -```yaml -# Amp CLI 配置 -ampcode: - # 上游 URL - upstream_url: "https://ampcode.com" - # 是否限制管理端点只能从 localhost 访问 - restrict_management_to_localhost: false - # 模型映射列表 - 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" -``` - -## 凭证池配置 - -### OAuth Provider - -```yaml -credential_pool: - # Kiro OAuth 凭证 - kiro: - - id: "kiro-main" - token_file: "kiro/main-token.json" - disabled: false - proxy_url: "socks5://proxy1:1080" # 可选:单独代理 - - id: "kiro-backup" - token_file: "kiro/backup-token.json" - disabled: false - - # Gemini OAuth 凭证 - gemini: - - id: "gemini-main" - token_file: "gemini/oauth_creds.json" - disabled: false - - # Qwen OAuth 凭证 - qwen: - - id: "qwen-main" - token_file: "qwen/oauth_creds.json" - disabled: false - - # Codex OAuth 凭证 - codex: - - id: "codex-main" - token_file: "codex/oauth.json" - proxy_url: "http://proxy2:8080" -``` - -### iFlow Provider - -```yaml -credential_pool: - # iFlow 凭证(支持 OAuth 和 Cookie) - iflow: - # OAuth 模式 - - id: "iflow-oauth" - token_file: "iflow/oauth.json" - auth_type: "oauth" - disabled: false - # Cookie 模式 - - id: "iflow-cookie" - auth_type: "cookie" - cookies: "session_id=abc123; auth_token=xyz789" - disabled: false -``` - -### API Key Provider - -```yaml -credential_pool: - # OpenAI API Key - openai: - - id: "openai-main" - api_key: "sk-xxx..." - base_url: "https://api.openai.com/v1" - disabled: false - proxy_url: "http://proxy:8080" - - # Claude API Key - claude: - - id: "claude-main" - api_key: "sk-ant-xxx..." - base_url: "https://api.anthropic.com" - disabled: false -``` - -### Gemini API Key 多账号 - -```yaml -credential_pool: - # Gemini API Key 多账号负载均衡 - 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 -``` - -### Vertex AI Provider - -```yaml -credential_pool: - # Vertex AI 凭证 - 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 -``` - -## 路由配置 - -```yaml -# 路由配置 + auth: "api-key" routing: - # 默认 Provider - default_provider: "kiro" - - # 路由规则 - rules: - - pattern: "claude-*" - provider: "kiro" - priority: 1 - - pattern: "gemini-*" - provider: "gemini" - priority: 2 - - pattern: "gpt-*" - provider: "openai" - priority: 3 - - # 模型别名 - model_aliases: - "claude-latest": "claude-sonnet-4-5-20250514" - "gemini-latest": "gemini-2.5-pro" - - # 排除列表 - exclusions: - kiro: - - "claude-3-opus-*" - gemini: - - "gemini-1.0-*" + fallback: true ``` -## 重试配置 +适用:有脚本联动、自动化流程需求的用户。 -```yaml -# 重试配置 -retry: - max_retries: 3 - base_delay_ms: 1000 - max_delay_ms: 30000 - auto_switch_provider: true -``` +## 调整顺序建议 -## 日志配置 - -```yaml -# 日志配置 -logging: - enabled: true - level: "info" - retention_days: 7 - include_request_body: false -``` - -## 参数注入配置 - -```yaml -# 参数注入配置 -injection: - enabled: true - rules: - - id: "thinking-budget" - pattern: "gemini-2.5-*" - parameters: - generationConfig: - thinkingConfig: - thinkingBudget: 32768 - mode: "default" # default: 仅在参数缺失时设置 - priority: 1 - enabled: true - - id: "reasoning-effort" - pattern: "gpt-*" - parameters: - reasoning: - effort: "high" - mode: "override" # override: 总是覆盖 - priority: 2 - enabled: true -``` - -## 完整配置示例 - -以下是一个完整的配置文件示例: - -```yaml -# ProxyCast 完整配置示例 -server: - host: "127.0.0.1" - port: 8999 - api_key: "your-api-key" - tls: - enable: false - cert_path: "" - key_path: "" - -proxy_url: "" -auth_dir: "~/.proxycast/auth" - -remote_management: - allow_remote: false - secret_key: "" - disable_control_panel: false - -quota_exceeded: - switch_project: true - switch_preview_model: true - cooldown_seconds: 300 - -ampcode: - upstream_url: "" - restrict_management_to_localhost: false - model_mappings: [] - -credential_pool: - kiro: - - id: "kiro-main" - token_file: "kiro/main-token.json" - disabled: false - gemini: [] - qwen: [] - openai: [] - claude: [] - gemini_api_keys: [] - vertex_api_keys: [] - codex: [] - iflow: [] - -routing: - default_provider: "kiro" - rules: [] - model_aliases: {} - exclusions: {} - -retry: - max_retries: 3 - base_delay_ms: 1000 - max_delay_ms: 30000 - auto_switch_provider: true - -logging: - enabled: true - level: "info" - retention_days: 7 - include_request_body: false - -injection: - enabled: false - rules: [] -``` +1. 先确认导航与主题 +2. 再确认连接与稳定性 +3. 最后再做 API 与自动化扩展 diff --git a/docs/content/02.user-guide/4.smart-routing.md b/docs/content/02.user-guide/4.smart-routing.md index 0ae3d32be..0b4dd7233 100644 --- a/docs/content/02.user-guide/4.smart-routing.md +++ b/docs/content/02.user-guide/4.smart-routing.md @@ -1,142 +1,66 @@ --- -title: 智能路由 -description: 配置请求路由规则 +title: 模型分发规则 +description: 按任务类型将请求分发到不同模型(进阶) navigation: icon: i-heroicons-arrows-right-left --- -# 智能路由 +# 模型分发规则 -智能路由允许你根据模型名称将请求定向到特定的 Provider。 +::alert{type="info"} +这是进阶能力。只有在“多模型并行使用”时才需要配置。 +:: -## 模型映射 +分发规则用于把不同任务自动交给更合适的模型。 -### 映射规则 +## 什么时候需要它 -将请求中的模型名称映射到实际的 Provider 和模型: +- 文本创作和图片任务使用不同模型 +- 同一主题需要“快速草稿 + 高质量润色”两种路径 +- 你希望把高成本任务限制在特定模型上 -| 请求模型 | 目标 Provider | 目标模型 | -|----------|---------------|----------| -| `gpt-4` | Kiro Claude | `claude-sonnet-4-20250514` | -| `gpt-3.5-turbo` | Gemini CLI | `gemini-2.0-flash` | -| `claude-*` | Kiro Claude | 保持原样 | +## 常见策略 -### 配置映射 +### 按任务类型分发 -1. 进入 **智能路由** 页面 -2. 点击 **添加规则** -3. 配置映射: +- 长文写作走高质量模型 +- 快速问答走低延迟模型 +- 图片任务走图片专用模型 -```yaml -# 示例配置 -routes: - - pattern: "gpt-4*" - provider: kiro-claude - model: claude-sonnet-4-20250514 - - pattern: "gpt-3.5*" - provider: gemini-cli - model: gemini-2.0-flash -``` +### 按阶段分发 -## 规则语法 +- 初稿阶段:速度优先 +- 定稿阶段:质量优先 -### 模式匹配 +### 按兜底分发 -| 模式 | 说明 | 示例 | -|------|------|------| -| `exact` | 精确匹配 | `gpt-4` 只匹配 `gpt-4` | -| `prefix*` | 前缀匹配 | `gpt-4*` 匹配 `gpt-4`, `gpt-4-turbo` | -| `*suffix` | 后缀匹配 | `*-turbo` 匹配 `gpt-4-turbo` | -| `*contains*` | 包含匹配 | `*claude*` 匹配任何包含 claude 的模型 | +主模型异常时,自动回退到备用模型。 -### 规则字段 - -| 字段 | 必填 | 说明 | -|------|------|------| -| pattern | ✅ | 模型名称匹配模式 | -| provider | ✅ | 目标 Provider | -| model | ❌ | 目标模型(不填则保持原样) | -| priority | ❌ | 规则优先级(默认 100) | -| enabled | ❌ | 是否启用(默认 true) | - -## 优先级排序 - -### 规则优先级 - -- 数值越小优先级越高 -- 相同优先级按添加顺序 -- 第一个匹配的规则生效 - -### 示例 +## 示例(示意) ```yaml routes: - # 优先级 10:精确匹配优先 - - pattern: "gpt-4-turbo" - provider: openai-custom + - pattern: "video-script-*" + provider: "primary" + model: "high-quality-model" priority: 10 - - # 优先级 50:前缀匹配 - - pattern: "gpt-4*" - provider: kiro-claude - priority: 50 - - # 优先级 100:默认规则 + - pattern: "quick-*" + provider: "fast-lane" + model: "fast-model" + priority: 20 - pattern: "*" - provider: gemini-cli + provider: "fallback" priority: 100 ``` -## 默认回退 +## 配置建议 -### 无规则匹配时 +1. 先只配 2 到 3 条关键规则 +2. 给兜底规则留最后优先级 +3. 每次改完都做一次路由测试 -当请求的模型不匹配任何规则时: +## 常见误区 -1. 使用默认 Provider -2. 保持原始模型名称 -3. 如果默认 Provider 不支持该模型,返回错误 - -### 配置默认 Provider - -```yaml -default: - provider: kiro-claude - fallback: true # 启用回退 -``` - -## Provider 选择 - -### 可用 Provider - -| Provider | 标识 | 说明 | -|----------|------|------| -| Kiro Claude | `kiro-claude` | Kiro IDE 的 Claude | -| Gemini CLI | `gemini-cli` | Google Gemini | -| Qwen | `qwen` | 通义千问 | -| OpenAI Custom | `openai-custom` | 自定义 OpenAI | -| Claude Custom | `claude-custom` | 自定义 Claude | - -### 多 Provider 负载均衡 - -同一规则可以指定多个 Provider: - -```yaml -routes: - - pattern: "gpt-4*" - providers: - - kiro-claude - - claude-custom - strategy: round-robin -``` - -## 测试路由 - -### 路由测试工具 - -1. 输入模型名称 -2. 点击 **测试路由** -3. 查看匹配结果: - - 匹配的规则 - - 目标 Provider - - 目标模型 +- 规则过多导致难以维护 +- 没有兜底规则,异常时直接失败 +- 频繁改规则但不做回归测试 diff --git a/docs/content/02.user-guide/5.resilience.md b/docs/content/02.user-guide/5.resilience.md index d264780b7..26f207841 100644 --- a/docs/content/02.user-guide/5.resilience.md +++ b/docs/content/02.user-guide/5.resilience.md @@ -1,145 +1,68 @@ --- -title: 容错配置 -description: 重试、超时和故障转移设置 +title: 稳定性与容错 +description: 在高强度创作下保持调用稳定(进阶) navigation: icon: i-heroicons-shield-check --- -# 容错配置 +# 稳定性与容错 -容错配置帮助你的应用优雅地处理 API 故障,确保服务稳定性。 +::alert{type="info"} +这是进阶能力。只有在你频繁遇到超时、失败、波动时才需要细调。 +:: -## 重试机制 +稳定性配置的核心目标是: -### 重试配置 +- 少失败 +- 失败后可恢复 +- 出错时可定位 -| 选项 | 默认值 | 说明 | -|------|--------|------| -| 最大重试次数 | 3 | 失败后重试的最大次数 | -| 初始延迟 | 1s | 首次重试前的等待时间 | -| 最大延迟 | 30s | 重试延迟的上限 | -| 退避倍数 | 2 | 每次重试延迟的增长倍数 | +## 三个关键参数 -### 退避策略 +### 重试 -``` -第1次重试: 1s -第2次重试: 2s -第3次重试: 4s -... -``` +用于处理偶发失败。 -### 可重试错误 +建议: -以下错误会触发重试: +- 最大重试次数:2 到 3 次 +- 首次重试延迟:1 秒左右 +- 使用递增退避,避免短时间反复打满请求 -- 网络超时 -- 连接失败 -- 5xx 服务器错误 -- 429 速率限制 +### 超时 -不重试的错误: +用于避免单次请求长时间卡住。 -- 4xx 客户端错误(除 429) -- 认证失败 -- 无效请求 +建议: -## 超时设置 +- 普通文本任务:较短超时 +- 长文或复杂任务:适当放宽 +- 图片任务:通常需要更长超时 -### 超时配置 +### 故障回退 -| 选项 | 默认值 | 说明 | -|------|--------|------| -| 连接超时 | 10s | 建立连接的超时时间 | -| 请求超时 | 120s | 整个请求的超时时间 | -| 流式超时 | 300s | 流式响应的超时时间 | +主连接失败后自动走备用连接,减少中断。 -### 按 Provider 配置 +## 推荐调参顺序 -可以为不同 Provider 设置不同的超时: +1. 先调超时 +2. 再调重试 +3. 最后配置回退策略 -```yaml -timeouts: - default: - connect: 10s - request: 120s - kiro-claude: - request: 180s # Claude 响应较慢 - gemini-cli: - request: 60s # Gemini 响应较快 -``` +## 诊断建议 -## 故障转移 +### 连续失败 -### 自动故障转移 +优先检查: -当主 Provider 失败时,自动切换到备用 Provider: +1. 连接状态是否可用 +2. 当前模型是否可调用 +3. 是否触发限流 -1. 主 Provider 请求失败 -2. 检查是否有可用的备用 Provider -3. 使用备用 Provider 重试请求 -4. 记录故障转移事件 +### 偶发失败 -### 配置故障转移 +通常先提高重试效果更明显。 -```yaml -failover: - enabled: true - providers: - - kiro-claude # 主 Provider - - claude-custom # 备用 Provider 1 - - gemini-cli # 备用 Provider 2 - maxAttempts: 3 # 最大尝试 Provider 数 -``` +### 高峰波动 -### 故障转移条件 - -| 条件 | 说明 | -|------|------| -| 连接失败 | 无法连接到 Provider | -| 认证失败 | Token 过期或无效 | -| 速率限制 | 达到 Provider 限制 | -| 服务不可用 | Provider 返回 503 | - -## 熔断器 - -### 熔断器状态 - -| 状态 | 说明 | -|------|------| -| 关闭 | 正常工作,请求通过 | -| 打开 | 熔断激活,请求直接失败 | -| 半开 | 尝试恢复,允许部分请求 | - -### 熔断配置 - -| 选项 | 默认值 | 说明 | -|------|--------|------| -| 失败阈值 | 5 | 触发熔断的连续失败次数 | -| 恢复时间 | 30s | 熔断后尝试恢复的等待时间 | -| 半开请求数 | 3 | 半开状态允许的测试请求数 | - -### 熔断流程 - -``` -正常 → 连续失败5次 → 熔断打开 -熔断打开 → 等待30s → 半开状态 -半开状态 → 3次成功 → 恢复正常 -半开状态 → 1次失败 → 重新熔断 -``` - -## 监控告警 - -### 告警条件 - -- 错误率超过阈值 -- 延迟超过阈值 -- 熔断器打开 -- 所有 Provider 不可用 - -### 告警通知 - -当前支持: - -- 应用内通知 -- 系统通知(macOS/Windows) +建议拆分任务批次,避免同一时刻大量并发。 diff --git a/docs/content/02.user-guide/6.config-management.md b/docs/content/02.user-guide/6.config-management.md index ad245078e..9cc38a7cf 100644 --- a/docs/content/02.user-guide/6.config-management.md +++ b/docs/content/02.user-guide/6.config-management.md @@ -1,173 +1,63 @@ --- -title: 配置管理 -description: 导出和导入配置 +title: 配置管理与迁移 +description: 导出、导入、备份与跨设备迁移配置 navigation: icon: i-heroicons-document-duplicate --- -# 配置管理 +# 配置管理与迁移 -配置管理功能允许你导出、导入和分享 ProxyCast 配置。 +配置管理适合两类人: -## YAML 导出 +- 想把当前工作台快速迁移到另一台设备 +- 团队内需要统一一套基础配置 -### 导出内容 +## 导出配置 -导出的 YAML 文件包含: +你可以将当前设置导出为配置文件,常用于备份和迁移。 -- Provider 配置 -- 路由规则 -- 容错设置 -- API Server 配置 -- 通用设置 +常见导出内容: -### 导出步骤 - -1. 进入 **设置** > **配置管理** -2. 点击 **导出配置** -3. 选择保存位置 -4. 配置保存为 `.yaml` 文件 - -### 导出格式 - -```yaml -version: "1.0" -providers: - - name: kiro-claude - type: kiro - enabled: true - priority: 1 - - name: gemini-cli - type: gemini - enabled: true - priority: 2 - -routes: - - pattern: "gpt-4*" - provider: kiro-claude - model: claude-sonnet-4-20250514 - -resilience: - retry: - maxAttempts: 3 - initialDelay: 1s - timeout: - request: 120s - -server: - host: "127.0.0.1" - port: 8999 -``` - -### 敏感信息处理 +- 主题与导航偏好 +- 部分连接与路由策略 +- 稳定性相关参数 ::alert{type="warning"} -导出的配置**不包含**凭证信息(Token、API Key)。导入后需要重新配置凭证。 +导出文件通常不包含敏感凭证信息。导入后需重新检查连接状态。 :: ## 导入配置 -### 导入步骤 +1. 在设置页选择导入 +2. 预览配置差异 +3. 选择覆盖或合并策略 +4. 导入后做一次连接与功能自检 -1. 进入 **设置** > **配置管理** -2. 点击 **导入配置** -3. 选择 `.yaml` 配置文件 -4. 预览导入内容 -5. 确认导入 +## 备份建议 -### 冲突解决 +### 个人用户 -当导入的配置与现有配置冲突时: +至少保留最近 2 到 3 份配置备份。 -| 选项 | 说明 | -|------|------| -| 覆盖 | 用导入的配置替换现有配置 | -| 跳过 | 保留现有配置,跳过冲突项 | -| 合并 | 合并两个配置(仅适用于列表类型) | +### 团队用户 -### 验证导入 +建议按版本管理配置文件,例如: -导入前会验证: +- `team-config-v1.yaml` +- `team-config-v1.1.yaml` -- YAML 语法正确性 -- 配置版本兼容性 -- 必填字段完整性 +## 跨设备迁移清单 -## .env 格式导出 +1. 导出配置文件 +2. 在新设备导入配置 +3. 重新校验连接状态 +4. 检查主题、导航、资源路径是否符合预期 +5. 进行一次完整创作演练 -### 用途 +## 什么时候需要重置 -导出为 `.env` 格式,方便在其他工具中使用: +当你长期调参后“越调越乱”,最稳妥的方式是: -- 脚本调用 -- Docker 环境 -- CI/CD 配置 - -### 导出内容 - -```bash -# ProxyCast API Configuration -PROXYCAST_API_BASE=http://127.0.0.1:8999/v1 -PROXYCAST_API_KEY=your-api-key - -# OpenAI Compatible -OPENAI_API_BASE=http://127.0.0.1:8999/v1 -OPENAI_API_KEY=your-api-key - -# Claude Compatible -ANTHROPIC_API_BASE=http://127.0.0.1:8999 -ANTHROPIC_API_KEY=your-api-key -``` - -### 导出步骤 - -1. 进入 **设置** > **配置管理** -2. 点击 **导出 .env** -3. 选择保存位置 - -## 配置备份 - -### 自动备份 - -ProxyCast 会自动备份配置: - -- 每次修改后自动保存 -- 保留最近 10 个版本 -- 备份位置:`~/.proxycast/backups/` - -### 恢复备份 - -1. 进入 **设置** > **配置管理** -2. 点击 **备份历史** -3. 选择要恢复的版本 -4. 点击 **恢复** - -## 完整备份与恢复(生产建议) - -仅导出配置无法覆盖数据库与凭证文件。生产环境建议定期备份以下路径: - -- 配置文件:macOS `~/Library/Application Support/proxycast/config.yaml`;Linux `~/.config/proxycast/config.yaml`;Windows `%APPDATA%\\proxycast\\config.yaml` -- 凭证副本目录:macOS `~/Library/Application Support/proxycast/credentials/`;Linux `~/.local/share/proxycast/credentials/`;Windows `%APPDATA%\\proxycast\\credentials\\` -- 数据库与日志:`~/.proxycast/`(含 `proxycast.db`、`logs/`、`request_logs/`、`auth/`) - -```bash -# 示例:备份数据库与日志目录 -cp -a ~/.proxycast ~/.proxycast.backup-$(date +%Y%m%d%H%M%S) -``` - -恢复时将备份内容替换回原路径,并确保应用已退出。 - -## 旧版本迁移说明 - -如果检测到旧版 `~/.proxycast/config.json`,当前版本会阻止启动并提示手动迁移。请先导出旧配置或重新导入 YAML 配置,再启动应用。 - -## 配置同步 - -### 跨设备同步 - -通过导出/导入实现跨设备配置同步: - -1. 在设备 A 导出配置 -2. 将配置文件传输到设备 B -3. 在设备 B 导入配置 -4. 重新配置凭证 +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 index 94c13e56f..5cd2b6a7d 100644 --- a/docs/content/02.user-guide/7.config-switch.md +++ b/docs/content/02.user-guide/7.config-switch.md @@ -1,152 +1,50 @@ --- -title: 配置切换 -description: 快速切换 AI 客户端配置 +title: 工作模式切换 +description: 在不同创作场景间快速切换配置 navigation: icon: i-heroicons-arrows-up-down --- -# 配置切换 +# 工作模式切换 -配置切换功能让你可以一键在不同的 AI 客户端配置之间切换。 +如果你在不同场景下有明显不同的工作方式,可以使用配置档案快速切换。 -## 功能目的 +## 典型模式 -当你需要在不同场景使用不同的 AI 服务时: +### 日更模式 -- 开发时使用 Kiro Claude -- 测试时使用 Gemini CLI -- 生产时使用自定义 OpenAI +- 目标:快速产出 +- 适合:社媒短内容、灵感快写 +- 特点:速度优先、流程简化 -配置切换让你无需手动修改配置,一键完成切换。 +### 深度创作模式 -## 预设配置 +- 目标:质量优先 +- 适合:长文、小说章节、方案定稿 +- 特点:更强调结构和多轮迭代 -### 内置配置档案 +### 出图冲刺模式 -| 档案 | 说明 | -|------|------| -| Claude Code | 适用于 Claude Code 客户端 | -| Codex | 适用于 OpenAI Codex | -| Gemini CLI | 适用于 Gemini CLI | +- 目标:集中生成并沉淀图片素材 +- 适合:活动海报、视觉素材周更 +- 特点:图片相关入口前置、资源回流优先 -### 配置内容 +## 建议的档案字段 -每个档案包含: +每个档案建议包含: -- 默认 Provider -- 路由规则 -- 模型映射 -- API 端点配置 +- 启用的导航模块 +- 启用的创作主题 +- 关键连接与稳定性偏好 -## 创建配置档案 - -### 新建档案 - -1. 进入 **配置切换** 页面 -2. 点击 **新建档案** -3. 输入档案名称 -4. 配置以下内容: - -```yaml -name: "我的配置" -description: "自定义配置档案" -provider: kiro-claude -routes: - - pattern: "*" - provider: kiro-claude -settings: - timeout: 120s - retry: 3 -``` - -### 从当前配置创建 - -1. 配置好当前设置 -2. 点击 **保存为档案** -3. 输入档案名称 -4. 档案保存成功 - -## 切换配置 - -### 一键切换 - -1. 进入 **配置切换** 页面 -2. 查看可用档案列表 -3. 点击目标档案的 **应用** 按钮 -4. 配置立即生效 - -### 快捷切换 - -使用标签页快速切换: - -- **Claude Code** 标签 -- **Codex** 标签 -- **Gemini CLI** 标签 - -点击标签即可切换到对应配置。 - -## 设置活动配置 - -### 标记当前配置 - -当前使用的配置会显示 **当前使用中** 标记。 - -### 切换活动配置 +## 切换步骤 1. 选择目标档案 -2. 点击 **设为活动** -3. 该档案成为当前活动配置 +2. 应用后检查核心入口是否符合预期 +3. 用一个小任务做快速验证 -## 档案管理 +## 使用建议 -### 编辑档案 - -1. 点击档案的 **编辑** 按钮 -2. 修改配置内容 -3. 点击 **保存** - -### 删除档案 - -1. 点击档案的 **删除** 按钮 -2. 确认删除操作 - -::alert{type="warning"} -内置档案无法删除,但可以修改。 -:: - -### 导出档案 - -单独导出某个档案: - -1. 点击档案的 **导出** 按钮 -2. 选择保存位置 -3. 档案保存为 `.yaml` 文件 - -### 导入档案 - -1. 点击 **导入档案** -2. 选择 `.yaml` 文件 -3. 档案添加到列表 - -## 使用场景 - -### 场景 1: 开发/测试切换 - -``` -开发环境: 使用 Kiro Claude(免费额度) -测试环境: 使用 Gemini CLI(快速响应) -``` - -### 场景 2: 模型切换 - -``` -代码生成: Claude Sonnet(高质量) -快速问答: Gemini Flash(低延迟) -``` - -### 场景 3: 团队协作 - -``` -团队成员 A: 使用个人 Kiro 账户 -团队成员 B: 使用共享 API Key -``` +1. 档案数量控制在 3 个以内 +2. 一个档案只服务一个明确场景 +3. 变更档案后记录用途,避免后续混乱 diff --git a/docs/content/02.user-guide/8.api-server.md b/docs/content/02.user-guide/8.api-server.md index fc94ea0dd..b8d545f06 100644 --- a/docs/content/02.user-guide/8.api-server.md +++ b/docs/content/02.user-guide/8.api-server.md @@ -1,167 +1,52 @@ --- -title: API Server -description: 配置和管理 API 服务 +title: 本地 API 接入 +description: 将 ProxyCast 能力暴露给外部工具(进阶) navigation: icon: i-heroicons-server --- -# API Server +# 本地 API 接入 -API Server 是 ProxyCast 的核心组件,提供 OpenAI/Claude 兼容的 API 端点。 - -## 服务器配置 - -### 基本配置 - -| 选项 | 默认值 | 说明 | -|------|--------|------| -| 主机地址 | `127.0.0.1` | 监听地址 | -| 端口 | `8999` | 监听端口 | -| API Key | 自动生成 | 访问密钥 | - -### 配置步骤 - -1. 进入 **设置** > **API Server** -2. 修改配置选项 -3. 点击 **保存** -4. 重启服务生效 - -### 监听地址 - -| 地址 | 说明 | -|------|------| -| `127.0.0.1` | 仅本机访问 | -| `localhost` | 仅本机访问 | - -::alert{type="warning"} -当前版本仅支持本地监听(127.0.0.1/localhost/::1),不支持对外开放。 +::alert{type="info"} +这是进阶能力。普通创作者可以不配置,直接在应用内完成创作。 :: -## API 端点 +当你希望把 ProxyCast 接入脚本、自动化工具或第三方客户端时,可启用本地 API。 -### OpenAI 兼容端点 +## 核心说明 -| 端点 | 方法 | 说明 | -|------|------|------| -| `/v1/chat/completions` | POST | 聊天补全 | -| `/v1/models` | GET | 模型列表 | -| `/v1/embeddings` | POST | 文本嵌入 | +- 服务默认在本地地址运行 +- 通过 API Key 控制访问 +- 支持常见兼容接口形态 -### Claude 兼容端点 +## 快速配置 -| 端点 | 方法 | 说明 | -|------|------|------| -| `/v1/messages` | POST | 消息 API | -| `/v1/messages/count_tokens` | POST | Token 计数 | - -## 请求日志 - -### 日志查看 - -1. 进入 **监控中心** -2. 查看 **请求日志** 标签 -3. 实时显示所有请求 - -### 日志内容 - -每条日志包含: - -- 时间戳 -- 请求方法和路径 -- 请求模型 -- 响应状态 -- 响应时间 -- Token 使用量 - -### 日志过滤 - -支持按以下条件过滤: - -- 时间范围 -- 状态码 -- 模型名称 -- Provider - -## 访问控制 - -### API Key 认证 - -启用 API Key 认证: - -1. 进入 **设置** > **API Server** -2. 开启 **启用认证** +1. 进入设置中的 API Server +2. 开启服务并确认端口 3. 设置或生成 API Key -4. 保存配置 +4. 使用一条测试请求验证连通性 -### 请求认证 +## 最小测试示例 -请求时需要携带 API Key: - -**OpenAI 格式:** ```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": [...]}' + -d '{"model":"your-model","messages":[{"role":"user","content":"你好"}]}' ``` -**Claude 格式:** -```bash -curl http://127.0.0.1:8999/v1/messages \ - -H "x-api-key: your-api-key" \ - -H "anthropic-version: 2023-06-01" \ - -H "Content-Type: application/json" \ - -d '{"model": "claude-3-sonnet", "messages": [...]}' -``` +## 安全建议 -### 多 API Key +1. 只在本机环境使用 +2. 不要把 API Key 提交到代码仓库 +3. 定期更换密钥并清理无效连接 -支持配置多个 API Key: +## 常见问题 -```yaml -auth: - keys: - - name: "开发环境" - key: "dev-key-xxx" - - name: "生产环境" - key: "prod-key-xxx" -``` +### 启动后无法访问 -## CORS 配置 +先确认端口未被占用,再检查本地防火墙策略。 -### 跨域设置 +### 请求总是 401 -| 选项 | 默认值 | 说明 | -|------|--------|------| -| 允许来源 | `*` | 允许的请求来源 | -| 允许方法 | `GET,POST,OPTIONS` | 允许的 HTTP 方法 | -| 允许头部 | `*` | 允许的请求头 | - -### 配置示例 - -```yaml -cors: - origins: - - "http://localhost:3000" - - "https://myapp.com" - methods: - - GET - - POST - headers: - - Authorization - - Content-Type -``` - -## 服务管理 - -### 启动/停止 - -- **启动**: 点击仪表盘的 **启动服务** 按钮 -- **停止**: 点击 **停止服务** 按钮 -- **重启**: 点击 **重启服务** 按钮 - -### 开机自启 - -1. 进入 **设置** > **通用** -2. 开启 **开机自动启动** -3. 开启 **启动时自动运行服务** +通常是 API Key 填写错误或请求头格式不正确。 diff --git a/docs/content/02.user-guide/9.mcp.md b/docs/content/02.user-guide/9.mcp.md index d6f234639..a4c78550a 100644 --- a/docs/content/02.user-guide/9.mcp.md +++ b/docs/content/02.user-guide/9.mcp.md @@ -1,185 +1,53 @@ --- -title: MCP 服务器 -description: Model Context Protocol 集成 +title: MCP 工具扩展 +description: 让 AI 调用外部工具与资源(进阶) navigation: icon: i-heroicons-puzzle-piece --- -# MCP 服务器 +# MCP 工具扩展 -MCP (Model Context Protocol) 是一种标准协议,允许 AI 模型与外部工具和数据源交互。 +MCP 可以让 AI 不只“回答问题”,还可以调用外部工具完成动作。 -## MCP 概念 +::alert{type="info"} +这是进阶能力。建议先熟悉基础创作流程,再接入 MCP。 +:: -### 什么是 MCP +## 适合的场景 -MCP 定义了 AI 模型与外部系统交互的标准方式: +- 让 AI 读取指定目录素材 +- 连接外部知识源或服务 +- 把重复操作做成可调用工具 -- **工具调用**: AI 可以调用外部工具执行操作 -- **资源访问**: AI 可以读取外部数据源 -- **上下文扩展**: 为 AI 提供额外的上下文信息 +## 基本使用流程 -### 集成优势 +1. 添加 MCP 服务器配置 +2. 启动并确认连接状态 +3. 在工具列表里验证可用工具 +4. 在实际任务里小范围试跑 -- 扩展 AI 能力,执行实际操作 -- 访问实时数据和外部服务 -- 标准化的工具接口 - -## 服务器配置 - -### 添加 MCP 服务器 - -1. 进入 **MCP** 页面 -2. 点击 **添加服务器** -3. 配置服务器信息: - -| 字段 | 说明 | -|------|------| -| 名称 | 服务器标识名称 | -| 命令 | 启动命令 | -| 参数 | 命令参数 | -| 环境变量 | 环境变量配置 | - -### 配置示例 +## 一个简单示例 ```json { "mcpServers": { "filesystem": { "command": "npx", - "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"], - "env": {} - }, - "github": { - "command": "npx", - "args": ["-y", "@modelcontextprotocol/server-github"], - "env": { - "GITHUB_TOKEN": "your-token" - } + "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/workspace"] } } } ``` -### 连接设置 +## 安全边界建议 -| 选项 | 说明 | -|------|------| -| 自动启动 | 应用启动时自动连接 | -| 重连间隔 | 断开后重连的等待时间 | -| 超时时间 | 连接超时设置 | +1. 只授权必要目录和资源 +2. 敏感环境变量不要硬编码在公开配置里 +3. 新工具先在测试项目验证 -## 工具调用 +## 排错顺序 -### 可用工具 - -连接 MCP 服务器后,可以查看提供的工具: - -1. 进入 **MCP** 页面 -2. 选择已连接的服务器 -3. 查看 **工具列表** - -### 工具信息 - -每个工具显示: - -- 工具名称 -- 功能描述 -- 输入参数 -- 返回类型 - -### 调用示例 - -通过 API 调用 MCP 工具: - -```bash -curl http://127.0.0.1:8999/v1/chat/completions \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer your-api-key" \ - -d '{ - "model": "claude-sonnet-4-20250514", - "messages": [ - {"role": "user", "content": "读取 /tmp/test.txt 文件内容"} - ], - "tools": [ - { - "type": "function", - "function": { - "name": "read_file", - "description": "读取文件内容", - "parameters": { - "type": "object", - "properties": { - "path": {"type": "string"} - } - } - } - } - ] - }' -``` - -## 常用 MCP 服务器 - -### 文件系统 - -```json -{ - "filesystem": { - "command": "npx", - "args": ["-y", "@modelcontextprotocol/server-filesystem", "/allowed/path"] - } -} -``` - -### GitHub - -```json -{ - "github": { - "command": "npx", - "args": ["-y", "@modelcontextprotocol/server-github"], - "env": { - "GITHUB_TOKEN": "ghp_xxx" - } - } -} -``` - -### 数据库 - -```json -{ - "postgres": { - "command": "npx", - "args": ["-y", "@modelcontextprotocol/server-postgres"], - "env": { - "DATABASE_URL": "postgresql://..." - } - } -} -``` - -## 服务器管理 - -### 启动/停止 - -- **启动**: 点击服务器的 **启动** 按钮 -- **停止**: 点击 **停止** 按钮 -- **重启**: 点击 **重启** 按钮 - -### 状态监控 - -| 状态 | 说明 | -|------|------| -| 🟢 已连接 | 服务器正常运行 | -| 🔴 已断开 | 服务器未连接 | -| 🟡 连接中 | 正在建立连接 | - -### 日志查看 - -查看 MCP 服务器的运行日志: - -1. 选择服务器 -2. 点击 **查看日志** -3. 实时显示服务器输出 +1. 看连接状态是否正常 +2. 看工具是否成功注册 +3. 看调用参数是否符合工具定义 +4. 看服务器日志定位具体错误 diff --git a/docs/content/03.providers/1.overview.md b/docs/content/03.providers/1.overview.md index c9e33e4fb..addff463d 100644 --- a/docs/content/03.providers/1.overview.md +++ b/docs/content/03.providers/1.overview.md @@ -1,134 +1,68 @@ --- -title: Provider 概述 -description: 支持的 AI 服务提供商 +title: 模型连接概览 +description: 了解不同连接方式,并按你的创作目标选择 navigation: icon: i-heroicons-squares-2x2 --- -# Provider 概述 +# 模型连接概览 -ProxyCast 支持多种 AI 服务提供商(Provider),每种 Provider 有不同的认证方式和特点。 +::alert{type="info"} +本章节属于进阶内容。普通创作者可先使用默认连接,只有在需要多账号或精细控制时再深入配置。 +:: -## Provider 类型 +ProxyCast 支持多种模型连接方式,你可以按自己的使用习惯选择。 -### OAuth 类型 +## 两类连接方式 -通过 OAuth 协议认证,支持自动刷新 Token: +### 自动连接(推荐) -| Provider | 说明 | -|----------|------| -| Kiro Claude | AWS Kiro IDE 的 Claude 凭证 | -| Gemini CLI | Google Gemini CLI 凭证 | -| Qwen | 阿里云通义千问凭证 | -| Codex | OpenAI Codex OAuth 凭证 | -| iFlow | iFlow OAuth 凭证(也支持 Cookie) | +适合希望“少配置、快开始”的用户: -### API Key 类型 +- 登录对应客户端后自动识别 +- 日常创作可直接使用 -使用 API Key 认证,需要手动配置: +### 手动连接 -| Provider | 说明 | -|----------|------| -| OpenAI Custom | 自定义 OpenAI 兼容服务 | -| Claude Custom | 自定义 Claude 兼容服务 | -| Gemini API Key | Gemini API Key 多账号负载均衡 | -| Vertex AI | Google Cloud Vertex AI 服务 | +适合有明确工程需求的用户: -## 选择指南 +- 手动填写 API Key +- 自定义 Base URL +- 多账号并行管理 -### 根据使用场景选择 +## 如何选择 -| 场景 | 推荐 Provider | -|------|---------------| -| 已有 Kiro 订阅 | Kiro Claude | -| 已有 Google AI 订阅 | Gemini CLI | -| 已有阿里云订阅 | Qwen | -| 有 OpenAI API Key | OpenAI Custom | -| 有 Anthropic API Key | Claude Custom | +### 追求稳定创作 -### 根据模型需求选择 +优先选择你最常用、最稳定的连接方式,保持单一主连接即可。 -| 模型系列 | Provider | -|----------|----------| -| Claude 系列 | Kiro Claude, Claude Custom | -| Gemini 系列 | Gemini CLI | -| Qwen 系列 | Qwen | -| GPT 系列 | OpenAI Custom | +### 追求多模型组合 -## Provider 特性对比 +可按任务分配不同连接,例如: -| 特性 | Kiro | Gemini | Qwen | Codex | iFlow | Gemini API Key | Vertex AI | -|------|------|--------|------|-------|-------|----------------|-----------| -| 自动刷新 Token | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | -| 流式响应 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| 工具调用 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| 视觉能力 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| 自定义 Base URL | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | -| 多账号负载均衡 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| 模型排除 | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | -| 模型别名 | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | -| Per-Key 代理 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +- 长文与定稿使用质量优先模型 +- 快速草稿与批量任务使用速度优先模型 +- 图片任务使用视觉能力更强的模型 -## 配置流程 +### 追求高可用 -### OAuth Provider +可配置多个连接作为冗余,避免单点失败影响创作。 -1. 确保已安装对应的 AI 客户端 -2. 在客户端中完成登录 -3. ProxyCast 自动检测凭证文件 -4. 在凭证池中确认凭证状态 +## 配置建议 -### API Key Provider - -1. 获取 API Key -2. 在 ProxyCast 中添加凭证 -3. 配置 Base URL(如需要) -4. 测试凭证有效性 - -## 多 Provider 配置 - -### 负载均衡 - -配置多个 Provider 实现负载均衡: - -```yaml -providers: - - name: kiro-1 - type: kiro - priority: 1 - - name: kiro-2 - type: kiro - priority: 2 - - name: gemini-backup - type: gemini - priority: 10 -``` - -### 故障转移 - -主 Provider 失败时自动切换: - -```yaml -failover: - enabled: true - order: - - kiro-claude - - claude-custom - - gemini-cli -``` +1. 先完成一个主连接并测试可用 +2. 再按场景增加备用连接 +3. 每次新增连接后做一次小任务验证 ## 下一步 -选择你要配置的 Provider: +按你的连接类型进入对应页面: -### OAuth Provider - [Kiro Claude](/providers/kiro-claude) - [Gemini CLI](/providers/gemini-cli) - [Qwen](/providers/qwen) - [Codex](/providers/codex) - [iFlow](/providers/iflow) - -### API Key Provider - [OpenAI Custom](/providers/openai-custom) - [Claude Custom](/providers/claude-custom) - [Gemini API Key](/providers/gemini-api-key) diff --git a/docs/content/03.providers/10.vertex-ai.md b/docs/content/03.providers/10.vertex-ai.md index ce415ac07..ee11ad817 100644 --- a/docs/content/03.providers/10.vertex-ai.md +++ b/docs/content/03.providers/10.vertex-ai.md @@ -7,6 +7,10 @@ navigation: # Vertex AI Provider +::alert{type="info"} +本页属于进阶连接配置。若你已能正常创作,可先跳过。 +:: + 使用 API Key 访问 Google Cloud Vertex AI 服务,支持模型别名映射。 ## 概述 diff --git a/docs/content/03.providers/2.kiro-claude.md b/docs/content/03.providers/2.kiro-claude.md index a3f7e9722..374913174 100644 --- a/docs/content/03.providers/2.kiro-claude.md +++ b/docs/content/03.providers/2.kiro-claude.md @@ -7,6 +7,10 @@ navigation: # Kiro Claude +::alert{type="info"} +本页属于进阶连接配置。若你已能正常创作,可先跳过。 +:: + Kiro Claude 是 AWS Kiro IDE 提供的 Claude AI 服务凭证。 ## 凭证位置 diff --git a/docs/content/03.providers/3.gemini-cli.md b/docs/content/03.providers/3.gemini-cli.md index 658de0d54..0227bfcc5 100644 --- a/docs/content/03.providers/3.gemini-cli.md +++ b/docs/content/03.providers/3.gemini-cli.md @@ -7,6 +7,10 @@ navigation: # Gemini CLI +::alert{type="info"} +本页属于进阶连接配置。若你已能正常创作,可先跳过。 +:: + Gemini CLI 是 Google 提供的命令行 AI 工具,使用 OAuth 认证。 ## 凭证位置 diff --git a/docs/content/03.providers/4.qwen.md b/docs/content/03.providers/4.qwen.md index 72d4fc3a3..3314af139 100644 --- a/docs/content/03.providers/4.qwen.md +++ b/docs/content/03.providers/4.qwen.md @@ -7,6 +7,10 @@ navigation: # Qwen (通义千问) +::alert{type="info"} +本页属于进阶连接配置。若你已能正常创作,可先跳过。 +:: + Qwen 是阿里云提供的大语言模型服务。 ## 凭证位置 diff --git a/docs/content/03.providers/5.openai-custom.md b/docs/content/03.providers/5.openai-custom.md index bbddd9e56..cfe9cb4bb 100644 --- a/docs/content/03.providers/5.openai-custom.md +++ b/docs/content/03.providers/5.openai-custom.md @@ -7,6 +7,10 @@ navigation: # OpenAI Custom +::alert{type="info"} +本页属于进阶连接配置。若你已能正常创作,可先跳过。 +:: + OpenAI Custom 允许你配置任何 OpenAI 兼容的 API 服务。 ## 适用场景 diff --git a/docs/content/03.providers/6.claude-custom.md b/docs/content/03.providers/6.claude-custom.md index 54b51a608..c16f04136 100644 --- a/docs/content/03.providers/6.claude-custom.md +++ b/docs/content/03.providers/6.claude-custom.md @@ -7,6 +7,10 @@ navigation: # Claude Custom +::alert{type="info"} +本页属于进阶连接配置。若你已能正常创作,可先跳过。 +:: + Claude Custom 允许你配置 Anthropic 官方 API 或其他 Claude 兼容服务。 ## 适用场景 diff --git a/docs/content/03.providers/7.codex.md b/docs/content/03.providers/7.codex.md index 7b6358c5d..843a81649 100644 --- a/docs/content/03.providers/7.codex.md +++ b/docs/content/03.providers/7.codex.md @@ -7,6 +7,10 @@ navigation: # Codex Provider +::alert{type="info"} +本页属于进阶连接配置。若你已能正常创作,可先跳过。 +:: + 通过 OAuth 认证使用 OpenAI Codex 服务。 ## 概述 diff --git a/docs/content/03.providers/8.iflow.md b/docs/content/03.providers/8.iflow.md index 5a262581d..3bb359685 100644 --- a/docs/content/03.providers/8.iflow.md +++ b/docs/content/03.providers/8.iflow.md @@ -7,6 +7,10 @@ navigation: # iFlow Provider +::alert{type="info"} +本页属于进阶连接配置。若你已能正常创作,可先跳过。 +:: + iFlow Provider 支持两种认证方式:OAuth 和 Cookie。 ## 概述 diff --git a/docs/content/03.providers/9.gemini-api-key.md b/docs/content/03.providers/9.gemini-api-key.md index 00bd4d67c..b06e89abf 100644 --- a/docs/content/03.providers/9.gemini-api-key.md +++ b/docs/content/03.providers/9.gemini-api-key.md @@ -7,6 +7,10 @@ navigation: # Gemini API Key Provider +::alert{type="info"} +本页属于进阶连接配置。若你已能正常创作,可先跳过。 +:: + 使用 API Key 访问 Google Gemini 服务,支持多账号负载均衡和模型排除。 ## 概述 diff --git a/docs/content/04.api-reference/1.overview.md b/docs/content/04.api-reference/1.overview.md index 2b3919ec1..6540b25b0 100644 --- a/docs/content/04.api-reference/1.overview.md +++ b/docs/content/04.api-reference/1.overview.md @@ -1,107 +1,55 @@ --- -title: API 概述 -description: ProxyCast API 端点和认证 +title: API 概览 +description: 面向进阶用户的本地接口能力说明 navigation: icon: i-heroicons-code-bracket --- -# API 概述 +# API 概览 -ProxyCast 提供 OpenAI 和 Claude 兼容的 API 端点。 +::alert{type="info"} +本章节面向进阶用户与开发者。普通创作者可直接在应用内使用,无需 API 接入。 +:: -## 支持的端点 +当你需要把 ProxyCast 接入脚本、自动化流程或第三方工具时,可使用本地 API。 -### OpenAI 兼容 +## 常见端点类型 -| 端点 | 方法 | 说明 | -|------|------|------| -| `/v1/chat/completions` | POST | 聊天补全 | -| `/v1/models` | GET | 模型列表 | -| `/v1/embeddings` | POST | 文本嵌入 | +### 通用对话端点 -### Claude 兼容 +用于文本生成、对话续写等任务。 -| 端点 | 方法 | 说明 | -|------|------|------| -| `/v1/messages` | POST | 消息 API | -| `/v1/messages/count_tokens` | POST | Token 计数 | +### 模型与管理端点 -### Amp CLI 路由 +用于读取模型列表、状态信息和部分管理能力。 -| 端点 | 方法 | 说明 | -|------|------|------| -| `/api/provider/{provider}/v1/chat/completions` | POST | Amp 聊天补全 | -| `/api/provider/{provider}/v1/messages` | POST | Amp 消息 API | -| `/api/auth/*` | ANY | Amp 认证代理 | -| `/api/user/*` | ANY | Amp 用户代理 | +### 扩展端点 -### 管理 API - -| 端点 | 方法 | 说明 | -|------|------|------| -| `/v0/management/status` | GET | 服务器状态 | -| `/v0/management/credentials` | GET/POST/DELETE | 凭证管理 | -| `/v0/management/config` | GET/PUT | 配置管理 | +用于特定平台或集成场景。 ## 认证方式 -### OpenAI 格式 +- `Authorization: Bearer ` +- 或使用兼容格式的密钥头 -使用 `Authorization` 头: +请确保 API Key 仅在可信环境使用。 -```bash -curl http://127.0.0.1:8999/v1/chat/completions \ - -H "Authorization: Bearer your-api-key" \ - -H "Content-Type: application/json" \ - -d '...' -``` +## 默认地址 -### Claude 格式 +默认本地地址:`http://127.0.0.1:8999` -使用 `x-api-key` 头: +通常建议保持本地监听,不对公网暴露。 -```bash -curl http://127.0.0.1:8999/v1/messages \ - -H "x-api-key: your-api-key" \ - -H "anthropic-version: 2023-06-01" \ - -H "Content-Type: application/json" \ - -d '...' -``` +## 错误排查建议 -## 基础 URL - -默认地址:`http://127.0.0.1:8999` - -可在设置中修改主机和端口。 - -## 错误响应 - -### 错误格式 - -```json -{ - "error": { - "message": "错误描述", - "type": "error_type", - "code": "error_code" - } -} -``` - -### 常见错误码 - -| 状态码 | 说明 | -|--------|------| -| 400 | 请求格式错误 | -| 401 | 认证失败 | -| 404 | 端点不存在 | -| 429 | 速率限制 | -| 500 | 服务器错误 | -| 503 | 服务不可用 | +- `401`:密钥错误或请求头格式错误 +- `404`:端点路径错误 +- `429`:请求频率过高 +- `5xx`:服务端异常或上游波动 ## 下一步 -- [OpenAI API](/api-reference/openai-api) - OpenAI 兼容端点详情 -- [Claude API](/api-reference/claude-api) - Claude 兼容端点详情 -- [管理 API](/api-reference/management-api) - 远程管理端点详情 -- [Amp CLI API](/api-reference/amp-cli-api) - Amp CLI 集成端点详情 +- [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 eecdd54d3..8f38c3f9b 100644 --- a/docs/content/04.api-reference/2.openai-api.md +++ b/docs/content/04.api-reference/2.openai-api.md @@ -7,6 +7,10 @@ navigation: # OpenAI API +::alert{type="info"} +本页是开发者进阶文档。普通创作者可直接在应用内使用,无需 API 调用。 +:: + ProxyCast 提供完整的 OpenAI Chat Completions API 兼容。 ## /v1/chat/completions diff --git a/docs/content/04.api-reference/3.claude-api.md b/docs/content/04.api-reference/3.claude-api.md index e5055e037..3bba8e116 100644 --- a/docs/content/04.api-reference/3.claude-api.md +++ b/docs/content/04.api-reference/3.claude-api.md @@ -7,6 +7,10 @@ navigation: # Claude API +::alert{type="info"} +本页是开发者进阶文档。普通创作者可直接在应用内使用,无需 API 调用。 +:: + ProxyCast 提供 Anthropic Claude Messages API 兼容。 ## /v1/messages diff --git a/docs/content/04.api-reference/4.management-api.md b/docs/content/04.api-reference/4.management-api.md index 481130e55..0b969f675 100644 --- a/docs/content/04.api-reference/4.management-api.md +++ b/docs/content/04.api-reference/4.management-api.md @@ -7,6 +7,10 @@ navigation: # 管理 API +::alert{type="info"} +本页是开发者进阶文档,主要用于自动化管理与运维集成。 +:: + ProxyCast 提供远程管理 API,用于配置和监控服务。 ## 认证 diff --git a/docs/content/04.api-reference/5.amp-cli-api.md b/docs/content/04.api-reference/5.amp-cli-api.md index f5ce6c500..a3d00a500 100644 --- a/docs/content/04.api-reference/5.amp-cli-api.md +++ b/docs/content/04.api-reference/5.amp-cli-api.md @@ -7,6 +7,10 @@ navigation: # Amp CLI API +::alert{type="info"} +本页是开发者进阶文档。若你不涉及 Amp CLI 集成,可跳过。 +:: + ProxyCast 提供 Amp CLI 兼容的路由端点,支持将 Amp CLI 请求路由到本地 OAuth 凭证。 ## 概述 diff --git a/docs/content/05.troubleshooting/1.common-issues.md b/docs/content/05.troubleshooting/1.common-issues.md index ddf5e6de4..7ab4fdc7e 100644 --- a/docs/content/05.troubleshooting/1.common-issues.md +++ b/docs/content/05.troubleshooting/1.common-issues.md @@ -1,144 +1,107 @@ --- title: 常见问题 -description: 常见问题汇总和解决方案 +description: 按症状快速定位问题并恢复创作 navigation: icon: i-heroicons-question-mark-circle --- # 常见问题 -本页汇总了 ProxyCast 使用中的常见问题和解决方案。 +本页给你一个最快排查顺序: -## 启动问题 +1. 看页面提示 +2. 看当前项目与资源选择是否正确 +3. 看连接状态与网络 +4. 再进入详细排查页 -### 应用无法启动 +## 启动后看不到内容 -**症状**: 双击应用图标后无反应 +### 症状 -**解决方案**: +- 页面空白或内容未刷新 +- 明明生成过,但当前列表看不到 -1. **macOS**: 右键点击应用,选择"打开" -2. **Windows**: 以管理员身份运行 -3. 检查系统日志查看错误信息 +### 先检查 -### 端口被占用 +1. 是否选错了项目 +2. 是否切到了筛选分类(例如只看图片) +3. 是否处于搜索过滤状态 -**症状**: 服务启动失败,提示端口已被使用 +### 处理建议 -**解决方案**: +- 先切回“全部”分类 +- 清空搜索词 +- 刷新当前页面再确认 -```bash -# 查找占用端口的进程 -# macOS/Linux -lsof -i :8999 +## 图片没显示或数量不对 -# Windows -netstat -ano | findstr :8999 -``` +### 症状 -或在设置中更改端口号。 +- 资源页看不到已生成图片 +- 图片数量和预期不一致 -## 凭证问题 +### 先检查 -### 凭证未检测到 +1. 当前资源库(项目)是否正确 +2. 是否选在“图片”分类 +3. 图片是否已入库(自动或手动补录) -**症状**: 凭证池为空,未显示任何凭证 +### 处理建议 -**解决方案**: +- 回到图片生成页确认目标资源库 +- 对历史结果执行“补录到资源库” +- 回资源页切换“全部”核对总量 -1. 确认 AI 客户端已安装并登录 -2. 检查凭证文件是否存在 -3. 点击"刷新凭证"重新扫描 -4. 手动添加凭证 +## 生成失败或超时 -详见 [凭证错误](/troubleshooting/credential-errors) +### 症状 -### Token 过期 +- 请求长时间无响应 +- 返回超时或失败提示 -**症状**: 请求返回 401 错误 +### 处理建议 -**解决方案**: +1. 降低同一时间的并发任务数 +2. 缩短单次输入长度或拆成批次 +3. 稍后重试,观察是否为瞬时波动 +4. 必要时切换备用连接 -1. 打开对应的 AI 客户端 -2. 确认登录状态 -3. 在 ProxyCast 中刷新凭证 +## 认证或权限错误 -## 连接问题 +### 常见提示 -### 无法连接到 Provider +- `401`:认证失败 +- `403`:权限不足 -**症状**: 请求超时或连接失败 +### 处理建议 -**解决方案**: +1. 重新确认连接状态 +2. 刷新或重建对应连接 +3. 再做一次小请求测试 -1. 检查网络连接 -2. 确认 Provider 服务正常 -3. 检查代理设置 +详见 [连接鉴权问题](/troubleshooting/credential-errors)。 -详见 [连接问题](/troubleshooting/connection-issues) +## 网络连接不稳定 -### SSL 证书错误 +### 常见提示 -**症状**: 提示证书验证失败 +- 网络超时 +- DNS 解析失败 +- TLS/证书错误 -**解决方案**: +### 处理建议 -1. 检查系统时间是否正确 -2. 更新系统根证书 -3. 检查代理是否拦截 HTTPS +1. 检查本机网络 +2. 检查代理配置是否正确 +3. 避开高峰时段进行批量任务 -## API 问题 +详见 [网络与连接问题](/troubleshooting/connection-issues)。 -### 请求返回错误 +## 仍然无法解决 -**常见错误码**: +请整理以下信息后反馈: -| 错误码 | 原因 | 解决方案 | -|--------|------|----------| -| 400 | 请求格式错误 | 检查请求参数 | -| 401 | 认证失败 | 检查 API Key | -| 404 | 端点不存在 | 检查 URL | -| 429 | 速率限制 | 降低请求频率 | -| 500 | 服务器错误 | 查看日志 | - -### 流式响应中断 - -**症状**: 流式响应突然停止 - -**解决方案**: - -1. 检查网络稳定性 -2. 增加超时时间 -3. 检查 Provider 状态 - -## 性能问题 - -### 响应缓慢 - -**可能原因**: - -1. Provider 响应慢 -2. 网络延迟高 -3. 请求内容过长 - -**解决方案**: - -1. 切换到更快的 Provider -2. 使用更快的模型 -3. 减少请求内容长度 - -### 内存占用高 - -**解决方案**: - -1. 清除请求日志 -2. 减少日志保留天数 -3. 重启应用 - -## 获取帮助 - -如果以上方案无法解决问题: - -1. 查看应用日志 -2. 在 GitHub 提交 Issue -3. 提供详细的错误信息和复现步骤 +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 index 6eb6b9c10..217c13c08 100644 --- a/docs/content/05.troubleshooting/2.credential-errors.md +++ b/docs/content/05.troubleshooting/2.credential-errors.md @@ -1,146 +1,61 @@ --- -title: 凭证错误 -description: OAuth Token 问题诊断 +title: 连接鉴权问题 +description: 处理连接失效、认证失败与账号状态异常 navigation: icon: i-heroicons-key --- -# 凭证错误 +# 连接鉴权问题 -本页帮助你诊断和解决凭证相关的问题。 +本页用于处理“能打开应用,但调用失败”的问题。 -## 诊断步骤 +## 快速判断 -### 1. 检查凭证文件 +如果你看到以下报错,通常属于连接鉴权问题: -确认凭证文件存在: +- `401` 认证失败 +- `403` 权限不足 +- 连接状态显示已失效 -```bash -# Kiro -ls -la ~/.kiro/credentials.json +## 3 步排查 -# Gemini CLI -ls -la ~/.config/gemini-cli/oauth_creds.json +### 第 1 步:检查连接状态 -# Qwen -ls -la ~/.config/qwen/credentials.json -``` +在连接管理页面确认当前连接是否可用。 -### 2. 验证文件格式 +### 第 2 步:刷新或重建连接 -检查 JSON 格式是否正确: +- 先尝试刷新 +- 刷新失败则重新登录或重新添加连接 -```bash -# 验证 JSON 格式 -cat ~/.kiro/credentials.json | python -m json.tool -``` +### 第 3 步:做最小测试 -### 3. 检查 Token 有效性 +使用一条简短请求验证是否恢复。 -在 ProxyCast 中: +## 常见场景 -1. 进入凭证池 -2. 点击凭证的"测试"按钮 -3. 查看测试结果 +### 场景 1:昨天还能用,今天突然失败 -## 常见错误 +高概率是连接过期或上游状态变化。建议先重建该连接。 -### Token 已过期 +### 场景 2:部分模型可用,部分模型失败 -**症状**: 凭证状态显示"已过期" +可能是模型权限差异或连接配置不匹配。先换一个已知可用模型测试。 -**原因**: -- Access Token 超过有效期 -- Refresh Token 也已过期 +### 场景 3:导入配置后无法调用 -**解决方案**: +导入通常不包含敏感凭证信息,需要重新校验连接。 -1. 打开对应的 AI 客户端 -2. 重新登录 -3. 在 ProxyCast 中刷新凭证 +## 进阶检查(可选) -### Token 无效 +如果你需要定位更深层原因,可检查: -**症状**: 测试凭证返回 401 错误 +- 本地凭证文件是否存在且可读 +- 连接使用的账号是否仍有效 +- 代理或网络环境是否变更 -**原因**: -- Token 被撤销 -- 账户状态异常 +## 预防建议 -**解决方案**: - -1. 检查 AI 客户端账户状态 -2. 重新登录获取新 Token -3. 删除旧凭证,重新添加 - -### 刷新失败 - -**症状**: 自动刷新 Token 失败 - -**原因**: -- Refresh Token 过期 -- 网络问题 -- 服务端问题 - -**解决方案**: - -1. 检查网络连接 -2. 手动刷新凭证 -3. 如仍失败,重新登录客户端 - -## Provider 特定问题 - -### Kiro Claude - -**凭证位置**: `~/.kiro/credentials.json` - -**常见问题**: - -1. **未安装 Kiro**: 安装 Kiro IDE -2. **未登录**: 在 Kiro 中完成登录 -3. **订阅过期**: 检查 Kiro 订阅状态 - -### Gemini CLI - -**凭证位置**: `~/.config/gemini-cli/oauth_creds.json` - -**常见问题**: - -1. **未安装 CLI**: 安装 Gemini CLI -2. **未认证**: 运行 `gemini auth login` -3. **项目配额用尽**: 检查 Google Cloud 配额 - -### Qwen - -**凭证位置**: `~/.config/qwen/credentials.json` - -**常见问题**: - -1. **账户未开通**: 开通阿里云通义千问服务 -2. **配额用尽**: 检查阿里云账户余额 -3. **区域限制**: 确认服务区域设置 - -## 手动修复 - -### 重置凭证 - -1. 删除凭证文件 -2. 重新登录 AI 客户端 -3. 在 ProxyCast 中刷新凭证 - -### 手动添加凭证 - -如果自动检测失败: - -1. 从 AI 客户端获取 Token -2. 在 ProxyCast 中手动添加 -3. 测试凭证有效性 - -## 日志查看 - -查看详细错误信息: - -1. 进入设置 > 高级 -2. 设置日志级别为 Debug -3. 重现问题 -4. 查看日志文件 +1. 保留一个备用连接 +2. 关键活动前做一次连通性测试 +3. 定期清理长期失效连接 diff --git a/docs/content/05.troubleshooting/3.connection-issues.md b/docs/content/05.troubleshooting/3.connection-issues.md index b23dd7bd4..4ff8c0628 100644 --- a/docs/content/05.troubleshooting/3.connection-issues.md +++ b/docs/content/05.troubleshooting/3.connection-issues.md @@ -1,176 +1,72 @@ --- -title: 连接问题 -description: 网络和代理故障排除 +title: 网络与连接问题 +description: 处理超时、DNS、证书和代理相关问题 navigation: icon: i-heroicons-signal --- -# 连接问题 +# 网络与连接问题 -本页帮助你诊断和解决网络连接相关的问题。 +当你频繁遇到超时、连接失败或证书错误时,按下面顺序排查。 -## 诊断步骤 +## 排查顺序 -### 1. 检查网络连接 +1. 本机网络是否正常 +2. 代理是否配置正确 +3. 请求是否过于集中 +4. 是否为上游短时波动 -```bash -# 测试网络连通性 -ping api.anthropic.com -ping api.openai.com -``` - -### 2. 检查 DNS 解析 - -```bash -# 测试 DNS 解析 -nslookup api.anthropic.com -``` - -### 3. 测试 HTTPS 连接 - -```bash -# 测试 HTTPS 连接 -curl -I https://api.anthropic.com -``` - -## 常见问题 +## 常见症状与处理 ### 连接超时 -**症状**: 请求长时间无响应后超时 +处理建议: -**可能原因**: -- 网络不稳定 -- 防火墙阻止 -- Provider 服务不可用 - -**解决方案**: - -1. 检查网络连接 -2. 检查防火墙设置 -3. 尝试使用代理 -4. 增加超时时间 +1. 先减少并发 +2. 拆分任务批次 +3. 适当增加超时 +4. 稍后重试 ### DNS 解析失败 -**症状**: 无法解析域名 +处理建议: -**解决方案**: +1. 切换网络后重试 +2. 检查系统 DNS 设置 +3. 清理 DNS 缓存后重试 -1. 检查 DNS 设置 -2. 尝试使用公共 DNS(如 8.8.8.8) -3. 清除 DNS 缓存 +### 证书错误 -```bash -# macOS -sudo dscacheutil -flushcache +处理建议: -# Windows -ipconfig /flushdns -``` +1. 校准系统时间 +2. 检查网络代理是否拦截 HTTPS +3. 更换网络环境复测 -### SSL/TLS 错误 +## 代理相关 -**症状**: 证书验证失败 +如果你使用代理,请重点检查: -**可能原因**: -- 系统时间不正确 -- 根证书过期 -- 代理拦截 HTTPS +1. 代理地址格式是否正确 +2. 账号密码是否有效 +3. 排除列表是否包含本地地址 -**解决方案**: +常见格式示例: -1. 同步系统时间 -2. 更新系统证书 -3. 检查代理设置 +- `http://proxy.example.com:8080` +- `http://user:password@proxy.example.com:8080` +- `socks5://proxy.example.com:1080` -## 代理配置 +## 什么时候判断是上游问题 -### 设置代理 +满足以下特征时,通常是上游波动: -在 ProxyCast 设置中配置代理: +- 同一配置偶发失败、重试可恢复 +- 不同网络环境都出现短时错误 +- 一段时间后无需改配置自动恢复 -1. 进入 **设置** > **高级** -2. 配置代理设置: +## 仍未恢复怎么办 -| 选项 | 说明 | -|------|------| -| HTTP 代理 | HTTP 代理地址 | -| HTTPS 代理 | HTTPS 代理地址 | -| 不代理地址 | 排除的地址列表 | - -### 代理格式 - -``` -http://proxy.example.com:8080 -http://user:password@proxy.example.com:8080 -socks5://proxy.example.com:1080 -``` - -### 环境变量 - -也可以通过环境变量设置: - -```bash -export HTTP_PROXY=http://proxy.example.com:8080 -export HTTPS_PROXY=http://proxy.example.com:8080 -export NO_PROXY=localhost,127.0.0.1 -``` - -## Provider 特定问题 - -### Anthropic API - -**端点**: `https://api.anthropic.com` - -**常见问题**: -- 某些地区可能需要代理 -- 检查 API 状态页面 - -### Google Gemini - -**端点**: `https://generativelanguage.googleapis.com` - -**常见问题**: -- 需要 Google Cloud 项目 -- 检查 API 是否启用 - -### 阿里云 Qwen - -**端点**: `https://dashscope.aliyuncs.com` - -**常见问题**: -- 海外访问可能需要代理 -- 检查区域设置 - -## 防火墙设置 - -### 允许的端口 - -确保防火墙允许以下端口: - -| 端口 | 用途 | -|------|------| -| 443 | HTTPS 请求 | -| 8999 | ProxyCast API(默认) | - -### macOS 防火墙 - -1. 系统偏好设置 > 安全性与隐私 -2. 防火墙 > 防火墙选项 -3. 允许 ProxyCast 接收传入连接 - -### Windows 防火墙 - -1. 控制面板 > Windows Defender 防火墙 -2. 允许应用通过防火墙 -3. 添加 ProxyCast - -## 调试模式 - -启用详细日志: - -1. 进入 **设置** > **高级** -2. 设置日志级别为 **Debug** -3. 重现问题 -4. 查看网络请求日志 +1. 记录失败时间段 +2. 保存错误提示和关键日志 +3. 先切换备用连接保障创作不中断 diff --git a/docs/content/06.development/5.plugin-development.md b/docs/content/06.development/5.plugin-development.md index befd0a89a..e60759884 100644 --- a/docs/content/06.development/5.plugin-development.md +++ b/docs/content/06.development/5.plugin-development.md @@ -1,249 +1,17 @@ -# 插件开发指南 +--- +title: 插件开发(迁移说明) +description: 本章节已迁移至开放平台文档 +navigation: + icon: i-heroicons-arrow-top-right-on-square +--- + +# 插件开发(迁移说明) ::alert{type="info"} -📢 本文档已迁移至开放平台。请访问 [开放平台 - 插件开发](/open-platform/plugin-development) 获取最新内容。 +插件开发文档已迁移,请阅读:[开放平台 - 插件开发指南](/open-platform/plugin-development)。 :: -本文档描述 ProxyCast 插件系统的规范和开发指南,为插件市场做准备。 +迁移后,开发者文档与用户文档分层更清晰: -## 插件类型 - -ProxyCast 支持两种类型的插件: - -### 1. 脚本插件 (Script Plugin) - -纯 JavaScript/TypeScript 插件,通过 Hook 机制扩展功能。 - -```json -{ - "plugin_type": "script", - "entry": "main.js", - "hooks": ["on_request", "on_response"] -} -``` - -### 2. 二进制插件 (Binary Plugin) - -独立的可执行文件,通过 CLI 接口与 ProxyCast 通信。适合需要系统级操作的工具。 - -```json -{ - "plugin_type": "binary", - "entry": "my-tool-cli", - "binary": { - "binary_name": "my-tool-cli", - "github_owner": "your-org", - "github_repo": "your-repo", - "platform_binaries": { - "macos-arm64": "my-tool-aarch64-apple-darwin", - "macos-x64": "my-tool-x86_64-apple-darwin", - "linux-x64": "my-tool-x86_64-unknown-linux-gnu", - "linux-arm64": "my-tool-aarch64-unknown-linux-gnu", - "windows-x64": "my-tool-x86_64-pc-windows-msvc.exe" - }, - "checksum_file": "checksums.txt" - } -} -``` - -## 插件包结构 - -插件以 ZIP 包形式分发,包含以下文件: - -``` -my-plugin.zip -├── plugin.json # 插件元数据(必需) -└── config.json # 默认配置(可选) -``` - -### plugin.json 规范 - -```json -{ - "name": "my-plugin", - "version": "1.0.0", - "description": "插件描述", - "author": "作者名", - "homepage": "https://github.com/org/repo", - "license": "MIT", - "plugin_type": "binary", - "entry": "my-tool-cli", - "hooks": [], - "min_proxycast_version": "1.0.0", - "binary": { ... }, - "ui": { - "surfaces": ["tools"], - "icon": "Cpu", - "title": "我的工具", - "default_width": 800, - "default_height": 600 - } -} -``` - -#### 字段说明 - -| 字段 | 类型 | 必需 | 说明 | -|------|------|------|------| -| `name` | string | ✅ | 插件唯一标识符,小写字母和连字符 | -| `version` | string | ✅ | 语义化版本号 (semver) | -| `description` | string | ✅ | 插件描述 | -| `author` | string | ❌ | 作者名称 | -| `homepage` | string | ❌ | 项目主页 URL | -| `license` | string | ❌ | 开源许可证 | -| `plugin_type` | string | ✅ | `script` 或 `binary` | -| `entry` | string | ✅ | 入口文件/二进制名称 | -| `hooks` | array | ❌ | 注册的 Hook 列表 | -| `min_proxycast_version` | string | ❌ | 最低 ProxyCast 版本要求 | -| `binary` | object | ❌ | 二进制插件配置 | -| `ui` | object | ❌ | UI 配置 | - -## UI 展示位置 (Surfaces) - -插件可以在以下位置显示 UI: - -| Surface | 说明 | 入口位置 | -|---------|------|----------| -| `tools` | 工具箱 | 导航栏「工具」页面 | -| `sidebar` | 侧边栏 | 主侧边栏(规划中) | -| `settings` | 设置页 | 设置页扩展区域(规划中) | - -### 示例:工具类插件 - -```json -{ - "ui": { - "surfaces": ["tools"], - "icon": "Cpu", - "title": "机器码管理工具" - } -} -``` - -安装后,插件会出现在「工具箱」页面,用户点击即可打开。 - -## 图标规范 - -使用 [Lucide Icons](https://lucide.dev/icons/) 图标名称: - -```json -{ - "ui": { - "icon": "Cpu" - } -} -``` - -常用图标: -- `Cpu` - 系统/硬件工具 -- `Globe` - 网络工具 -- `Database` - 数据工具 -- `Shield` - 安全工具 -- `Wrench` - 通用工具 -- `Terminal` - 命令行工具 - -## 二进制插件 CLI 接口规范 - -二进制插件通过 CLI 与 ProxyCast 通信,必须遵循以下规范: - -### 输出格式 - -所有输出必须是 JSON 格式: - -```bash -# 成功 -$ my-tool-cli get -{"machine_id": "550e8400-e29b-41d4-a716-446655440000"} - -# 错误 -$ my-tool-cli invalid-command -{"error": "未知命令: invalid-command"} -``` - -### 退出码 - -- `0` - 成功 -- `1` - 错误 - -### 命令结构 - -```bash -my-tool-cli [arguments] -``` - -建议实现 `help` 命令: - -```bash -$ my-tool-cli help -MachineIdTool CLI v1.0.0 -用法: my-tool-cli <命令> [参数] - -命令: - get 获取当前值 - set 设置新值 - help 显示帮助 -``` - -## 插件安装流程 - -1. **下载插件包** - 从 URL 或本地文件获取 ZIP -2. **解压验证** - 解压并验证 plugin.json -3. **下载二进制** - 如果是二进制插件,根据当前平台下载对应二进制 -4. **校验完整性** - 验证 checksum -5. **注册插件** - 将插件信息写入数据库 -6. **加载插件** - 启用插件功能 - -## 插件发布 - -### GitHub Release 发布 - -推荐通过 GitHub Release 发布插件: - -1. 创建 `plugin/` 目录,包含 `plugin.json` 和 `config.json` -2. 在 GitHub Actions 中打包 ZIP -3. 上传到 Release Assets - -```yaml -- name: Package plugin - run: | - mkdir -p plugin-package - cp plugin/plugin.json plugin-package/ - cp plugin/config.json plugin-package/ - cd plugin-package - zip -j ../release/my-plugin.zip plugin.json config.json -``` - -### 插件市场(规划中) - -未来将支持: -- 插件市场浏览和搜索 -- 一键安装 -- 自动更新 -- 评分和评论 - -## 推荐插件 - -ProxyCast 内置推荐插件列表,在「工具箱」和「插件中心」显示未安装的推荐插件。 - -要将插件添加到推荐列表,请提交 PR 修改: -- `src/components/tools/ToolsPage.tsx` - `recommendedPlugins` -- `src/components/plugins/PluginManager.tsx` - `recommendedPlugins` - -## 示例插件 - -参考 [MachineIdTool](https://github.com/aiclientproxy/MachineIdTool) 作为二进制插件的完整示例。 - -## 开发调试 - -### 本地安装测试 - -1. 打包插件 ZIP -2. 在「插件中心」点击「安装插件」 -3. 选择本地 ZIP 文件安装 - -### 日志调试 - -插件执行日志保存在: -- macOS: `~/Library/Application Support/proxycast/logs/` -- Windows: `%APPDATA%/proxycast/logs/` -- Linux: `~/.local/share/proxycast/logs/` +- 开放平台:插件规范、接入流程、生态能力 +- 用户指南:插件安装与使用 diff --git a/docs/content/08.open-platform/1.overview.md b/docs/content/08.open-platform/1.overview.md index c076289e7..0c8a7adf5 100644 --- a/docs/content/08.open-platform/1.overview.md +++ b/docs/content/08.open-platform/1.overview.md @@ -1,63 +1,41 @@ -# 开放平台概述 +--- +title: 开放平台概览 +description: 面向开发者与生态合作方的扩展能力 +navigation: + icon: i-heroicons-cube-transparent +--- -ProxyCast 开放平台为开发者和服务商提供扩展能力,包括插件系统和中转商生态合作方案。 +# 开放平台概览 + +开放平台面向开发者与生态合作方,用于扩展 ProxyCast 的能力边界。 + +::alert{type="info"} +如果你是普通创作者,可先跳过本章节。 +:: ## 平台能力 -### 🔌 插件系统 +### 插件系统 -通过插件扩展 ProxyCast 功能: - -- **脚本插件** - JavaScript/TypeScript 插件,通过 Hook 机制扩展 -- **二进制插件** - 独立可执行文件,适合系统级操作 -- **工具插件** - 在工具箱中显示的独立工具 +用于扩展工具、工作流和界面能力。 [了解更多 →](/open-platform/plugins) -### 🔗 ProxyCast Connect +### Connect 能力 -中转商生态合作方案,实现一键配置: - -- **一键配置** - 用户点击链接即可完成配置 -- **品牌展示** - 中转商在 ProxyCast 内有专属展示位 -- **统计回调** - 追踪推广效果 +用于外部平台与 ProxyCast 的配置联动与生态集成。 [了解更多 →](/open-platform/connect) -## 核心价值 +## 谁适合阅读 -| 角色 | 价值 | -|------|------| -| **开发者** | 扩展功能、定制工具、集成服务 | -| **中转商** | 用户转化率提升、品牌曝光、差异化竞争 | -| **用户** | 一键配置、开箱即用、统一管理 | -| **ProxyCast** | 生态繁荣、用户增长 | +- 需要开发自定义插件的团队 +- 需要对接外部系统的开发者 +- 需要建设生态能力的合作方 -## 快速开始 +## 快速入口 - - -## 相关仓库 - -| 仓库 | 说明 | -|------|------| -| [proxycast](https://github.com/aiclientproxy/proxycast) | ProxyCast 主项目 | -| [connect](https://github.com/aiclientproxy/connect) | 中转商注册仓库 | -| [MachineIdTool](https://github.com/aiclientproxy/MachineIdTool) | 插件示例项目 | +- [插件中心](/open-platform/plugins) +- [插件开发指南](/open-platform/plugin-development) +- [Connect 接入](/open-platform/connect) +- [Connect 集成说明](/open-platform/connect-integration) diff --git a/docs/content/08.open-platform/2.plugins.md b/docs/content/08.open-platform/2.plugins.md index e99879771..04fc68bd3 100644 --- a/docs/content/08.open-platform/2.plugins.md +++ b/docs/content/08.open-platform/2.plugins.md @@ -1,112 +1,38 @@ -# 插件中心 +--- +title: 开放平台 - 插件中心 +description: 面向开发者的插件安装、管理与发布能力 +navigation: + icon: i-heroicons-puzzle-piece +--- -ProxyCast 支持通过插件扩展功能。插件中心提供插件的安装、管理和配置。 +# 开放平台 - 插件中心 -## 访问插件中心 +::alert{type="info"} +本页面向开发者与高级用户。普通创作者可使用用户指南中的插件页。 +:: -点击左侧导航栏的「插件中心」进入插件管理页面。 +ProxyCast 支持通过插件扩展能力,适用于自定义工具、自动化流程和生态集成。 -## 功能概览 +## 你可以做什么 -### 推荐插件 +- 安装推荐插件或第三方插件包 +- 管理插件启用状态与版本 +- 查看插件加载与执行状态 +- 在工具入口中使用插件能力 -插件中心会显示推荐的插件列表,点击「一键安装」即可快速安装。 +## 安装方式 -### 已安装插件 +1. 推荐插件一键安装 +2. 通过 URL 安装 ZIP 包 +3. 通过本地文件安装 ZIP 包 -显示所有已安装的插件,包括: -- 插件名称和版本 -- 安装来源(本地/URL/GitHub) -- 启用/禁用状态 -- 卸载按钮 +## 管理建议 -### 已加载插件 +1. 先安装高频插件,再逐步扩展 +2. 每次新增插件后做一次功能验证 +3. 定期清理长期不用的插件 -显示当前运行中的插件状态: -- 执行次数 -- 错误次数 -- 最后执行时间 +## 下一步 -## 安装插件 - -### 方式一:推荐插件一键安装 - -1. 在「推荐插件」区域找到想要的插件 -2. 点击「一键安装」 -3. 等待下载和安装完成 - -### 方式二:从 URL 安装 - -1. 点击「安装插件」按钮 -2. 输入插件 ZIP 包的下载 URL -3. 点击「安装」 - -支持的 URL 格式: -- GitHub Release: `https://github.com/org/repo/releases/latest/download/plugin.zip` -- 直接下载链接: `https://example.com/plugin.zip` - -### 方式三:从本地文件安装 - -1. 点击「安装插件」按钮 -2. 点击「选择文件」 -3. 选择本地的 `.zip` 文件 -4. 点击「安装」 - -## 使用插件 - -安装完成后,插件会根据类型出现在不同位置: - -### 工具类插件 - -工具类插件会出现在「工具箱」页面: - -1. 点击左侧导航栏的「工具」 -2. 在工具列表中找到已安装的插件 -3. 点击「打开工具」使用 - -### 其他类型插件 - -- **Hook 插件**: 自动在请求/响应时执行 -- **侧边栏插件**: 出现在主侧边栏(规划中) - -## 管理插件 - -### 启用/禁用 - -在已加载插件列表中,点击电源图标可以启用或禁用插件。 - -### 卸载 - -1. 在「已安装插件包」列表中找到要卸载的插件 -2. 点击红色的删除按钮 -3. 确认卸载 - -卸载会删除插件文件和配置,但不会删除插件产生的数据。 - -## 二进制组件 - -部分功能需要安装额外的二进制组件: - -- **aster-server**: AI Agent 框架,提供 Agent 对话能力 - -在「二进制组件」区域可以查看和管理这些组件。 - -## 常见问题 - -### 插件安装失败 - -1. 检查网络连接 -2. 确认 URL 正确且可访问 -3. 检查 ZIP 包格式是否正确 - -### 插件无法加载 - -1. 检查 ProxyCast 版本是否满足插件要求 -2. 查看日志了解详细错误信息 -3. 尝试重新安装插件 - -### 二进制插件权限问题 - -部分二进制插件需要管理员权限: -- **Windows**: 以管理员身份运行 ProxyCast -- **macOS/Linux**: 插件会提示需要的权限 +- [插件开发指南](/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 243f8e735..eb1a20415 100644 --- a/docs/content/08.open-platform/3.plugin-development.md +++ b/docs/content/08.open-platform/3.plugin-development.md @@ -1,219 +1,44 @@ -# 插件开发指南 +--- +title: 开放平台 - 插件开发指南 +description: 开发 ProxyCast 插件的规范与最佳实践 +navigation: + icon: i-heroicons-code-bracket-square +--- -本文档描述 ProxyCast 插件系统的规范和开发指南。 +# 开放平台 - 插件开发指南 + +::alert{type="info"} +本页面向开发者。若你不开发插件,可跳过。 +:: + +本文档说明插件类型、打包方式和开发建议,帮助你把能力稳定接入 ProxyCast。 ## 插件类型 -ProxyCast 支持两种类型的插件: +### 脚本插件 -### 1. 脚本插件 (Script Plugin) +基于 JavaScript/TypeScript,通过 Hook 扩展行为。 -纯 JavaScript/TypeScript 插件,通过 Hook 机制扩展功能。 +### 二进制插件 -```json -{ - "plugin_type": "script", - "entry": "main.js", - "hooks": ["on_request", "on_response"] -} -``` +通过独立可执行文件提供系统级能力,适合重计算或本地工具集成。 -### 2. 二进制插件 (Binary Plugin) +## 基础结构 -独立的可执行文件,通过 CLI 接口与 ProxyCast 通信。适合需要系统级操作的工具。 +插件以 ZIP 分发,至少包含: -```json -{ - "plugin_type": "binary", - "entry": "my-tool-cli", - "binary": { - "binary_name": "my-tool-cli", - "github_owner": "your-org", - "github_repo": "your-repo", - "platform_binaries": { - "macos-arm64": "my-tool-aarch64-apple-darwin", - "macos-x64": "my-tool-x86_64-apple-darwin", - "linux-x64": "my-tool-x86_64-unknown-linux-gnu", - "linux-arm64": "my-tool-aarch64-unknown-linux-gnu", - "windows-x64": "my-tool-x86_64-pc-windows-msvc.exe" - }, - "checksum_file": "checksums.txt" - } -} -``` +- `plugin.json`:元数据与入口定义 +- 可选配置文件与资源文件 -## 插件包结构 +## 开发建议 -插件以 ZIP 包形式分发,包含以下文件: +1. 先做最小可用版本 +2. 明确输入输出协议 +3. 做异常与超时处理 +4. 提供清晰的版本兼容说明 -``` -my-plugin.zip -├── plugin.json # 插件元数据(必需) -└── config.json # 默认配置(可选) -``` +## 发布建议 -### plugin.json 规范 - -```json -{ - "name": "my-plugin", - "version": "1.0.0", - "description": "插件描述", - "author": "作者名", - "homepage": "https://github.com/org/repo", - "license": "MIT", - "plugin_type": "binary", - "entry": "my-tool-cli", - "hooks": [], - "min_proxycast_version": "1.0.0", - "binary": { ... }, - "ui": { - "surfaces": ["tools"], - "icon": "Cpu", - "title": "我的工具", - "default_width": 800, - "default_height": 600 - } -} -``` - -### 字段说明 - -| 字段 | 类型 | 必需 | 说明 | -|------|------|------|------| -| `name` | string | ✅ | 插件唯一标识符,小写字母和连字符 | -| `version` | string | ✅ | 语义化版本号 (semver) | -| `description` | string | ✅ | 插件描述 | -| `author` | string | ❌ | 作者名称 | -| `homepage` | string | ❌ | 项目主页 URL | -| `license` | string | ❌ | 开源许可证 | -| `plugin_type` | string | ✅ | `script` 或 `binary` | -| `entry` | string | ✅ | 入口文件/二进制名称 | -| `hooks` | array | ❌ | 注册的 Hook 列表 | -| `min_proxycast_version` | string | ❌ | 最低 ProxyCast 版本要求 | -| `binary` | object | ❌ | 二进制插件配置 | -| `ui` | object | ❌ | UI 配置 | - -## UI 展示位置 (Surfaces) - -插件可以在以下位置显示 UI: - -| Surface | 说明 | 入口位置 | -|---------|------|----------| -| `tools` | 工具箱 | 导航栏「工具」页面 | -| `sidebar` | 侧边栏 | 主侧边栏(规划中) | -| `settings` | 设置页 | 设置页扩展区域(规划中) | - -### 示例:工具类插件 - -```json -{ - "ui": { - "surfaces": ["tools"], - "icon": "Cpu", - "title": "机器码管理工具" - } -} -``` - -## 图标规范 - -使用 [Lucide Icons](https://lucide.dev/icons/) 图标名称: - -常用图标: -- `Cpu` - 系统/硬件工具 -- `Globe` - 网络工具 -- `Database` - 数据工具 -- `Shield` - 安全工具 -- `Wrench` - 通用工具 -- `Terminal` - 命令行工具 - -## 二进制插件 CLI 接口规范 - -二进制插件通过 CLI 与 ProxyCast 通信,必须遵循以下规范: - -### 输出格式 - -所有输出必须是 JSON 格式: - -```bash -# 成功 -$ my-tool-cli get -{"machine_id": "550e8400-e29b-41d4-a716-446655440000"} - -# 错误 -$ my-tool-cli invalid-command -{"error": "未知命令: invalid-command"} -``` - -### 退出码 - -- `0` - 成功 -- `1` - 错误 - -### 命令结构 - -```bash -my-tool-cli [arguments] -``` - -建议实现 `help` 命令: - -```bash -$ my-tool-cli help -MachineIdTool CLI v1.0.0 -用法: my-tool-cli <命令> [参数] - -命令: - get 获取当前值 - set 设置新值 - help 显示帮助 -``` - -## 插件安装流程 - -1. **下载插件包** - 从 URL 或本地文件获取 ZIP -2. **解压验证** - 解压并验证 plugin.json -3. **下载二进制** - 如果是二进制插件,根据当前平台下载对应二进制 -4. **校验完整性** - 验证 checksum -5. **注册插件** - 将插件信息写入数据库 -6. **加载插件** - 启用插件功能 - -## 插件发布 - -### GitHub Release 发布 - -推荐通过 GitHub Release 发布插件: - -1. 创建 `plugin/` 目录,包含 `plugin.json` 和 `config.json` -2. 在 GitHub Actions 中打包 ZIP -3. 上传到 Release Assets - -```yaml -- name: Package plugin - run: | - mkdir -p plugin-package - cp plugin/plugin.json plugin-package/ - cp plugin/config.json plugin-package/ - cd plugin-package - zip -j ../release/my-plugin.zip plugin.json config.json -``` - -## 开发调试 - -### 本地安装测试 - -1. 打包插件 ZIP -2. 在「插件中心」点击「安装插件」 -3. 选择本地 ZIP 文件安装 - -### 日志调试 - -插件执行日志保存在: -- macOS: `~/Library/Application Support/proxycast/logs/` -- Windows: `%APPDATA%/proxycast/logs/` -- Linux: `~/.local/share/proxycast/logs/` - -## 示例插件 - -参考 [MachineIdTool](https://github.com/aiclientproxy/MachineIdTool) 作为二进制插件的完整示例。 +1. 版本号语义化管理 +2. 发布前做跨平台验证 +3. 提供回滚策略与变更日志 diff --git a/docs/content/08.open-platform/4.connect.md b/docs/content/08.open-platform/4.connect.md index 52f3a006b..ea37b0c35 100644 --- a/docs/content/08.open-platform/4.connect.md +++ b/docs/content/08.open-platform/4.connect.md @@ -1,169 +1,45 @@ -# ProxyCast Connect +--- +title: 开放平台 - Connect +description: 面向服务提供方的一键配置接入能力 +navigation: + icon: i-heroicons-link +--- -ProxyCast Connect 是一套中转商生态合作方案,通过 Deep Link 协议实现一键配置功能。 +# 开放平台 - Connect + +::alert{type="info"} +本页面向生态合作方与平台接入方。普通创作者可跳过。 +:: + +Connect 通过 Deep Link 提供“一键配置”能力,帮助外部平台将配置快速带入 ProxyCast。 ## 核心价值 -| 角色 | 价值 | -|------|------| -| **中转商** | 用户转化率提升、品牌曝光、差异化竞争 | -| **用户** | 一键配置、开箱即用、统一管理多个中转 | -| **ProxyCast** | 用户增长、生态繁荣、市场占有率 | +- 用户:减少手动配置步骤 +- 服务提供方:降低接入门槛 +- 平台:提升配置成功率 -## 工作原理 +## 一键配置流程 -### 一键配置流程 +1. 用户在外部平台点击一键配置 +2. 浏览器打开 `proxycast://` 链接 +3. ProxyCast 弹出确认 +4. 用户确认后完成导入 -1. 用户在中转商后台点击「一键配置 ProxyCast」 -2. 浏览器打开 `proxycast://connect?relay=xxx&key=sk-xxx` 链接 -3. ProxyCast 自动打开,显示确认弹窗 -4. 用户确认后,API Key 自动添加到 ProxyCast -5. 配置完成,可以立即使用 +## 基础协议 -### Deep Link 协议 - -``` +```text proxycast://connect?relay={relay_id}&key={api_key}&name={key_name}&ref={ref_code} ``` | 参数 | 必填 | 说明 | |------|------|------| -| `relay` | ✅ | 中转商 ID(需在 ProxyCast 注册) | +| `relay` | ✅ | 服务方唯一标识 | | `key` | ✅ | API Key | -| `name` | ❌ | Key 名称(默认使用中转商名称) | -| `ref` | ❌ | 推广码(用于统计) | - -### 示例 - -``` -# 基础用法 -proxycast://connect?relay=openrouter&key=sk-or-v1-xxxx - -# 带名称 -proxycast://connect?relay=siliconflow&key=sk-xxxx&name=硅基流动-主账号 - -# 带推广码 -proxycast://connect?relay=myrelay&key=sk-xxxx&ref=promo2024 -``` - -## 中转商注册 - -ProxyCast 是开源软件,中转商通过 **GitHub PR** 方式注册,无需网站注册。 - -### 注册仓库 - -``` -https://github.com/aiclientproxy/connect -``` - -### 注册流程 - -1. **Fork 仓库** - Fork [aiclientproxy/connect](https://github.com/aiclientproxy/connect) -2. **创建配置文件** - 在 `providers/` 目录下创建 `{your-id}.json` -3. **提交 PR** - 提交 Pull Request 到主仓库 -4. **自动化检查** - GitHub Actions 自动验证配置 -5. **社区审核** - 维护者审核并合并 PR -6. **自动发布** - 合并后自动构建 registry.json - -### 配置文件格式 - -```json -{ - "id": "myrelay", - "name": "我的中转站", - "description": "稳定、便宜、快速的 AI API 中转服务", - - "branding": { - "logo": "https://myrelay.com/logo.png", - "color": "#6366f1" - }, - - "links": { - "homepage": "https://myrelay.com", - "register": "https://myrelay.com/register", - "recharge": "https://myrelay.com/recharge", - "docs": "https://docs.myrelay.com", - "status": "https://status.myrelay.com" - }, - - "api": { - "base_url": "https://api.myrelay.com/v1", - "protocol": "openai", - "auth_header": "Authorization", - "auth_prefix": "Bearer " - }, - - "contact": { - "email": "support@myrelay.com", - "telegram": "@myrelay" - }, - - "features": { - "streaming": true, - "models_endpoint": true - }, - - "webhook": { - "callback_url": "https://api.myrelay.com/proxycast/callback", - "secret": "whsec_xxxxxxxxxxxxxxxx" - } -} -``` - -### 字段说明 - -| 字段 | 必填 | 说明 | -|------|------|------| -| `id` | ✅ | 唯一标识,小写字母、数字、连字符 | -| `name` | ✅ | 显示名称 | -| `description` | ✅ | 简短描述,≤100 字 | -| `branding.logo` | ✅ | Logo URL,256x256 PNG | -| `branding.color` | ❌ | 主题色,默认 `#6366f1` | -| `links.homepage` | ✅ | 官网地址 | -| `api.base_url` | ✅ | API 地址(必须 HTTPS) | -| `api.protocol` | ✅ | 协议:`openai` 或 `anthropic` | -| `contact.email` | ✅ | 联系邮箱 | -| `webhook.callback_url` | ❌ | 统计回调地址 | -| `webhook.secret` | ❌ | 回调签名密钥 | - -### 审核标准 - -PR 合并前需满足: - -- JSON Schema 验证通过 -- 文件名与 `id` 字段一致 -- Logo 图片可访问(256x256 PNG) -- API 地址使用 HTTPS -- 官网可访问 -- 联系方式有效 - -## 品牌展示 - -注册成功后,中转商会在 ProxyCast 内获得品牌展示: - -- **扩展市场** - 在中转服务分类中展示 -- **已安装页面** - 显示品牌信息、快捷链接 -- **API Key 管理** - 统一管理该中转商的所有 Key - -## 安全设计 - -### Deep Link 安全 - -| 风险 | 防护措施 | -|------|---------| -| 恶意链接 | relay_id 必须在注册表中存在 | -| Key 泄露 | 确认弹窗显示脱敏 Key,用户确认后才添加 | -| 钓鱼攻击 | 显示中转商完整信息,用户可核实 | - -### 确认弹窗 - -所有通过 Deep Link 添加的 Key 必须经过用户确认,显示: -- 中转商名称和 Logo -- 脱敏后的 API Key -- Key 名称(如果有) -- 安全提示 +| `name` | ❌ | 显示名称 | +| `ref` | ❌ | 推广或渠道标记 | ## 下一步 -- [Connect 接入指南](/open-platform/connect-integration) - 详细的接入步骤 -- [统计回调](/open-platform/connect-webhook) - 配置统计回调追踪推广效果 +- [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 index 2a15f50c1..e8f15bb9b 100644 --- a/docs/content/08.open-platform/5.connect-integration.md +++ b/docs/content/08.open-platform/5.connect-integration.md @@ -1,229 +1,45 @@ -# Connect 接入指南 +--- +title: 开放平台 - Connect 接入指南 +description: 外部服务接入 Connect 的实施步骤与字段规范 +navigation: + icon: i-heroicons-wrench-screwdriver +--- -本文档详细介绍中转商如何接入 ProxyCast Connect,实现一键配置功能。 +# 开放平台 - Connect 接入指南 -## 接入流程 +::alert{type="info"} +本页面向生态合作方技术团队。 +:: -### Step 1: Fork 仓库 +本文档说明如何把你的服务接入 Connect,并完成一键配置联动。 -Fork [aiclientproxy/connect](https://github.com/aiclientproxy/connect) 仓库到你的 GitHub 账号。 +## 接入步骤 -### Step 2: 创建配置文件 +1. 准备服务方元数据 +2. 按规范生成配置文件 +3. 提交审核或接入申请 +4. 联调 Deep Link +5. 灰度发布并观察回调数据 -在 `providers/` 目录下创建 `{your-id}.json` 文件: +## 配置文件建议 -```json -{ - "id": "myrelay", - "name": "我的中转站", - "description": "稳定、便宜、快速的 AI API 中转服务", - - "branding": { - "logo": "https://myrelay.com/logo.png", - "color": "#6366f1" - }, - - "links": { - "homepage": "https://myrelay.com", - "register": "https://myrelay.com/register", - "recharge": "https://myrelay.com/recharge", - "docs": "https://docs.myrelay.com", - "status": "https://status.myrelay.com" - }, - - "api": { - "base_url": "https://api.myrelay.com/v1", - "protocol": "openai", - "auth_header": "Authorization", - "auth_prefix": "Bearer " - }, - - "contact": { - "email": "support@myrelay.com", - "telegram": "@myrelay" - }, - - "features": { - "streaming": true, - "models_endpoint": true - }, - - "webhook": { - "callback_url": "https://api.myrelay.com/proxycast/callback", - "secret": "whsec_xxxxxxxxxxxxxxxx" - } -} -``` +建议包含: -### Step 3: 提交 PR +- 唯一标识与展示信息 +- 官网与文档链接 +- API 基础信息 +- 回调地址(可选) -提交 Pull Request 到主仓库,填写 PR 模板说明你的中转服务。 +## 联调重点 -### Step 4: 等待审核 +1. Deep Link 参数完整性 +2. 用户确认流程体验 +3. 异常输入的兜底处理 +4. 回调状态与业务统计一致性 -GitHub Actions 会自动验证配置文件,维护者会在 1-3 个工作日内审核。 +## 上线前检查 -### Step 5: 合并上线 - -PR 合并后,registry.json 会自动构建,ProxyCast 客户端会自动同步。 - -## 配置字段说明 - -### 必填字段 - -| 字段 | 说明 | 示例 | -|------|------|------| -| `id` | 唯一标识,小写字母、数字、连字符 | `myrelay` | -| `name` | 显示名称 | `我的中转站` | -| `description` | 简短描述,≤100 字 | `稳定、便宜、快速的 AI API 中转服务` | -| `branding.logo` | Logo URL,256x256 PNG | `https://myrelay.com/logo.png` | -| `links.homepage` | 官网地址 | `https://myrelay.com` | -| `api.base_url` | API 地址(必须 HTTPS) | `https://api.myrelay.com/v1` | -| `api.protocol` | 协议类型 | `openai` 或 `anthropic` | -| `contact.email` | 联系邮箱 | `support@myrelay.com` | - -### 可选字段 - -| 字段 | 说明 | 默认值 | -|------|------|--------| -| `branding.color` | 主题色 | `#6366f1` | -| `links.register` | 注册页面 | - | -| `links.recharge` | 充值页面 | - | -| `links.docs` | 文档地址 | - | -| `links.status` | 状态页面 | - | -| `api.auth_header` | 认证头 | `Authorization` | -| `api.auth_prefix` | 认证前缀 | `Bearer ` | -| `contact.telegram` | Telegram 联系方式 | - | -| `contact.discord` | Discord 联系方式 | - | -| `features.streaming` | 是否支持流式响应 | `true` | -| `features.models_endpoint` | 是否提供 /models 端点 | `false` | -| `webhook.callback_url` | 统计回调地址 | - | -| `webhook.secret` | 回调签名密钥 | - | - -## 集成方式 - -### 方式一:直接链接 - -最简单的方式,在用户后台放置链接: - -```html - - 一键配置 ProxyCast - -``` - -### 方式二:JavaScript SDK - -提供更好的用户体验: - -```html - - - -``` - -SDK 功能: -- 自动检测 ProxyCast 是否安装 -- 未安装时显示下载引导 -- 支持回调函数 - -```javascript -ProxyCast.connect({ - relay: 'myrelay', - key: userApiKey, - name: '我的Key', - onSuccess: () => { - showToast('配置成功!'); - }, - onNotInstalled: () => { - showDownloadModal(); - } -}); -``` - -### 方式三:配置文件下载 - -生成 `.proxycast` 配置文件供用户下载: - -```javascript -function downloadConfig(apiKey) { - const config = { - relay: 'myrelay', - key: apiKey, - name: '我的Key' - }; - - const blob = new Blob([JSON.stringify(config)], { type: 'application/json' }); - const url = URL.createObjectURL(blob); - - const a = document.createElement('a'); - a.href = url; - a.download = 'myrelay.proxycast'; - a.click(); -} -``` - -用户双击 `.proxycast` 文件,ProxyCast 自动打开并导入配置。 - -## Deep Link 参数 - -``` -proxycast://connect?relay={relay_id}&key={api_key}&name={key_name}&ref={ref_code} -``` - -| 参数 | 必填 | 说明 | -|------|------|------| -| `relay` | ✅ | 中转商 ID(需在 ProxyCast 注册) | -| `key` | ✅ | API Key | -| `name` | ❌ | Key 名称(默认使用中转商名称) | -| `ref` | ❌ | 推广码(用于统计) | - -### 示例 - -``` -# 基础用法 -proxycast://connect?relay=openrouter&key=sk-or-v1-xxxx - -# 带名称 -proxycast://connect?relay=siliconflow&key=sk-xxxx&name=硅基流动-主账号 - -# 带推广码 -proxycast://connect?relay=myrelay&key=sk-xxxx&ref=promo2024 -``` - -## 品牌素材要求 - -| 素材 | 规格 | 说明 | -|------|------|------| -| Logo | 256x256 PNG | 透明背景,正方形 | -| 主题色 | HEX 色值 | 用于 UI 强调色 | -| 简介 | ≤50 字 | 一句话描述 | -| 详细描述 | ≤200 字 | 详细介绍 | - -## API 要求 - -中转商的 API 需要满足: - -| 要求 | 说明 | -|------|------| -| 协议兼容 | OpenAI 或 Anthropic 协议 | -| HTTPS | 必须使用 HTTPS | -| 模型列表 | 提供 `/models` 端点(可选) | -| 稳定性 | 99% 以上可用性 | - -## 审核标准 - -PR 合并前需满足: - -- JSON Schema 验证通过 -- 文件名与 `id` 字段一致 -- Logo 图片可访问(256x256 PNG) -- API 地址使用 HTTPS -- 官网可访问 -- 联系方式有效 - -## 下一步 - -- [统计回调](/open-platform/connect-webhook) - 配置 Webhook 追踪推广效果 +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 950b18c72..d7279236a 100644 --- a/docs/content/08.open-platform/6.connect-webhook.md +++ b/docs/content/08.open-platform/6.connect-webhook.md @@ -1,198 +1,58 @@ -# 统计回调(Webhook) +--- +title: 开放平台 - 统计回调(Webhook) +description: Connect 回调事件格式与接入建议 +navigation: + icon: i-heroicons-arrow-path-rounded-square +--- -ProxyCast Connect 提供统计回调机制,让中转商追踪推广效果。 +# 开放平台 - 统计回调(Webhook) -## 回调流程 +::alert{type="info"} +本页面向生态合作方技术团队。 +:: -``` -用户点击一键配置 - │ - ▼ -ProxyCast 打开,显示确认弹窗 - │ - ├─── 用户取消 ───▶ 发送回调: status=cancelled - │ - └─── 用户确认 ───▶ Key 添加成功 - │ - ▼ - 发送回调: status=success - │ - ▼ - 中转商收到回调,更新统计 -``` +Webhook 用于回传配置行为结果,帮助你统计接入效果。 -## 配置回调 +## 回调时机 -在 `providers/{id}.json` 中添加 webhook 配置: +常见状态: -```json -{ - "id": "myrelay", - "name": "我的中转站", - - "webhook": { - "callback_url": "https://api.myrelay.com/proxycast/callback" - } -} -``` +- `success`:用户确认并配置成功 +- `cancelled`:用户取消 +- `error`:执行失败 -| 字段 | 必填 | 说明 | -|------|------|------| -| `webhook.callback_url` | ✅ | 回调地址(必须 HTTPS) | - -## 回调请求格式 - -ProxyCast 向中转商发送 POST 请求: +## 请求示例 ```http -POST https://api.myrelay.com/proxycast/callback +POST https://your-domain.com/proxycast/callback Content-Type: application/json -User-Agent: ProxyCast/1.2.0 { "event": "connect", "status": "success", - "relay_id": "myrelay", - "ref": "promo2024", - "key_prefix": "sk-xxxx", - "timestamp": "2026-01-05T12:00:00Z", - "client": { - "version": "1.2.0", - "platform": "macos" - } + "relay_id": "your-relay", + "ref": "campaign-2026", + "timestamp": "2026-02-16T10:00:00Z" } ``` -## 回调字段说明 +## 字段建议 -| 字段 | 说明 | -|------|------| -| `event` | 事件类型:`connect` | -| `status` | 状态:`success`(成功)、`cancelled`(用户取消)、`error`(失败) | -| `relay_id` | 中转商 ID | -| `ref` | 推广码(如果有) | -| `key_prefix` | Key 前缀(脱敏,仅前 7 位) | -| `timestamp` | 事件时间(ISO 8601 格式) | -| `client.version` | ProxyCast 版本 | -| `client.platform` | 平台:`macos`、`windows`、`linux` | -| `error_code` | 错误码(仅 status=error 时) | -| `error_message` | 错误信息(仅 status=error 时) | +- `event`:事件类型 +- `status`:状态值 +- `relay_id`:服务方标识 +- `ref`:渠道标记 +- `timestamp`:事件时间 -## 请求验证 +## 安全建议 -由于 ProxyCast 是开源软件,不使用签名验证。中转商应通过以下方式验证请求: +1. 仅接受 HTTPS 回调 +2. 校验来源与参数完整性 +3. 对回调做幂等处理 +4. 记录失败重试日志 -1. **检查 key_prefix** - 验证该 Key 前缀是否为自己下发的 Key -2. **检查 relay_id** - 确认是自己的中转商 ID -3. **检查 User-Agent** - 确认包含 `ProxyCast` +## 监控建议 -### Express 示例 - -```javascript -app.post('/proxycast/callback', async (req, res) => { - const { relay_id, key_prefix, status, ref } = req.body; - const userAgent = req.headers['user-agent'] || ''; - - // 验证 User-Agent - if (!userAgent.includes('ProxyCast')) { - return res.status(403).json({ error: 'Invalid User-Agent' }); - } - - // 验证 relay_id - if (relay_id !== 'myrelay') { - return res.status(403).json({ error: 'Invalid relay_id' }); - } - - // 验证 key_prefix 是否为自己下发的 Key - const isValidKey = await db.apiKeys.exists({ - key: { $regex: `^${key_prefix}` } - }); - - if (!isValidKey) { - return res.status(403).json({ error: 'Unknown key_prefix' }); - } - - // 处理回调 - if (status === 'success') { - await db.stats.increment({ - relay_id, - ref: ref || 'direct', - date: new Date().toISOString().split('T')[0] - }); - } - - res.json({ received: true }); -}); -``` - -## 重试机制 - -| 重试次数 | 间隔 | 说明 | -|----------|------|------| -| 第 1 次 | 立即 | 首次发送 | -| 第 2 次 | 1 分钟 | 首次失败后 | -| 第 3 次 | 5 分钟 | 第二次失败后 | -| 第 4 次 | 30 分钟 | 第三次失败后 | -| 放弃 | - | 超过 4 次不再重试 | - -成功响应:HTTP 2xx 状态码 - - -## 统计数据示例 - -基于回调数据,中转商可以构建统计面板: - -``` -┌─────────────────────────────────────────────────────────────┐ -│ ProxyCast Connect 统计 2026-01-05 │ -├─────────────────────────────────────────────────────────────┤ -│ │ -│ 今日概览 │ -│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ -│ │ 128 │ │ 115 │ │ 13 │ │ 89.8% │ │ -│ │ 点击次数 │ │ 成功配置 │ │ 用户取消 │ │ 转化率 │ │ -│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ -│ │ -│ 推广码效果 │ -│ ┌─────────────────────────────────────────────────────┐ │ -│ │ 推广码 点击 成功 取消 转化率 │ │ -│ ├─────────────────────────────────────────────────────┤ │ -│ │ promo2024 56 52 4 92.9% │ │ -│ │ twitter 38 33 5 86.8% │ │ -│ │ (无推广码) 34 30 4 88.2% │ │ -│ └─────────────────────────────────────────────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────┘ -``` - -## 隐私保护 - -回调数据遵循最小化原则: - -| 数据 | 是否发送 | 说明 | -|------|----------|------| -| 完整 API Key | ❌ | 仅发送前 7 位前缀 | -| 用户 ID | ❌ | 不发送任何用户标识 | -| 设备 ID | ❌ | 不发送设备标识 | -| IP 地址 | ❌ | 不发送用户 IP | -| 推广码 | ✅ | 用于统计推广效果 | -| 平台信息 | ✅ | 仅操作系统类型 | - -## 错误码 - -当 `status=error` 时,会包含错误信息: - -| 错误码 | 说明 | -|--------|------| -| `invalid_relay` | 中转商 ID 无效 | -| `invalid_key` | API Key 格式无效 | -| `relay_not_found` | 中转商未注册 | -| `network_error` | 网络错误 | -| `internal_error` | 内部错误 | - -## 最佳实践 - -1. **验证 key_prefix** - 检查是否为自己下发的 Key -2. **幂等处理** - 同一事件可能重复发送 -3. **快速响应** - 在 5 秒内返回响应 -4. **异步处理** - 复杂逻辑放到后台队列 \ No newline at end of file +1. 统计成功率与取消率 +2. 跟踪错误类型占比 +3. 区分渠道来源效果 diff --git a/docs/content/index.md b/docs/content/index.md index e885c95fb..56cb460ac 100644 --- a/docs/content/index.md +++ b/docs/content/index.md @@ -1,149 +1,52 @@ --- -title: ProxyCast - 把你的 AI 客户端额度用到任何地方 -description: 一款基于 Tauri 的桌面应用,将 Kiro、Gemini CLI、Qwen 等 AI 客户端凭证转换为标准 OpenAI/Claude 兼容 API +title: ProxyCast 文档中心 +description: 创作类 AI Agent 平台文档,从灵感到发布的一站式指南 navigation: false --- -
+# ProxyCast 文档中心 -
-

ProxyCast

-

把你的 AI 客户端额度用到任何地方

-

一款基于 Tauri 的桌面应用,将 Kiro、Gemini CLI、Qwen 等 AI 客户端凭证转换为标准 OpenAI/Claude 兼容 API

-

凭证池管理 • 智能路由 • 协议转换 • 容错机制

- -
+ProxyCast 是创作类 AI Agent 平台。 +你可以在同一个工作台里完成对话、创作、图片生成、项目沉淀与资源复用。 -
-

- ⚠️ 免责声明: 本工具仅限于个人合法使用,严禁用于非法盈利目的。初衷是帮助用户充分利用已订阅的 AI 服务 Token。 - 查看完整声明 -

-
+## 从这里开始 -## ✨ 核心特性 +1. [概述](/introduction/overview):先了解平台能帮你完成什么 +2. [安装指南](/introduction/installation):安装到本地桌面 +3. [快速开始](/introduction/quickstart):3 步走完首次创作 -
-
-

🔑 凭证池管理

-

支持多种 AI 客户端凭证的统一管理,包括 Kiro、Gemini CLI、Qwen、Claude Code 等,自动检测和刷新 OAuth Token。

-
-
-

🔀 智能路由

-

基于模型名称的请求路由,支持负载均衡、优先级配置、健康检查和自动故障转移。

-
-
-

🛡️ 容错配置

-

内置熔断器、重试机制、超时控制,确保服务稳定性,优雅处理 API 故障。

-
-
-

⚡ 配置切换

-

一键切换 Claude Code、Codex、Gemini CLI 等客户端配置,快速适应不同使用场景。

-
-
-

📊 监控统计

-

实时监控请求统计、Token 使用追踪、详细的请求日志和性能指标。

-
-
-

🔌 API 兼容

-

完整支持 OpenAI Chat Completions API 和 Claude Messages API,无缝集成现有工具。

-
-
+## 九大创作主题 -## 🎯 支持的 Provider +| 主题 | 常见产出 | +|------|----------| +| 通用对话 | 灵感梳理、问题分析、方案草稿 | +| 社媒内容 | 选题、标题、多平台文案 | +| 图文海报 | 主视觉文案、配图方向、活动海报内容 | +| 歌词曲谱 | 主题歌词、段落续写、风格改编 | +| 知识探索 | 知识卡片、结构化总结、学习资料 | +| 计划规划 | 周计划、项目拆解、执行清单 | +| 办公文档 | 报告、方案、邮件、纪要 | +| 短视频 | 脚本、分镜、口播稿 | +| 小说创作 | 设定、章节、人物对白 | -| Provider | 类型 | 认证方式 | 说明 | -|----------|------|----------|------| -| Kiro Claude | OAuth | 自动刷新 | AWS Kiro IDE 的 Claude 凭证 | -| Gemini CLI | OAuth | 自动刷新 | Google Gemini CLI 凭证 | -| Qwen (通义千问) | OAuth | 自动刷新 | 阿里云通义千问凭证 | -| OpenAI Custom | API Key | 手动配置 | 自定义 OpenAI 兼容服务 | -| Claude Custom | API Key | 手动配置 | 自定义 Claude 兼容服务 | +## 常用功能入口 -## 🚀 快速开始 +- [首页与工作台](/user-guide/dashboard) +- [资源库](/user-guide/resources) +- [图片生成与编辑](/user-guide/image-generation) +- [设置](/user-guide/settings) +- [插件中心](/user-guide/plugins) -### 1. 下载安装 +## 进阶能力(可选) -从 [GitHub Tags](https://github.com/aiclientproxy/proxycast/tags) 下载适合你系统的安装包。 +当你需要更深度的模型接入或工程能力时,可继续阅读: -### 2. 加载凭证 +- [Provider 概述](/providers/overview) +- [API 参考](/api-reference/overview) +- [开放平台](/open-platform/overview) +- [故障排查](/troubleshooting/common-issues) -ProxyCast 会自动检测本地的 AI 客户端凭证文件: +## 免责声明 -``` -~/.kiro/credentials.json # Kiro Claude -~/.config/gemini-cli/oauth_creds.json # Gemini CLI -~/.config/qwen/credentials.json # Qwen -``` - -### 3. 启动服务 - -点击仪表盘的「启动服务」按钮,API Server 默认运行在 `http://127.0.0.1:8999`。 - -### 4. 测试 API - -```bash -curl http://127.0.0.1:8999/v1/chat/completions \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer your-api-key" \ - -d '{ - "model": "claude-sonnet-4-20250514", - "messages": [{"role": "user", "content": "Hello!"}] - }' -``` - -## 📖 文档导航 - - - -## 🌐 开放平台 - - - -## 🤝 社区与支持 - -- **GitHub Issues**: [报告问题](https://github.com/aiclientproxy/proxycast/issues) -- **GitHub Discussions**: [参与讨论](https://github.com/aiclientproxy/proxycast/discussions) - -## 📄 开源协议 - -ProxyCast 采用 [MIT License](https://github.com/aiclientproxy/proxycast/blob/main/LICENSE) 开源。 - -
+请在合法合规前提下使用本产品。 +完整说明见 [免责声明](/legal/disclaimer)。 diff --git a/docs/product-overview.md b/docs/product-overview.md index a02bde669..428c2d134 100644 --- a/docs/product-overview.md +++ b/docs/product-overview.md @@ -1,285 +1,126 @@ -# ProxyCast AI 创作工作站 - 产品介绍 +# ProxyCast 创作类 AI Agent 平台 - 产品介绍 -> 版本: 1.0.0 -> 更新: 2026-02-04 -> 用途: 客户演示、产品介绍 +> 版本: 2.0.0 +> 更新: 2026-02-16 +> 用途: 产品介绍、客户演示、团队对齐 --- ## 一、产品定位 -**中文创作者的本地 AI 工作站** +**面向创作者的一站式 AI Agent 平台** -核心理念:**AI 增强人,而非替代人** +ProxyCast 不是单点工具,而是一条完整创作链路: -设计原则: -- **对话即创作** - 用自然语言描述需求,AI 理解意图 -- **一个对话,多种画布** - 同一对话可切换不同创作画布 -- **人机协作** - AI 建议透明可审查,用户掌控最终决策 +- 从灵感讨论开始 +- 到文本与图片产出 +- 再到项目沉淀与长期复用 + +核心理念:**让创作更快,但主导权始终在创作者手中**。 --- -## 二、六大创作画布 +## 二、九大创作主题 -ProxyCast 提供 **6 种专业画布**,覆盖主流内容创作场景: - -| 画布类型 | 图标 | 适用场景 | 核心能力 | -|---------|------|---------|---------| -| **通用对话** | 💬 | 日常问答、头脑风暴 | 智能对话、知识问答 | -| **社媒内容** | 📱 | 公众号、小红书、知乎 | 6 步工作流、多平台适配 | -| **图文海报** | 🖼️ | 营销海报、社交图片 | 可视化设计、多尺寸导出 | -| **音乐歌词** | 🎵 | 歌词创作、简谱编曲 | 旋律学习、Suno 导出 | -| **短剧脚本** | 🎬 | 短视频、微短剧 | 场景管理、对白编辑 | -| **小说创作** | 📖 | 网文、长篇小说 | 章节管理、大纲规划 | +| 主题 | 典型任务 | 常见产出 | +|------|----------|----------| +| 通用对话 | 灵感发散、问题梳理 | 对话结论、行动草案 | +| 社媒内容 | 选题、标题、正文 | 多平台文案 | +| 图文海报 | 活动视觉、品牌传播 | 海报文案、配图方案 | +| 歌词曲谱 | 主题创作、段落续写 | 歌词草稿、结构框架 | +| 知识探索 | 学习拆解、资料整合 | 知识卡片、总结笔记 | +| 计划规划 | 目标拆解、执行跟踪 | 周计划、任务清单 | +| 办公文档 | 报告、邮件、纪要 | 可交付文档 | +| 短视频 | 口播、脚本、分镜 | 拍摄脚本、内容提纲 | +| 小说创作 | 世界观、人物、章节 | 连载章节、剧情草案 | --- -## 三、各画布详细能力 +## 三、创作流程 -### 3.1 📱 社媒内容画布 +### 1) 对话定方向 -**6 步引导式创作流程**: +先用 AI Agent 明确目标、受众和输出形式。 -``` -选题研究 → 竞品分析 → 大纲生成 → 初稿写作 → 多轮优化 → 平台发布 - 10% 20% 40% 70% 90% 100% -``` +### 2) 生成首稿 -**多平台一键适配**: +按主题工作流生成内容初稿,快速得到可迭代版本。 -| 平台 | 特点 | 自动处理 | -|-----|------|---------| -| 公众号 | 深度长文 | 外链转二维码、排版优化 | -| 小红书 | 种草短文 | emoji 风格、话题标签 | -| 知乎 | 专业问答 | 引用来源、脚注格式 | -| 小说平台 | 章节连载 | 作者说、字数统计 | +### 3) 图片与素材补齐 -**专业 Agent 协作**: +在图片生成功能中完成视觉产出,支持参考图参与编辑。 -| Agent | 功能 | -|-------|------| -| 选题 Agent | 热点分析、选题推荐 | -| 标题 Agent | 爆款标题优化 | -| 开头 Agent | 吸睛开场设计 | -| 互动 Agent | 评论区引导 | -| 金句 Agent | 金句提取与优化 | +### 4) 资产沉淀 - - -### 3.2 🎵 音乐歌词画布 - -**支持歌曲类型**: - -| 类型 | 说明 | -|-----|------| -| 流行 (pop) | 主流流行音乐 | -| 民谣 (folk) | 抒情民谣 | -| 摇滚 (rock) | 摇滚乐 | -| 古风 (guofeng) | 中国风 | -| 说唱 (rap) | Hip-hop | -| R&B | 节奏蓝调 | -| 电子 (electronic) | 电子音乐 | - -**三种创作模式**: - -| 模式 | 说明 | 适合人群 | -|-----|------|---------| -| 教练模式 | AI 逐段引导创作 | 新手创作者 | -| 快速模式 | AI 直接生成完整歌词 | 追求效率 | -| 混合模式 | AI 生成框架,用户填充细节 | 专业创作者 | - -**四种视图模式**: -- 🎤 纯歌词视图 - 专注歌词编辑 -- 🎼 简谱视图 - 数字简谱展示 -- 🎸 吉他谱视图 - 和弦指法图 -- 🎹 钢琴谱视图 - 钢琴键位标注 - -**旋律学习功能**: -- 上传 MIDI/MP3 参考曲目 -- AI 分析旋律特征(调式、节奏、音程) -- 智能借鉴风格创作新曲 -- 一致性评分(结构、风格、旋律适配度) - -**导出格式**: -- PDF 歌词本 -- MIDI 文件 -- MusicXML -- **Suno 提示词** - 直接生成 AI 音乐 -- **Tunee 素材包** - 对话素材导出 - - - -### 3.3 🖼️ 图文海报画布 - -**基于 Fabric.js 的专业设计器**: -- 文字元素 - 多字体、多样式 -- 图片元素 - 裁剪、滤镜 -- 形状元素 - 矩形、圆形、线条 -- 背景元素 - 纯色、渐变、图片 - -**专业功能**: -- 图层管理 - 上移、下移、置顶、置底 -- 对齐工具 - 左对齐、居中、右对齐、分布 -- 多页面支持 - 批量设计 - -**预设尺寸**: - -| 平台 | 比例 | 像素 | -|-----|------|-----| -| 小红书封面 | 3:4 | 1080×1440 | -| 公众号头图 | 2.35:1 | 900×383 | -| 朋友圈 | 1:1 | 1080×1080 | -| 自定义 | 任意 | 自定义 | - -**导出格式**:PNG、JPEG、PDF - - - -### 3.4 🎬 短剧脚本画布 - -**专业剧本格式**: -- 场景管理 - 内景/外景、日/夜/晨/昏 -- 角色对白编辑 -- 表演指示标注(括号内) -- 情绪标记 - -**结构化编辑示例**: - -``` -第1场:咖啡厅(日) -*女主角坐在窗边,若有所思* - -女主:(叹气)为什么事情总是这样... -男主:(走近)你还好吗? -``` - -**场景元素**: -- 场景编号 -- 地点描述 -- 时间设定 -- 场景描述 -- 对白列表 - - - -### 3.5 📖 小说创作画布 - -**长篇创作支持**: -- 章节管理 - 拖拽排序、批量操作 -- 大纲树形结构 - 多级展开 -- 字数统计 - 章节/全书 -- 版本历史 - 随时回溯 - -**章节状态**: -- 草稿 (draft) - 创作中 -- 已完成 (completed) - 定稿 - -**创作辅助**: -- 世界观设定 -- 角色档案 -- 剧情线索追踪 -- AI 续写建议 +把文档、图片、语音、视频统一沉淀到项目资源库,便于复用。 --- -## 四、通用能力 +## 四、典型用户场景 -### 4.1 人设系统 +### 场景 1:自媒体日更 -**人设配置项**: -- 名称与简介 -- 写作风格描述 -- 语气设定 -- 目标读者画像 -- 禁用词列表 -- 偏好词列表 -- 示例文章(供 AI 学习) -- 适用平台 +- 早上 10 分钟定选题 +- 中午完成首稿与配图 +- 下午发布并沉淀素材用于复盘 -**使用方式**: -- 项目级默认人设 -- 话题级人设覆盖 -- 多人设快速切换 +### 场景 2:短视频团队周更 +- 统一脚本结构 +- 批量生成口播与镜头要点 +- 版本资产留档,便于协同交接 +### 场景 3:小说连载 -### 4.2 素材库 - -**支持素材类型**: -- 文档 (document) - PDF、Word、Markdown -- 图片 (image) - PNG、JPEG、GIF -- 文本 (text) - 纯文本片段 -- 数据 (data) - Excel、CSV -- 链接 (link) - 网页引用 - -**管理功能**: -- 标签分类 -- 描述备注 -- 预览查看 -- 写作时一键引用 - -### 4.3 项目管理 - -**层级关系**: -``` -项目 (Project) - 内容容器 - └── 话题 (Topic) - 内容载体 - └── 消息 (Message) - 对话记录 - └── 产出物 (Artifact) - 生成内容 -``` - -**项目类型**: -- general - 通用 -- social - 社媒内容 -- novel - 小说创作 -- drama - 短剧脚本 -- document - 办公文档 -- paper - 学术论文 -- music - 歌词曲谱 -- poster - 图文海报 +- 持续维护设定与角色 +- 章节迭代不丢上下文 +- 连载节奏稳定、可持续推进 +### 场景 4:品牌与运营活动 +- 快速生成多套文案与视觉方向 +- 统一保存历史版本与素材 +- 缩短从想法到上线的周期 --- -## 五、产品亮点 +## 五、产品价值 -| 特性 | 说明 | -|-----|------| -| **本地运行** | 数据安全,无需上传云端 | -| **多画布** | 6 种专业画布,覆盖主流场景 | -| **人机协作** | AI 建议透明可审查,用户掌控最终决策 | -| **多平台适配** | 一份内容,自动适配多个发布平台 | -| **专业导出** | 支持 Suno、Tunee 等 AI 音乐平台 | -| **项目化管理** | 人设/素材/排版 项目级复用 | +| 价值 | 体现 | +|------|------| +| 创作效率提升 | 同一处完成对话、出稿、出图、沉淀 | +| 结果可复用 | 项目化管理历史内容与素材 | +| 团队协作更顺畅 | 上下文和资产都可追溯 | +| 门槛更低 | 先用再学,按需开启进阶能力 | --- ## 六、目标用户 -| 用户群体 | 典型场景 | -|---------|---------| -| 自媒体创作者 | 公众号、小红书、知乎日更 | -| 音乐创作者 | 歌词创作、编曲辅助 | -| 短剧编剧 | 微短剧、短视频脚本 | -| 网文作者 | 小说连载、大纲规划 | -| 设计师 | 营销海报、社交图片 | -| 内容运营 | 品牌文案、多平台分发 | +- 自媒体与内容创作者 +- 短视频脚本团队 +- 小说与剧情创作者 +- 品牌运营与营销团队 +- 需要长期沉淀创作资产的个人与小团队 --- -## 七、技术架构(简述) +## 七、进阶能力(可选) -- **前端**:React + TypeScript + Vite + TailwindCSS -- **后端**:Rust + Tauri -- **数据库**:SQLite(本地存储) -- **AI 框架**:集成 Aster-Rust Agent 框架 +对于开发者或自动化场景,ProxyCast 还提供: + +- 本地 API 接入 +- MCP 工具扩展 +- 插件扩展体系 + +普通创作者不需要先配置这些能力,也能完成完整创作流程。 --- -## 相关文档 +## 八、推荐阅读 -- [社媒内容创作 PRD](prd/ai-content-creator.md) -- [SheMedia 工作流设计](prd/shemei/workflow.md) -- [画布系统架构](../src/components/content-creator/canvas/README.md) -- [统一内容系统](prd/unified-content-system.md) +- [文档首页](content/index.md) +- [快速开始](content/01.introduction/3.quickstart.md) +- [首页与工作台](content/02.user-guide/1.dashboard.md) +- [资源库](content/02.user-guide/14.resources.md) +- [图片生成与编辑](content/02.user-guide/15.image-generation.md) diff --git a/docs/three-stage-workflow-guide.md b/docs/three-stage-workflow-guide.md deleted file mode 100644 index da9e65730..000000000 --- a/docs/three-stage-workflow-guide.md +++ /dev/null @@ -1,348 +0,0 @@ -# 三阶段工作流使用指南 - -基于 planning-with-files 的核心理念,ProxyCast 和 aster-rust 现已集成完整的三阶段工作流系统,解决 AI Agent 的上下文丢失、目标漂移、错误重复问题。 - -## 核心理念 - -``` -Context Window = RAM (易失性,有限) -Filesystem = Disk (持久性,无限) - -→ 重要信息都写入磁盘存储 -``` - -## 三阶段工作流 - -### 1. Pre-Action 阶段 -- **目的**: 执行前的上下文刷新和检查 -- **功能**: - - 读取任务计划和历史记忆 - - 检查 3次错误协议 - - 刷新目标和上下文 - -### 2. Action 阶段 -- **目的**: 执行实际操作 -- **功能**: - - 记录操作过程 - - 跟踪视觉操作计数 - - 监控执行状态 - -### 3. Post-Action 阶段 -- **目的**: 操作后的状态更新和学习 -- **功能**: - - 应用 2-Action 规则 - - 记录错误和解决方案 - - 更新进度和发现 - -## 核心文件系统 - -### 三文件模式 - -1. **task_plan.md** - 任务计划和阶段跟踪 -2. **findings.md** - 研究发现和重要信息 -3. **progress.md** - 会话进度日志 - -### 自动化规则 - -- **2-Action 规则**: 每2次视觉操作后立即保存发现 -- **3次错误协议**: 永不重复相同的失败操作 -- **上下文刷新**: 重要决策前重新阅读计划文件 - -## ProxyCast 使用方法 - -### 1. 基础集成 - -```typescript -import { useWorkflowIntegration } from './hooks/useWorkflowIntegration'; - -function ChatComponent({ sessionId }: { sessionId: string }) { - const [workflowState, workflowActions] = useWorkflowIntegration({ - sessionId, - enableAutoWorkflow: true, - workflowThreshold: 5, // 5条消息后自动启用 - }); - - // 初始化工作流 - const handleInitWorkflow = async () => { - await workflowActions.initializeWorkflow( - '数据分析项目', - '帮助用户分析销售数据并生成报告' - ); - }; - - // 处理消息发送 - const handleSendMessage = async (content: string) => { - // Pre-Action: 获取上下文 - const preActionInfo = await workflowActions.handlePreMessage(content, 'user'); - - // Action: 发送消息 - const response = await sendMessageToAPI(content); - - // Post-Action: 更新状态 - const postActionInfo = await workflowActions.handlePostMessage(response); - - return { response, preActionInfo, postActionInfo }; - }; - - return ( -
- - {/* 其他聊天组件 */} -
- ); -} -``` - -### 2. 手动记录重要信息 - -```typescript -// 记录重要发现 -await workflowActions.recordFinding( - '关键数据洞察', - '发现销售数据中存在明显的季节性趋势,Q4销量比Q1高出40%', - ['数据分析', '季节性', '重要'] -); - -// 记录决策 -await workflowActions.recordDecision( - '使用时间序列分析', - '考虑到数据的季节性特征,决定采用ARIMA模型进行预测分析' -); - -// 更新阶段状态 -await workflowActions.updatePhaseStatus(2, 'complete', '数据清洗和初步分析已完成'); -``` - -### 3. 工具使用集成 - -```typescript -// 工具使用前后自动记录 -const handleToolUse = async (toolName: string, params: any) => { - try { - const result = await executeTool(toolName, params); - - // 自动记录成功的工具使用 - await workflowActions.handleToolUse(toolName, params, result); - - return result; - } catch (error) { - // 自动记录失败的工具使用 - await workflowActions.handleToolUse(toolName, params, '', error.message); - throw error; - } -}; -``` - -## aster-rust 使用方法 - -### 1. 基础工具集成 - -```rust -use aster::tools::{ThreeStageWorkflowTool, WorkflowIntegratedTool, ToolHookManager}; - -// 创建带钩子的工具 -let hook_manager = Arc::new(ToolHookManager::new(true)); -hook_manager.register_default_hooks().await; - -let workflow_tool = WorkflowIntegratedTool::default() - .with_hook_manager(hook_manager.clone()); - -// 注册到工具注册表 -registry.register(Box::new(workflow_tool)); -``` - -### 2. 三阶段工作流工具 - -```rust -// 初始化工作流 -let init_params = serde_json::json!({ - "action": "init_workflow", - "project_name": "Rust项目重构" -}); - -let result = three_stage_tool.execute(init_params, &context).await?; - -// 记录发现 -let finding_params = serde_json::json!({ - "action": "add_finding", - "finding": "发现代码中存在大量重复逻辑,需要提取公共模块" -}); - -let result = three_stage_tool.execute(finding_params, &context).await?; - -// 应用 2-Action 规则 -let rule_params = serde_json::json!({ - "action": "apply_2action_rule", - "finding": "通过代码审查发现了性能瓶颈" -}); - -let result = three_stage_tool.execute(rule_params, &context).await?; -``` - -### 3. 自定义钩子 - -```rust -use aster::tools::hooks::{ToolHook, HookContext, HookTrigger}; - -#[derive(Debug)] -struct CustomWorkflowHook { - name: String, -} - -#[async_trait] -impl ToolHook for CustomWorkflowHook { - fn name(&self) -> &str { - &self.name - } - - fn description(&self) -> &str { - "自定义工作流钩子" - } - - async fn execute(&self, context: &HookContext) -> Result<()> { - // 自定义钩子逻辑 - tracing::info!("执行自定义工作流钩子: {}", context.tool_name); - Ok(()) - } -} - -// 注册自定义钩子 -hook_manager.register_hook( - HookTrigger::PreExecution, - Box::new(CustomWorkflowHook { - name: "custom_workflow_hook".to_string(), - }) -).await; -``` - -## 最佳实践 - -### 1. 工作流初始化时机 -- **自动模式**: 消息数量达到阈值时自动初始化 -- **手动模式**: 用户明确表达复杂任务意图时初始化 -- **智能模式**: 结合消息内容分析和用户行为模式 - -### 2. 记忆管理策略 -- **及时记录**: 重要发现立即保存,不要依赖记忆 -- **分类标记**: 使用标签系统便于后续检索 -- **定期清理**: 自动归档过期记忆,保持系统性能 - -### 3. 错误处理原则 -- **详细记录**: 记录错误的完整上下文和尝试的解决方案 -- **避免重复**: 严格执行 3次错误协议 -- **学习改进**: 从错误中提取经验,更新工作流程 - -### 4. 阶段管理技巧 -- **明确划分**: 每个阶段有清晰的目标和完成标准 -- **及时更新**: 阶段状态变化时立即更新 -- **灵活调整**: 根据实际情况调整阶段计划 - -## 故障排除 - -### 常见问题 - -1. **工作流未自动初始化** - - 检查 `enableAutoWorkflow` 设置 - - 确认消息数量是否达到阈值 - - 查看控制台错误信息 - -2. **钩子未触发** - - 验证钩子管理器是否正确初始化 - - 检查钩子条件是否匹配 - - 确认钩子是否已启用 - -3. **记忆保存失败** - - 检查会话ID是否有效 - - 验证存储权限 - - 查看后端服务状态 - -4. **性能问题** - - 定期清理过期记忆 - - 限制单次记录的内容长度 - - 优化钩子执行频率 - -### 调试技巧 - -```typescript -// 启用详细日志 -const [workflowState, workflowActions] = useThreeStageWorkflow({ - sessionId, - debugMode: true, // 启用调试模式 -}); - -// 获取详细统计信息 -const stats = await workflowActions.getSessionStats(); -console.log('工作流统计:', stats); - -// 检查记忆状态 -const memoryStats = await ContextMemoryAPI.getMemoryStats(sessionId); -console.log('记忆统计:', memoryStats); -``` - -## 扩展开发 - -### 自定义钩子规则 - -```typescript -// 创建自定义钩子规则 -const customRule = ToolHooksAPI.createCustomRule( - 'code-review-reminder', - '代码审查提醒', - '检测到代码相关操作时提醒进行代码审查', - 'post_tool_use', - [ - { message_contains: '代码' }, - { tool_name_contains: 'edit' }, - ], - [ - { - save_finding: { - title: '代码审查提醒', - content: '建议对修改的代码进行审查', - tags: ['代码审查', '提醒'], - priority: 3, - }, - }, - ], - 50 // 优先级 -); - -await ToolHooksAPI.addHookRule(customRule); -``` - -### 自定义记忆类型 - -```typescript -// 扩展记忆文件类型 -type ExtendedMemoryFileType = MemoryFileType | 'code_review' | 'test_results'; - -// 保存自定义类型记忆 -await ContextMemoryAPI.saveMemoryEntry({ - session_id: sessionId, - file_type: 'code_review' as any, - title: '代码审查结果', - content: '审查发现3个潜在问题...', - tags: ['代码审查', '质量'], - priority: 4, -}); -``` - -## 总结 - -三阶段工作流系统为 ProxyCast 和 aster-rust 提供了强大的上下文管理和自动化能力: - -- **解决核心问题**: 上下文丢失、目标漂移、错误重复 -- **自动化工程**: Pre-Action → Action → Post-Action 流程 -- **持久化记忆**: 基于文件系统的可靠存储 -- **智能学习**: 错误跟踪和经验积累 -- **灵活扩展**: 支持自定义钩子和记忆类型 - -通过正确使用这个系统,可以显著提升 AI Agent 的工作效率和可靠性,让复杂任务的执行更加有序和可控。 \ No newline at end of file diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index c8fe03ef3..7d8d4248f 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -203,6 +203,7 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "aster" version = "0.11.0" +source = "git+https://github.com/astercloud/aster-rust?tag=v0.11.0#c4a9c40b48bcb0c77375b10ccb1313366fb4e7ba" dependencies = [ "ahash", "anyhow", @@ -291,6 +292,14 @@ dependencies = [ "zip", ] +[[package]] +name = "aster-models" +version = "0.12.0" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "async-broadcast" version = "0.7.2" @@ -6621,7 +6630,7 @@ dependencies = [ [[package]] name = "proxycast" -version = "0.67.0" +version = "0.68.0" dependencies = [ "anyhow", "arboard", @@ -6719,7 +6728,7 @@ dependencies = [ [[package]] name = "proxycast-agent" -version = "0.67.0" +version = "0.68.0" dependencies = [ "aster", "async-trait", @@ -6742,7 +6751,7 @@ dependencies = [ [[package]] name = "proxycast-config" -version = "0.67.0" +version = "0.68.0" dependencies = [ "async-trait", "parking_lot", @@ -6758,8 +6767,9 @@ dependencies = [ [[package]] name = "proxycast-core" -version = "0.67.0" +version = "0.68.0" dependencies = [ + "aster-models", "async-trait", "axum 0.7.9", "bytes", @@ -6797,7 +6807,7 @@ dependencies = [ [[package]] name = "proxycast-credential" -version = "0.67.0" +version = "0.68.0" dependencies = [ "axum 0.7.9", "chrono", @@ -6828,7 +6838,7 @@ dependencies = [ [[package]] name = "proxycast-infra" -version = "0.67.0" +version = "0.68.0" dependencies = [ "chrono", "dashmap 5.5.3", @@ -6848,7 +6858,7 @@ dependencies = [ [[package]] name = "proxycast-mcp" -version = "0.67.0" +version = "0.68.0" dependencies = [ "async-trait", "glob", @@ -6879,7 +6889,7 @@ dependencies = [ [[package]] name = "proxycast-processor" -version = "0.67.0" +version = "0.68.0" dependencies = [ "async-trait", "parking_lot", @@ -6898,7 +6908,7 @@ dependencies = [ [[package]] name = "proxycast-providers" -version = "0.67.0" +version = "0.68.0" dependencies = [ "anyhow", "async-stream", @@ -6950,7 +6960,7 @@ dependencies = [ [[package]] name = "proxycast-server" -version = "0.67.0" +version = "0.68.0" dependencies = [ "async-stream", "axum 0.7.9", @@ -6989,7 +6999,7 @@ dependencies = [ [[package]] name = "proxycast-server-utils" -version = "0.67.0" +version = "0.68.0" dependencies = [ "axum 0.7.9", "futures", @@ -7004,7 +7014,7 @@ dependencies = [ [[package]] name = "proxycast-services" -version = "0.67.0" +version = "0.68.0" dependencies = [ "anyhow", "aster", @@ -7045,7 +7055,7 @@ dependencies = [ [[package]] name = "proxycast-skills" -version = "0.67.0" +version = "0.68.0" dependencies = [ "async-trait", "dirs 5.0.1", @@ -7061,7 +7071,7 @@ dependencies = [ [[package]] name = "proxycast-terminal" -version = "0.67.0" +version = "0.68.0" dependencies = [ "async-trait", "base64 0.22.1", @@ -7088,7 +7098,7 @@ dependencies = [ [[package]] name = "proxycast-websocket" -version = "0.67.0" +version = "0.68.0" dependencies = [ "axum 0.7.9", "chrono", @@ -12114,3 +12124,7 @@ dependencies = [ "syn 2.0.114", "winnow 0.7.14", ] + +[[patch.unused]] +name = "aster-core" +version = "0.12.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 1779c3b28..35d2d0aef 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -3,7 +3,7 @@ members = ["crates/*"] resolver = "2" [workspace.package] -version = "0.67.0" +version = "0.68.0" edition = "2021" authors = ["you"] repository = "https://github.com/aiclientproxy/proxycast" @@ -121,6 +121,8 @@ enigo = "0.3" # CI/CD: git = "https://github.com/astercloud/aster-rust", tag = "v0.11.0" # aster = { path = "../../../astercloud/aster-rust/crates/aster" } aster = { git = "https://github.com/astercloud/aster-rust", tag = "v0.11.0" } +# CI/CD: aster-models = { git = "https://github.com/astercloud/aster-rust", tag = "v0.12.0" } +aster-models = { path = "../../../astercloud/aster-rust/crates/aster-models" } # MCP (Model Context Protocol) rmcp = { version = "0.12.0", features = ["client", "transport-io", "transport-child-process"] } @@ -183,7 +185,7 @@ version = "2.4" [package] name = "proxycast" -version = "0.67.0" +version = "0.68.0" description = "AI API Proxy Desktop App" authors = ["you"] edition = "2021" diff --git a/src-tauri/crates/agent/src/aster_state.rs b/src-tauri/crates/agent/src/aster_state.rs index 4ddfcf296..80e101393 100644 --- a/src-tauri/crates/agent/src/aster_state.rs +++ b/src-tauri/crates/agent/src/aster_state.rs @@ -26,6 +26,7 @@ use aster::agents::{Agent, SessionConfig}; use aster::model::ModelConfig; #[cfg(test)] use aster::skills::{global_registry, load_skills_from_directory, SkillSource}; +use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use tokio::sync::RwLock; use tokio_util::sync::CancellationToken; @@ -61,6 +62,10 @@ pub struct AsterAgentState { current_provider_config: Arc>>, /// 凭证桥接器 credential_bridge: CredentialBridge, + /// Agent 初始化状态缓存(避免每次都获取锁) + initialized_cache: Arc, + /// Provider 配置状态缓存(避免每次都获取锁) + provider_configured_cache: Arc, } impl Default for AsterAgentState { @@ -77,6 +82,8 @@ impl AsterAgentState { cancel_tokens: Arc::new(RwLock::new(std::collections::HashMap::new())), current_provider_config: Arc::new(RwLock::new(None)), credential_bridge: CredentialBridge::new(), + initialized_cache: Arc::new(AtomicBool::new(false)), + provider_configured_cache: Arc::new(AtomicBool::new(false)), } } @@ -91,6 +98,11 @@ impl AsterAgentState { /// # 参数 /// - `db`: 数据库连接,用于创建 SessionStore pub async fn init_agent_with_db(&self, db: &DbConnection) -> Result<(), String> { + // 快速路径:检查缓存 + if self.initialized_cache.load(Ordering::Relaxed) { + return Ok(()); + } + let mut agent_guard = self.agent.write().await; if agent_guard.is_none() { // 创建 SessionStore @@ -116,10 +128,16 @@ impl AsterAgentState { crate::reload_proxycast_skills(); *agent_guard = Some(agent); + + // 更新缓存 + self.initialized_cache.store(true, Ordering::Relaxed); + tracing::info!( "[AsterAgent] Agent 初始化成功,已注入 ProxyCastSessionStore、ProxyCast 身份和 Skills" ); } else { + // 更新缓存 + self.initialized_cache.store(true, Ordering::Relaxed); tracing::debug!("[AsterAgent] Agent 已初始化,跳过"); } Ok(()) @@ -196,6 +214,10 @@ impl AsterAgentState { let mut config_guard = self.current_provider_config.write().await; *config_guard = Some(config.clone()); + // 更新缓存 + self.provider_configured_cache + .store(true, Ordering::Relaxed); + tracing::info!( "[AsterAgent] Provider 配置成功: {} / {}", config.provider_name, @@ -256,6 +278,10 @@ impl AsterAgentState { let mut config_guard = self.current_provider_config.write().await; *config_guard = Some(config); + // 更新缓存 + self.provider_configured_cache + .store(true, Ordering::Relaxed); + // 记录凭证使用 if let Err(e) = self .credential_bridge @@ -362,12 +388,26 @@ impl AsterAgentState { pub async fn clear_provider_config(&self) { let mut config_guard = self.current_provider_config.write().await; *config_guard = None; + + // 更新缓存 + self.provider_configured_cache + .store(false, Ordering::Relaxed); + tracing::info!("[AsterAgent] Provider 配置已清除"); } /// 检查 Provider 是否已配置 pub async fn is_provider_configured(&self) -> bool { - self.current_provider_config.read().await.is_some() + // 快速路径:检查缓存 + if self.provider_configured_cache.load(Ordering::Relaxed) { + return true; + } + + // 慢速路径:检查实际状态 + let result = self.current_provider_config.read().await.is_some(); + self.provider_configured_cache + .store(result, Ordering::Relaxed); + result } /// 获取 Agent 的只读引用并执行同步操作 @@ -511,7 +551,15 @@ impl AsterAgentState { /// 检查 Agent 是否已初始化 pub async fn is_initialized(&self) -> bool { - self.agent.read().await.is_some() + // 快速路径:检查缓存 + if self.initialized_cache.load(Ordering::Relaxed) { + return true; + } + + // 慢速路径:检查实际状态 + let result = self.agent.read().await.is_some(); + self.initialized_cache.store(result, Ordering::Relaxed); + result } } diff --git a/src-tauri/crates/agent/src/session_store.rs b/src-tauri/crates/agent/src/session_store.rs index adba3d1df..758a504be 100644 --- a/src-tauri/crates/agent/src/session_store.rs +++ b/src-tauri/crates/agent/src/session_store.rs @@ -127,6 +127,29 @@ pub fn get_session_sync(db: &DbConnection, session_id: &str) -> Result = messages + .into_iter() + .map(|message| convert_agent_message(&message)) + .collect(); + + // 测试序列化 + let test_content = vec![ + TauriMessageContent::Text { + text: "Hello".to_string(), + }, + TauriMessageContent::Thinking { + text: "Thinking...".to_string(), + }, + ]; + if let Ok(json) = serde_json::to_string(&test_content) { + tracing::info!("[SessionStore] 测试序列化: {}", json); + } + + // 调试日志:序列化后的 JSON + if let Ok(json) = serde_json::to_string_pretty(&tauri_messages) { + tracing::debug!("[SessionStore] 序列化消息 JSON:\n{}", json); + } + Ok(SessionDetail { id: session.id, name: session.title.unwrap_or_else(|| "未命名".to_string()), @@ -136,10 +159,7 @@ pub fn get_session_sync(db: &DbConnection, session_id: &str) -> Result Result<(), St /// 将 AgentMessage 转换为 TauriMessage fn convert_agent_message(message: &AgentMessage) -> TauriMessage { - let content = match &message.content { + let mut content = match &message.content { MessageContent::Text(text) => vec![TauriMessageContent::Text { text: text.clone() }], MessageContent::Parts(parts) => parts .iter() @@ -184,14 +204,33 @@ fn convert_agent_message(message: &AgentMessage) -> TauriMessage { .collect(), }; + // 添加 reasoning_content 作为 thinking 类型 + if let Some(reasoning) = &message.reasoning_content { + content.insert( + 0, + TauriMessageContent::Thinking { + text: reasoning.clone(), + }, + ); + } + let timestamp = chrono::DateTime::parse_from_rfc3339(&message.timestamp) .map(|dt| dt.timestamp()) .unwrap_or(0); - TauriMessage { + let result = TauriMessage { id: None, role: message.role.clone(), content, timestamp, - } + }; + + // 调试日志 + tracing::debug!( + "[SessionStore] 转换消息: role={}, content={:?}", + result.role, + result.content + ); + + result } diff --git a/src-tauri/crates/core/Cargo.toml b/src-tauri/crates/core/Cargo.toml index 6c3e3bae3..c575d4526 100644 --- a/src-tauri/crates/core/Cargo.toml +++ b/src-tauri/crates/core/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true repository.workspace = true [dependencies] +# Shared API models +aster-models.workspace = true + # 序列化 serde.workspace = true serde_json.workspace = true diff --git a/src-tauri/crates/core/src/content/manager.rs b/src-tauri/crates/core/src/content/manager.rs index f378a5cc3..e0fd62ace 100644 --- a/src-tauri/crates/core/src/content/manager.rs +++ b/src-tauri/crates/core/src/content/manager.rs @@ -107,7 +107,7 @@ impl ContentManager { ); let workspace_type = match workspace_type { - Ok(value) => WorkspaceType::from_str(&value), + Ok(value) => WorkspaceType::parse(&value), Err(_) => return ContentType::Document, }; diff --git a/src-tauri/crates/core/src/database/dao/agent.rs b/src-tauri/crates/core/src/database/dao/agent.rs index f25b10eac..abdd5bc1e 100644 --- a/src-tauri/crates/core/src/database/dao/agent.rs +++ b/src-tauri/crates/core/src/database/dao/agent.rs @@ -2,7 +2,7 @@ //! //! 提供 Agent 会话和消息的持久化存储功能 -use crate::agent::types::{AgentMessage, AgentSession, MessageContent, ToolCall}; +use crate::agent::types::{AgentMessage, AgentSession, ContentPart, MessageContent, ToolCall}; use rusqlite::{params, Connection}; /// 解析消息内容 JSON,支持多种格式 @@ -14,28 +14,34 @@ use rusqlite::{params, Connection}; fn parse_message_content(content_json: &str) -> MessageContent { // 尝试解析为 Aster 格式 (Vec) if let Ok(aster_contents) = serde_json::from_str::>(content_json) { - let mut text_parts: Vec = Vec::new(); + let mut parts: Vec = Vec::new(); for item in aster_contents { // Aster 格式: {"Text": "..."} 或 {"ToolRequest": ...} if let Some(text) = item.get("Text").and_then(|v| v.as_str()) { - text_parts.push(text.to_string()); + parts.push(ContentPart::Text { + text: text.to_string(), + }); } // 也支持小写 "text" 格式 else if let Some(text) = item.get("text").and_then(|v| v.as_str()) { - text_parts.push(text.to_string()); + parts.push(ContentPart::Text { + text: text.to_string(), + }); } // ProxyCast Parts 格式: {"type": "text", "text": "..."} else if item.get("type").and_then(|v| v.as_str()) == Some("text") { if let Some(text) = item.get("text").and_then(|v| v.as_str()) { - text_parts.push(text.to_string()); + parts.push(ContentPart::Text { + text: text.to_string(), + }); } } // 忽略 ToolRequest、ToolResponse 等非文本内容 } - if !text_parts.is_empty() { - return MessageContent::Text(text_parts.join("\n")); + if !parts.is_empty() { + return MessageContent::Parts(parts); } } diff --git a/src-tauri/crates/core/src/database/migration.rs b/src-tauri/crates/core/src/database/migration.rs index 1c955555f..2f764995b 100644 --- a/src-tauri/crates/core/src/database/migration.rs +++ b/src-tauri/crates/core/src/database/migration.rs @@ -464,15 +464,13 @@ pub fn cleanup_legacy_api_key_credentials(conn: &Connection) -> Result Result { conn.busy_timeout(std::time::Duration::from_secs(5)) .map_err(|e| format!("设置 busy_timeout 失败: {e}"))?; + // 启用 WAL 模式提升并发性能 + conn.execute_batch( + "PRAGMA journal_mode = WAL; + PRAGMA synchronous = NORMAL; + PRAGMA cache_size = -64000; + PRAGMA temp_store = MEMORY;", + ) + .map_err(|e| format!("设置数据库优化参数失败: {e}"))?; + + tracing::info!("[数据库] 已启用 WAL 模式和性能优化参数"); + // 创建表结构 schema::create_tables(&conn).map_err(|e| e.to_string())?; migration::migrate_from_json(&conn)?; diff --git a/src-tauri/crates/core/src/models/anthropic.rs b/src-tauri/crates/core/src/models/anthropic.rs index 87926833f..c82c8397f 100644 --- a/src-tauri/crates/core/src/models/anthropic.rs +++ b/src-tauri/crates/core/src/models/anthropic.rs @@ -1,142 +1,4 @@ //! Anthropic/Claude API 数据模型 -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(tag = "type")] -pub enum AnthropicContentBlock { - #[serde(rename = "text")] - Text { text: String }, - #[serde(rename = "tool_use")] - ToolUse { - id: String, - name: String, - input: serde_json::Value, - }, - #[serde(rename = "tool_result")] - ToolResult { - tool_use_id: String, - content: serde_json::Value, - }, - #[serde(rename = "image")] - Image { source: ImageSource }, - /// Extended Thinking 块 - #[serde(rename = "thinking")] - Thinking { - thinking: String, - /// 签名字段,用于验证思维内容的完整性 - signature: String, - }, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ImageSource { - #[serde(rename = "type")] - pub source_type: String, - pub media_type: String, - pub data: String, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct AnthropicMessage { - pub role: String, - pub content: serde_json::Value, // Can be string or array -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct AnthropicTool { - pub name: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub description: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub input_schema: Option, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct AnthropicMessagesRequest { - pub model: String, - pub messages: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - pub max_tokens: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub system: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub temperature: Option, - #[serde(default)] - pub stream: bool, - #[serde(skip_serializing_if = "Option::is_none")] - pub tools: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - pub tool_choice: Option, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct AnthropicUsage { - pub input_tokens: u32, - pub output_tokens: u32, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -#[allow(dead_code)] -pub struct AnthropicMessagesResponse { - pub id: String, - #[serde(rename = "type")] - pub response_type: String, - pub role: String, - pub content: Vec, - pub model: String, - pub stop_reason: Option, - pub usage: AnthropicUsage, -} - -// Streaming events -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(tag = "type")] -pub enum AnthropicStreamEvent { - #[serde(rename = "message_start")] - MessageStart { message: AnthropicMessageStart }, - #[serde(rename = "content_block_start")] - ContentBlockStart { - index: u32, - content_block: AnthropicContentBlock, - }, - #[serde(rename = "content_block_delta")] - ContentBlockDelta { index: u32, delta: AnthropicDelta }, - #[serde(rename = "content_block_stop")] - ContentBlockStop { index: u32 }, - #[serde(rename = "message_delta")] - MessageDelta { - delta: AnthropicMessageDelta, - usage: AnthropicUsage, - }, - #[serde(rename = "message_stop")] - MessageStop, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct AnthropicMessageStart { - pub id: String, - #[serde(rename = "type")] - pub msg_type: String, - pub role: String, - pub model: String, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(tag = "type")] -pub enum AnthropicDelta { - #[serde(rename = "text_delta")] - TextDelta { text: String }, - #[serde(rename = "input_json_delta")] - InputJsonDelta { partial_json: String }, - /// Extended Thinking delta - #[serde(rename = "thinking_delta")] - ThinkingDelta { thinking: String }, - /// Signature delta for thinking blocks - #[serde(rename = "signature_delta")] - SignatureDelta { signature: String }, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct AnthropicMessageDelta { - pub stop_reason: Option, -} +//! +//! Types re-exported from `aster-models` crate (single source of truth). +pub use aster_models::anthropic::*; diff --git a/src-tauri/crates/core/src/models/openai.rs b/src-tauri/crates/core/src/models/openai.rs index 2119cb667..629671011 100644 --- a/src-tauri/crates/core/src/models/openai.rs +++ b/src-tauri/crates/core/src/models/openai.rs @@ -1,236 +1,13 @@ //! OpenAI API 数据模型 //! -//! 支持标准 OpenAI 格式以及扩展的工具类型(如 web_search)。 -//! -//! # 工具类型支持 -//! -//! - `function`: 标准函数调用工具 -//! - `web_search`: 联网搜索工具(Claude Code 使用 `web_search_20250305`) -//! -//! # 更新日志 -//! -//! - 2025-12-27: 添加 web_search 工具支持,修复 Issue #49 +//! Chat Completion types re-exported from `aster-models` crate (single source of truth). +//! Image generation types are ProxyCast-specific and defined locally. +pub use aster_models::openai::*; + use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ImageUrl { - pub url: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub detail: Option, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(tag = "type")] -pub enum ContentPart { - #[serde(rename = "text")] - Text { text: String }, - #[serde(rename = "image_url")] - ImageUrl { image_url: ImageUrl }, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ToolCall { - pub id: String, - #[serde(rename = "type")] - pub call_type: String, - pub function: FunctionCall, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct FunctionCall { - pub name: String, - pub arguments: String, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(untagged)] -pub enum MessageContent { - Text(String), - Parts(Vec), -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ChatMessage { - pub role: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub content: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub tool_calls: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - pub tool_call_id: Option, - /// 推理内容(DeepSeek R1 等模型的思维链内容) - /// DeepSeek Reasoner 在 Tool Calls 场景下要求此字段 - #[serde(skip_serializing_if = "Option::is_none")] - pub reasoning_content: Option, -} - -impl ChatMessage { - pub fn get_content_text(&self) -> String { - match &self.content { - Some(MessageContent::Text(s)) => s.clone(), - Some(MessageContent::Parts(parts)) => parts - .iter() - .filter_map(|p| { - if let ContentPart::Text { text } = p { - Some(text.clone()) - } else { - None - } - }) - .collect::>() - .join(""), - None => String::new(), - } - } - - /// 提取消息中的图片 URL 列表 - /// 返回 (format, base64_data) 元组列表 - pub fn get_images(&self) -> Vec<(String, String)> { - match &self.content { - Some(MessageContent::Parts(parts)) => parts - .iter() - .filter_map(|p| { - if let ContentPart::ImageUrl { image_url } = p { - // 解析 data URL: data:image/jpeg;base64,xxxxx - if image_url.url.starts_with("data:") { - let parts: Vec<&str> = image_url.url.splitn(2, ',').collect(); - if parts.len() == 2 { - // 提取 media_type: data:image/jpeg;base64 -> image/jpeg - let header = parts[0]; - let data = parts[1]; - let media_type = header - .strip_prefix("data:") - .and_then(|s| s.split(';').next()) - .unwrap_or("image/jpeg"); - // 提取格式: image/jpeg -> jpeg - let format = - media_type.split('/').nth(1).unwrap_or("jpeg").to_string(); - return Some((format, data.to_string())); - } - } - None - } else { - None - } - }) - .collect(), - _ => Vec::new(), - } - } -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct FunctionDef { - pub name: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub description: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub parameters: Option, -} - -/// 工具定义 -/// -/// 支持多种工具类型: -/// - `function`: 标准函数调用工具,包含 function 字段 -/// - `web_search`: 联网搜索工具,无需额外字段 -/// - `web_search_20250305`: Claude Code 的联网搜索工具类型 -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(tag = "type")] -pub enum Tool { - /// 标准函数调用工具 - #[serde(rename = "function")] - Function { function: FunctionDef }, - /// 联网搜索工具(Codex/Kiro 格式) - #[serde(rename = "web_search")] - WebSearch, - /// 联网搜索工具(Claude Code 格式) - #[serde(rename = "web_search_20250305")] - WebSearch20250305, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ChatCompletionRequest { - pub model: String, - pub messages: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - pub temperature: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub max_tokens: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub top_p: Option, - #[serde(default)] - pub stream: bool, - #[serde(skip_serializing_if = "Option::is_none")] - pub tools: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - pub tool_choice: Option, - /// 思维链强度:none, low, medium, high - #[serde(skip_serializing_if = "Option::is_none")] - pub reasoning_effort: Option, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Usage { - pub prompt_tokens: u32, - pub completion_tokens: u32, - pub total_tokens: u32, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ResponseMessage { - pub role: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub content: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub tool_calls: Option>, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Choice { - pub index: u32, - pub message: ResponseMessage, - pub finish_reason: String, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ChatCompletionResponse { - pub id: String, - pub object: String, - pub created: u64, - pub model: String, - pub choices: Vec, - pub usage: Usage, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct StreamDelta { - #[serde(skip_serializing_if = "Option::is_none")] - pub role: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub content: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub tool_calls: Option>, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct StreamChoice { - pub index: u32, - pub delta: StreamDelta, - #[serde(skip_serializing_if = "Option::is_none")] - pub finish_reason: Option, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ChatCompletionChunk { - pub id: String, - pub object: String, - pub created: u64, - pub model: String, - pub choices: Vec, -} - // ============================================================================ -// 图像生成 API 数据模型 +// 图像生成 API 数据模型 (ProxyCast 特有) // ============================================================================ /// OpenAI 图像生成请求 diff --git a/src-tauri/crates/core/src/workspace/manager.rs b/src-tauri/crates/core/src/workspace/manager.rs index 0af71bf0f..4379dc47a 100644 --- a/src-tauri/crates/core/src/workspace/manager.rs +++ b/src-tauri/crates/core/src/workspace/manager.rs @@ -7,7 +7,7 @@ use crate::database::DbConnection; use chrono::Utc; use rusqlite::params; use std::collections::HashSet; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use uuid::Uuid; /// Workspace 管理器 @@ -186,7 +186,7 @@ impl WorkspaceManager { } /// 通过路径获取 workspace - pub fn get_by_path(&self, root_path: &PathBuf) -> Result, String> { + pub fn get_by_path(&self, root_path: &Path) -> Result, String> { let root_path_str = root_path.to_str().ok_or("无效的路径")?; let conn = self.db.lock().map_err(|e| format!("数据库锁定失败: {e}"))?; @@ -464,7 +464,7 @@ impl WorkspaceManager { Ok(Workspace { id, name, - workspace_type: WorkspaceType::from_str(&workspace_type_str), + workspace_type: WorkspaceType::parse(&workspace_type_str), root_path: PathBuf::from(root_path_str), is_default, created_at: chrono::DateTime::from_timestamp_millis(created_at_ms) diff --git a/src-tauri/crates/core/src/workspace/types.rs b/src-tauri/crates/core/src/workspace/types.rs index 1c64a2cda..391634f1b 100644 --- a/src-tauri/crates/core/src/workspace/types.rs +++ b/src-tauri/crates/core/src/workspace/types.rs @@ -55,7 +55,7 @@ impl WorkspaceType { } } - pub fn from_str(s: &str) -> Self { + pub fn parse(s: &str) -> Self { match s { "temporary" => WorkspaceType::Temporary, "general" => WorkspaceType::General, @@ -221,51 +221,36 @@ mod tests { #[test] fn test_workspace_type_from_str() { assert_eq!( - WorkspaceType::from_str("persistent"), + WorkspaceType::parse("persistent"), WorkspaceType::Persistent ); + assert_eq!(WorkspaceType::parse("temporary"), WorkspaceType::Temporary); + assert_eq!(WorkspaceType::parse("general"), WorkspaceType::General); assert_eq!( - WorkspaceType::from_str("temporary"), - WorkspaceType::Temporary - ); - assert_eq!(WorkspaceType::from_str("general"), WorkspaceType::General); - assert_eq!( - WorkspaceType::from_str("social-media"), + WorkspaceType::parse("social-media"), WorkspaceType::SocialMedia ); - assert_eq!(WorkspaceType::from_str("poster"), WorkspaceType::Poster); - assert_eq!(WorkspaceType::from_str("music"), WorkspaceType::Music); - assert_eq!( - WorkspaceType::from_str("knowledge"), - WorkspaceType::Knowledge - ); - assert_eq!(WorkspaceType::from_str("planning"), WorkspaceType::Planning); - assert_eq!(WorkspaceType::from_str("document"), WorkspaceType::Document); - assert_eq!(WorkspaceType::from_str("video"), WorkspaceType::Video); - assert_eq!(WorkspaceType::from_str("novel"), WorkspaceType::Novel); + assert_eq!(WorkspaceType::parse("poster"), WorkspaceType::Poster); + assert_eq!(WorkspaceType::parse("music"), WorkspaceType::Music); + assert_eq!(WorkspaceType::parse("knowledge"), WorkspaceType::Knowledge); + assert_eq!(WorkspaceType::parse("planning"), WorkspaceType::Planning); + assert_eq!(WorkspaceType::parse("document"), WorkspaceType::Document); + assert_eq!(WorkspaceType::parse("video"), WorkspaceType::Video); + assert_eq!(WorkspaceType::parse("novel"), WorkspaceType::Novel); } #[test] fn test_legacy_type_migration() { // 旧类型应该正确映射到新类型 - assert_eq!(WorkspaceType::from_str("drama"), WorkspaceType::Video); - assert_eq!( - WorkspaceType::from_str("social"), - WorkspaceType::SocialMedia - ); + assert_eq!(WorkspaceType::parse("drama"), WorkspaceType::Video); + assert_eq!(WorkspaceType::parse("social"), WorkspaceType::SocialMedia); } #[test] fn test_unknown_type_defaults_to_persistent() { - assert_eq!( - WorkspaceType::from_str("unknown"), - WorkspaceType::Persistent - ); - assert_eq!(WorkspaceType::from_str(""), WorkspaceType::Persistent); - assert_eq!( - WorkspaceType::from_str("invalid"), - WorkspaceType::Persistent - ); + assert_eq!(WorkspaceType::parse("unknown"), WorkspaceType::Persistent); + assert_eq!(WorkspaceType::parse(""), WorkspaceType::Persistent); + assert_eq!(WorkspaceType::parse("invalid"), WorkspaceType::Persistent); } #[test] @@ -330,7 +315,7 @@ mod tests { for wt in types { let s = wt.as_str(); - let parsed = WorkspaceType::from_str(s); + let parsed = WorkspaceType::parse(s); assert_eq!(wt, parsed, "Roundtrip failed for {wt:?}"); } } diff --git a/src-tauri/crates/memory/src/feedback.rs b/src-tauri/crates/memory/src/feedback.rs index c98899a04..3f11d1393 100644 --- a/src-tauri/crates/memory/src/feedback.rs +++ b/src-tauri/crates/memory/src/feedback.rs @@ -114,7 +114,7 @@ pub fn calculate_approval_rate(feedbacks: &[UserFeedback]) -> f32 { } } - (score / total).max(0.0).min(1.0) + (score / total).clamp(0.0, 1.0) } // ==================== Extraction Parameters ==================== diff --git a/src-tauri/crates/memory/src/search.rs b/src-tauri/crates/memory/src/search.rs index 99b9a8f0d..5ef7d5b73 100644 --- a/src-tauri/crates/memory/src/search.rs +++ b/src-tauri/crates/memory/src/search.rs @@ -146,10 +146,7 @@ fn parse_memory_from_row( let vec_len = blob.len() / 4; let mut vec = Vec::with_capacity(vec_len); for chunk in blob.chunks_exact(4) { - let bytes: [u8; 4] = match chunk.try_into() { - Ok(arr) => arr, - Err(_) => [0; 4], - }; + let bytes: [u8; 4] = chunk.try_into().unwrap_or_default(); let val = f32::from_le_bytes(bytes); vec.push(val); } diff --git a/src-tauri/crates/providers/src/converter/cw_to_openai.rs b/src-tauri/crates/providers/src/converter/cw_to_openai.rs index a15753c0f..f5c673d0e 100644 --- a/src-tauri/crates/providers/src/converter/cw_to_openai.rs +++ b/src-tauri/crates/providers/src/converter/cw_to_openai.rs @@ -31,6 +31,7 @@ pub fn convert_cw_event_to_openai_chunk( role: Some("assistant".to_string()), content: Some(content.clone()), tool_calls: None, + reasoning_content: None, }, finish_reason: None, }], @@ -58,6 +59,7 @@ pub fn convert_cw_event_to_openai_chunk( .unwrap_or_default(), }, }]), + reasoning_content: None, }, finish_reason: None, }], @@ -131,6 +133,7 @@ pub fn create_stream_end_chunk(model: &str, response_id: &str) -> ChatCompletion role: None, content: None, tool_calls: None, + reasoning_content: None, }, finish_reason: Some("stop".to_string()), }], diff --git a/src-tauri/crates/services/src/project_context_builder.rs b/src-tauri/crates/services/src/project_context_builder.rs index 130fc36c5..f1e1e7a56 100644 --- a/src-tauri/crates/services/src/project_context_builder.rs +++ b/src-tauri/crates/services/src/project_context_builder.rs @@ -187,7 +187,7 @@ impl ProjectContextBuilder { Ok(Workspace { id, name, - workspace_type: WorkspaceType::from_str(&workspace_type_str), + workspace_type: WorkspaceType::parse(&workspace_type_str), root_path: PathBuf::from(root_path_str), is_default, created_at: chrono::DateTime::from_timestamp_millis(created_at_ms) diff --git a/src-tauri/src/commands/unified_chat_cmd.rs b/src-tauri/src/commands/unified_chat_cmd.rs index 1d50442ef..c807e4173 100644 --- a/src-tauri/src/commands/unified_chat_cmd.rs +++ b/src-tauri/src/commands/unified_chat_cmd.rs @@ -123,10 +123,16 @@ pub async fn chat_create_session( updated_at: now, }; - // 保存到数据库 + // 保存到数据库(异步化) { - let conn = db.lock().map_err(|e| format!("数据库锁定失败: {e}"))?; - ChatDao::create_session(&conn, &session).map_err(|e| format!("创建会话失败: {e}"))?; + let db = db.inner().clone(); + let session_clone = session.clone(); + tokio::task::spawn_blocking(move || { + let conn = db.lock().map_err(|e| format!("数据库锁定失败: {e}"))?; + ChatDao::create_session(&conn, &session_clone).map_err(|e| format!("创建会话失败: {e}")) + }) + .await + .map_err(|e| format!("任务执行失败: {e}"))??; } // 初始化 Aster Agent(如果是 Agent 或 Creator 模式) @@ -158,20 +164,25 @@ pub async fn chat_list_sessions( db: State<'_, DbConnection>, mode: Option, ) -> Result, String> { - let conn = db.lock().map_err(|e| format!("数据库锁定失败: {e}"))?; + let db = db.inner().clone(); + tokio::task::spawn_blocking(move || { + let conn = db.lock().map_err(|e| format!("数据库锁定失败: {e}"))?; - let sessions = - ChatDao::list_sessions(&conn, mode).map_err(|e| format!("获取会话列表失败: {e}"))?; + let sessions = + ChatDao::list_sessions(&conn, mode).map_err(|e| format!("获取会话列表失败: {e}"))?; - let mut result: Vec = Vec::new(); - for session in sessions { - let message_count = ChatDao::get_message_count(&conn, &session.id).unwrap_or(0); - let mut resp = SessionResponse::from(session); - resp.message_count = message_count; - result.push(resp); - } + let mut result: Vec = Vec::new(); + for session in sessions { + let message_count = ChatDao::get_message_count(&conn, &session.id).unwrap_or(0); + let mut resp = SessionResponse::from(session); + resp.message_count = message_count; + result.push(resp); + } - Ok(result) + Ok(result) + }) + .await + .map_err(|e| format!("任务执行失败: {e}"))? } /// 获取会话详情 @@ -180,17 +191,22 @@ pub async fn chat_get_session( db: State<'_, DbConnection>, session_id: String, ) -> Result { - let conn = db.lock().map_err(|e| format!("数据库锁定失败: {e}"))?; + let db = db.inner().clone(); + tokio::task::spawn_blocking(move || { + let conn = db.lock().map_err(|e| format!("数据库锁定失败: {e}"))?; - let session = ChatDao::get_session(&conn, &session_id) - .map_err(|e| format!("获取会话失败: {e}"))? - .ok_or_else(|| "会话不存在".to_string())?; + let session = ChatDao::get_session(&conn, &session_id) + .map_err(|e| format!("获取会话失败: {e}"))? + .ok_or_else(|| "会话不存在".to_string())?; - let message_count = ChatDao::get_message_count(&conn, &session_id).unwrap_or(0); - let mut resp = SessionResponse::from(session); - resp.message_count = message_count; + let message_count = ChatDao::get_message_count(&conn, &session_id).unwrap_or(0); + let mut resp = SessionResponse::from(session); + resp.message_count = message_count; - Ok(resp) + Ok(resp) + }) + .await + .map_err(|e| format!("任务执行失败: {e}"))? } /// 删除会话 @@ -199,16 +215,21 @@ pub async fn chat_delete_session( db: State<'_, DbConnection>, session_id: String, ) -> Result { - let conn = db.lock().map_err(|e| format!("数据库锁定失败: {e}"))?; + let db = db.inner().clone(); + tokio::task::spawn_blocking(move || { + let conn = db.lock().map_err(|e| format!("数据库锁定失败: {e}"))?; - let deleted = - ChatDao::delete_session(&conn, &session_id).map_err(|e| format!("删除会话失败: {e}"))?; + let deleted = ChatDao::delete_session(&conn, &session_id) + .map_err(|e| format!("删除会话失败: {e}"))?; - if deleted { - tracing::info!("[UnifiedChat] 删除会话: id={}", session_id); - } + if deleted { + tracing::info!("[UnifiedChat] 删除会话: id={}", session_id); + } - Ok(deleted) + Ok(deleted) + }) + .await + .map_err(|e| format!("任务执行失败: {e}"))? } /// 重命名会话 @@ -218,18 +239,23 @@ pub async fn chat_rename_session( session_id: String, title: String, ) -> Result<(), String> { - let conn = db.lock().map_err(|e| format!("数据库锁定失败: {e}"))?; + let db = db.inner().clone(); + tokio::task::spawn_blocking(move || { + let conn = db.lock().map_err(|e| format!("数据库锁定失败: {e}"))?; - ChatDao::update_title(&conn, &session_id, &title) - .map_err(|e| format!("重命名会话失败: {e}"))?; + ChatDao::update_title(&conn, &session_id, &title) + .map_err(|e| format!("重命名会话失败: {e}"))?; - tracing::info!( - "[UnifiedChat] 重命名会话: id={}, title={}", - session_id, - title - ); + tracing::info!( + "[UnifiedChat] 重命名会话: id={}, title={}", + session_id, + title + ); - Ok(()) + Ok(()) + }) + .await + .map_err(|e| format!("任务执行失败: {e}"))? } // ============================================================================ @@ -243,12 +269,17 @@ pub async fn chat_get_messages( session_id: String, limit: Option, ) -> Result, String> { - let conn = db.lock().map_err(|e| format!("数据库锁定失败: {e}"))?; + let db = db.inner().clone(); + tokio::task::spawn_blocking(move || { + let conn = db.lock().map_err(|e| format!("数据库锁定失败: {e}"))?; - let messages = ChatDao::get_messages(&conn, &session_id, limit) - .map_err(|e| format!("获取消息失败: {e}"))?; + let messages = ChatDao::get_messages(&conn, &session_id, limit) + .map_err(|e| format!("获取消息失败: {e}"))?; - Ok(messages) + Ok(messages) + }) + .await + .map_err(|e| format!("任务执行失败: {e}"))? } /// 发送消息并获取流式响应 @@ -261,6 +292,8 @@ pub async fn chat_send_message( agent_state: State<'_, AsterAgentState>, request: SendMessageRequest, ) -> Result<(), String> { + let start_time = std::time::Instant::now(); + let image_count = request.images.as_ref().map(|v| v.len()).unwrap_or(0); tracing::info!( "[UnifiedChat] 发送消息: session={}, event={}, images={}", @@ -287,16 +320,25 @@ pub async fn chat_send_message( } } - // 获取会话信息 + // 获取会话信息(异步化数据库操作) + let db_start = std::time::Instant::now(); let session = { - let conn = db.lock().map_err(|e| format!("数据库锁定失败: {e}"))?; - ChatDao::get_session(&conn, &request.session_id) - .map_err(|e| format!("获取会话失败: {e}"))? - .ok_or_else(|| "会话不存在".to_string())? + let db = db.inner().clone(); + let session_id = request.session_id.clone(); + tokio::task::spawn_blocking(move || { + let conn = db.lock().map_err(|e| format!("数据库锁定失败: {e}"))?; + ChatDao::get_session(&conn, &session_id) + .map_err(|e| format!("获取会话失败: {e}"))? + .ok_or_else(|| "会话不存在".to_string()) + }) + .await + .map_err(|e| format!("任务执行失败: {e}"))?? }; + let db_elapsed = db_start.elapsed(); + tracing::debug!("[UnifiedChat] 数据库查询耗时: {:?}", db_elapsed); // 根据模式处理 - match session.mode { + let result = match session.mode { ChatMode::Agent | ChatMode::Creator => { // 使用 Aster Agent 处理 send_message_with_aster( @@ -323,7 +365,16 @@ pub async fn chat_send_message( ) .await } - } + }; + + let total_elapsed = start_time.elapsed(); + tracing::info!( + "[UnifiedChat] 消息发送完成: session={}, 总耗时={:?}", + request.session_id, + total_elapsed + ); + + result } /// 使用 Aster Agent 发送消息 @@ -336,15 +387,26 @@ async fn send_message_with_aster( event_name: &str, system_prompt: Option<&str>, ) -> Result<(), String> { + let start_time = std::time::Instant::now(); + // 确保 Agent 已初始化 + let init_start = std::time::Instant::now(); if !agent_state.is_initialized().await { agent_state.init_agent_with_db(db).await?; } + let init_elapsed = init_start.elapsed(); + tracing::debug!("[UnifiedChat] Agent 初始化检查耗时: {:?}", init_elapsed); // 检查 Provider 是否已配置 + let provider_check_start = std::time::Instant::now(); if !agent_state.is_provider_configured().await { return Err("Provider 未配置,请先配置凭证".to_string()); } + let provider_check_elapsed = provider_check_start.elapsed(); + tracing::debug!( + "[UnifiedChat] Provider 配置检查耗时: {:?}", + provider_check_elapsed + ); // 创建取消令牌 let cancel_token = agent_state.create_cancel_token(session_id).await; @@ -365,15 +427,27 @@ async fn send_message_with_aster( let agent = guard.as_ref().ok_or("Agent 未初始化")?; // 调用 Agent + let reply_start = std::time::Instant::now(); let stream_result = agent .reply(user_message, session_config, Some(cancel_token.clone())) .await; + let mut first_chunk_time: Option = None; + let mut chunk_count = 0; + match stream_result { Ok(mut stream) => { while let Some(event_result) = stream.next().await { match event_result { Ok(agent_event) => { + // 记录首个 chunk 时间(TTFB) + if first_chunk_time.is_none() { + first_chunk_time = Some(std::time::Instant::now()); + let ttfb = first_chunk_time.unwrap() - reply_start; + tracing::info!("[UnifiedChat] TTFB (首字节时间): {:?}", ttfb); + } + chunk_count += 1; + let tauri_events = convert_agent_event(agent_event); for tauri_event in tauri_events { if let Err(e) = app.emit(event_name, &tauri_event) { @@ -393,6 +467,14 @@ async fn send_message_with_aster( // 发送完成事件 let done_event = TauriAgentEvent::FinalDone { usage: None }; let _ = app.emit(event_name, &done_event); + + let stream_elapsed = start_time.elapsed(); + tracing::info!( + "[UnifiedChat] 流式传输完成: session={}, chunks={}, 总耗时={:?}", + session_id, + chunk_count, + stream_elapsed + ); } Err(e) => { let error_event = TauriAgentEvent::Error { diff --git a/src-tauri/src/commands/workspace_cmd.rs b/src-tauri/src/commands/workspace_cmd.rs index 5e6d0ddd3..636216593 100644 --- a/src-tauri/src/commands/workspace_cmd.rs +++ b/src-tauri/src/commands/workspace_cmd.rs @@ -136,7 +136,7 @@ pub async fn workspace_create( let workspace_type = request .workspace_type - .map(|t| WorkspaceType::from_str(&t)) + .map(|t| WorkspaceType::parse(&t)) .unwrap_or_default(); let workspace = manager.create_with_type( diff --git a/src-tauri/test_serialize.rs b/src-tauri/test_serialize.rs new file mode 100644 index 000000000..7bd209c5f --- /dev/null +++ b/src-tauri/test_serialize.rs @@ -0,0 +1,20 @@ +use serde::{Serialize, Deserialize}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(tag = "type")] +pub enum TauriMessageContent { + #[serde(rename = "text")] + Text { text: String }, + #[serde(rename = "thinking")] + Thinking { text: String }, +} + +fn main() { + let content = vec![ + TauriMessageContent::Text { text: "Hello".to_string() }, + TauriMessageContent::Thinking { text: "Thinking...".to_string() }, + ]; + + let json = serde_json::to_string_pretty(&content).unwrap(); + println!("{}", json); +} diff --git a/src/components/agent/chat/components/EmptyState.tsx b/src/components/agent/chat/components/EmptyState.tsx index 16918f85f..4669c4c02 100644 --- a/src/components/agent/chat/components/EmptyState.tsx +++ b/src/components/agent/chat/components/EmptyState.tsx @@ -825,8 +825,7 @@ export const EmptyState: React.FC = ({
- {themeHeadline.lead}
- {themeHeadline.focus} + {themeHeadline.lead}{themeHeadline.focus}
@@ -1199,7 +1198,7 @@ export const EmptyState: React.FC = ({ size="sm" onClick={handleSend} disabled={!input.trim() && !isEntryTheme} - className="bg-primary hover:bg-primary/90 text-primary-foreground h-9 px-5 rounded-xl shadow-lg shadow-primary/20 transition-all hover:scale-105 active:scale-95" + className="bg-primary hover:bg-primary/90 text-primary-foreground h-9 px-5 rounded-xl shadow-lg shadow-primary/20 transition-all hover:scale-105 active:scale-95 whitespace-nowrap" > 开始生成 diff --git a/src/components/agent/chat/hooks/useAsterAgentChat.ts b/src/components/agent/chat/hooks/useAsterAgentChat.ts index 98e5d22d6..90e0e9889 100644 --- a/src/components/agent/chat/hooks/useAsterAgentChat.ts +++ b/src/components/agent/chat/hooks/useAsterAgentChat.ts @@ -1011,11 +1011,12 @@ export function useAsterAgentChat(options: UseAsterAgentChatOptions) { toast.info("已切换话题"); } catch (error) { console.error("[AsterChat] 切换话题失败:", error); + console.error("[AsterChat] 错误详情:", JSON.stringify(error, null, 2)); setMessages([]); setSessionId(null); saveTransient(getScopedSessionKey(), null); savePersisted(getScopedPersistedSessionKey(), null); - toast.error("加载对话历史失败"); + toast.error(`加载对话历史失败: ${error instanceof Error ? error.message : String(error)}`); } }, [