mirror of
https://github.com/aiclientproxy/proxycast.git
synced 2026-09-24 23:10:56 +08:00
release: v0.68.0
## 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)
This commit is contained in:
@@ -2,23 +2,98 @@
|
||||
|
||||
# ProxyCast 🚀
|
||||
|
||||
**AI Agent 创作工具平台**
|
||||
**创作类 AI Agent 平台**
|
||||
|
||||
[](https://www.gnu.org/licenses/gpl-3.0)
|
||||
[](https://tauri.app/)
|
||||
[](https://react.dev/)
|
||||
[](https://www.rust-lang.org/)
|
||||
一句话:把灵感、写作、出图、改稿、沉淀放进同一个工作台,让创作从“想到”直接走到“可发布”。
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## ✨ 核心特性
|
||||
## 👋 这是什么
|
||||
|
||||
- **多 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 模型服务,模型能力由第三方提供商提供。
|
||||
|
||||
+26
-39
@@ -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. 同步更新:功能改动后同步修正文档入口页与对应章节
|
||||
|
||||
@@ -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) - 熟悉核心入口
|
||||
|
||||
@@ -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 步完成第一次创作。
|
||||
|
||||
@@ -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) - 深入图片链路
|
||||
|
||||
@@ -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 | 凭证类型 |
|
||||
| 状态 | 有效/过期/错误 |
|
||||
| 剩余额度 | 可用额度(如支持) |
|
||||
|
||||
## 快捷操作
|
||||
|
||||
- **打开设置**: 进入设置页面
|
||||
- **查看日志**: 打开请求日志
|
||||
- **刷新凭证**: 重新加载凭证文件
|
||||
在资源页切换分类视图,可只看文档、图片、语音或视频。
|
||||
|
||||
@@ -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. 确认导入
|
||||
|
||||
### 分享提示词
|
||||
|
||||
导出的提示词文件可以分享给他人使用。
|
||||
在项目中沉淀效果好的模板,后续同类任务可直接复用。
|
||||
|
||||
@@ -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. 定期清理低使用技能,保持列表可维护
|
||||
|
||||
@@ -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 | 日志文件保留时间 |
|
||||
- 统一主题配置
|
||||
- 固定项目命名规则
|
||||
- 约定资源标签方式
|
||||
|
||||
@@ -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)
|
||||
|
||||
## 常见问题
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
---
|
||||
title: 资源库
|
||||
description: 管理项目中的文档、图片、语音和视频素材
|
||||
navigation:
|
||||
icon: i-heroicons-folder-open
|
||||
---
|
||||
|
||||
# 资源库
|
||||
|
||||
资源库是 ProxyCast 的创作资产中心。
|
||||
它和项目绑定,用来长期沉淀你的创作结果。
|
||||
|
||||
## 资源分类
|
||||
|
||||
资源页支持按分类查看:
|
||||
|
||||
- 全部
|
||||
- 文档
|
||||
- 图片
|
||||
- 语音
|
||||
- 视频
|
||||
|
||||
当你只想找图或找文档时,直接切换分类即可。
|
||||
|
||||
## 常见操作
|
||||
|
||||
### 新建与上传
|
||||
|
||||
1. 选择左侧资源库(项目)
|
||||
2. 新建文件夹或新建文档
|
||||
3. 上传本地文件到当前目录
|
||||
|
||||
### 搜索与排序
|
||||
|
||||
- 支持按名称、描述、标签搜索
|
||||
- 支持按更新时间、创建时间、名称排序
|
||||
|
||||
### 重命名与删除
|
||||
|
||||
在资源列表的操作菜单中,可对资源进行重命名、删除等操作。
|
||||
|
||||
## 资源与创作联动
|
||||
|
||||
### 从图片生成回流资源库
|
||||
|
||||
在图片生成页选择目标资源库后,成功生成的图片可自动写入当前项目。
|
||||
|
||||
### 从资源继续对话创作
|
||||
|
||||
在资源页选中素材后,可继续进入 AI Agent 进行改写、扩写或二次创作。
|
||||
|
||||
## 常见问题
|
||||
|
||||
### 为什么看不到某些图片?
|
||||
|
||||
先确认:
|
||||
|
||||
1. 当前选择的是否是正确资源库(项目)
|
||||
2. 是否切到了“图片”分类
|
||||
3. 文件后缀或 MIME 类型是否被识别为图片
|
||||
|
||||
### 为什么资源数量和预期不一致?
|
||||
|
||||
常见原因是“分类过滤”或“项目切换”导致显示范围变化。
|
||||
建议先切换到“全部”分类再确认总量。
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
title: 图片生成与编辑
|
||||
description: 通过文本与参考图完成图片生成、编辑与资产沉淀
|
||||
navigation:
|
||||
icon: i-heroicons-photo
|
||||
---
|
||||
|
||||
# 图片生成与编辑
|
||||
|
||||
图片生成页用于完成从“文字描述”到“可用图片素材”的全过程。
|
||||
|
||||
## 基本流程
|
||||
|
||||
1. 选择模型与参数(尺寸、比例、数量)
|
||||
2. 输入提示词
|
||||
3. 可选上传参考图
|
||||
4. 生成后选图并沉淀到资源库
|
||||
|
||||
## 参考图与编辑
|
||||
|
||||
### 上传参考图
|
||||
|
||||
可上传参考图作为创作输入,帮助模型更贴近目标风格或构图。
|
||||
|
||||
### 编辑链路
|
||||
|
||||
当模型支持图片编辑接口时,系统会优先尝试编辑端点;
|
||||
若不可用,会自动回退到可用生成端点,尽量保障出图成功率。
|
||||
|
||||
## 历史记录
|
||||
|
||||
历史区域会保存你的生成记录,支持:
|
||||
|
||||
- 查看单张或批次结果
|
||||
- 重新选择目标图继续迭代
|
||||
- 将历史结果补录到资源库
|
||||
|
||||
## 与资源库联动
|
||||
|
||||
### 目标资源库
|
||||
|
||||
生成前可指定目标资源库(项目),用于自动沉淀图片资产。
|
||||
|
||||
### 补录历史
|
||||
|
||||
如果历史图片尚未入库,可使用“补录历史到资源库”进行批量回填。
|
||||
|
||||
## 实用建议
|
||||
|
||||
### 先定方向再出图
|
||||
|
||||
先在 AI Agent 里明确画面目标,再进入图片生成功能,会减少无效尝试。
|
||||
|
||||
### 一次只改一个变量
|
||||
|
||||
每轮仅调整一个维度(提示词、比例、参考图),更容易稳定收敛到理想结果。
|
||||
|
||||
### 把可用版本及时入库
|
||||
|
||||
选中可用图片后尽快入库,方便后续在资源页检索和复用。
|
||||
@@ -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 格式
|
||||
- 自定义时间范围
|
||||
如果你需要做团队复盘,可导出统计数据用于周报或复盘记录。
|
||||
|
||||
@@ -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. 导出配置时确认敏感信息不会被带出
|
||||
|
||||
@@ -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 与自动化扩展
|
||||
|
||||
@@ -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
|
||||
- 目标模型
|
||||
- 规则过多导致难以维护
|
||||
- 没有兜底规则,异常时直接失败
|
||||
- 频繁改规则但不做回归测试
|
||||
|
||||
@@ -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)
|
||||
建议拆分任务批次,避免同一时刻大量并发。
|
||||
|
||||
@@ -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. 只按必要场景逐项开启进阶能力
|
||||
|
||||
@@ -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. 变更档案后记录用途,避免后续混乱
|
||||
|
||||
@@ -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 填写错误或请求头格式不正确。
|
||||
|
||||
@@ -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. 看服务器日志定位具体错误
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -7,6 +7,10 @@ navigation:
|
||||
|
||||
# Vertex AI Provider
|
||||
|
||||
::alert{type="info"}
|
||||
本页属于进阶连接配置。若你已能正常创作,可先跳过。
|
||||
::
|
||||
|
||||
使用 API Key 访问 Google Cloud Vertex AI 服务,支持模型别名映射。
|
||||
|
||||
## 概述
|
||||
|
||||
@@ -7,6 +7,10 @@ navigation:
|
||||
|
||||
# Kiro Claude
|
||||
|
||||
::alert{type="info"}
|
||||
本页属于进阶连接配置。若你已能正常创作,可先跳过。
|
||||
::
|
||||
|
||||
Kiro Claude 是 AWS Kiro IDE 提供的 Claude AI 服务凭证。
|
||||
|
||||
## 凭证位置
|
||||
|
||||
@@ -7,6 +7,10 @@ navigation:
|
||||
|
||||
# Gemini CLI
|
||||
|
||||
::alert{type="info"}
|
||||
本页属于进阶连接配置。若你已能正常创作,可先跳过。
|
||||
::
|
||||
|
||||
Gemini CLI 是 Google 提供的命令行 AI 工具,使用 OAuth 认证。
|
||||
|
||||
## 凭证位置
|
||||
|
||||
@@ -7,6 +7,10 @@ navigation:
|
||||
|
||||
# Qwen (通义千问)
|
||||
|
||||
::alert{type="info"}
|
||||
本页属于进阶连接配置。若你已能正常创作,可先跳过。
|
||||
::
|
||||
|
||||
Qwen 是阿里云提供的大语言模型服务。
|
||||
|
||||
## 凭证位置
|
||||
|
||||
@@ -7,6 +7,10 @@ navigation:
|
||||
|
||||
# OpenAI Custom
|
||||
|
||||
::alert{type="info"}
|
||||
本页属于进阶连接配置。若你已能正常创作,可先跳过。
|
||||
::
|
||||
|
||||
OpenAI Custom 允许你配置任何 OpenAI 兼容的 API 服务。
|
||||
|
||||
## 适用场景
|
||||
|
||||
@@ -7,6 +7,10 @@ navigation:
|
||||
|
||||
# Claude Custom
|
||||
|
||||
::alert{type="info"}
|
||||
本页属于进阶连接配置。若你已能正常创作,可先跳过。
|
||||
::
|
||||
|
||||
Claude Custom 允许你配置 Anthropic 官方 API 或其他 Claude 兼容服务。
|
||||
|
||||
## 适用场景
|
||||
|
||||
@@ -7,6 +7,10 @@ navigation:
|
||||
|
||||
# Codex Provider
|
||||
|
||||
::alert{type="info"}
|
||||
本页属于进阶连接配置。若你已能正常创作,可先跳过。
|
||||
::
|
||||
|
||||
通过 OAuth 认证使用 OpenAI Codex 服务。
|
||||
|
||||
## 概述
|
||||
|
||||
@@ -7,6 +7,10 @@ navigation:
|
||||
|
||||
# iFlow Provider
|
||||
|
||||
::alert{type="info"}
|
||||
本页属于进阶连接配置。若你已能正常创作,可先跳过。
|
||||
::
|
||||
|
||||
iFlow Provider 支持两种认证方式:OAuth 和 Cookie。
|
||||
|
||||
## 概述
|
||||
|
||||
@@ -7,6 +7,10 @@ navigation:
|
||||
|
||||
# Gemini API Key Provider
|
||||
|
||||
::alert{type="info"}
|
||||
本页属于进阶连接配置。若你已能正常创作,可先跳过。
|
||||
::
|
||||
|
||||
使用 API Key 访问 Google Gemini 服务,支持多账号负载均衡和模型排除。
|
||||
|
||||
## 概述
|
||||
|
||||
@@ -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 <api-key>`
|
||||
- 或使用兼容格式的密钥头
|
||||
|
||||
使用 `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)
|
||||
|
||||
@@ -7,6 +7,10 @@ navigation:
|
||||
|
||||
# OpenAI API
|
||||
|
||||
::alert{type="info"}
|
||||
本页是开发者进阶文档。普通创作者可直接在应用内使用,无需 API 调用。
|
||||
::
|
||||
|
||||
ProxyCast 提供完整的 OpenAI Chat Completions API 兼容。
|
||||
|
||||
## /v1/chat/completions
|
||||
|
||||
@@ -7,6 +7,10 @@ navigation:
|
||||
|
||||
# Claude API
|
||||
|
||||
::alert{type="info"}
|
||||
本页是开发者进阶文档。普通创作者可直接在应用内使用,无需 API 调用。
|
||||
::
|
||||
|
||||
ProxyCast 提供 Anthropic Claude Messages API 兼容。
|
||||
|
||||
## /v1/messages
|
||||
|
||||
@@ -7,6 +7,10 @@ navigation:
|
||||
|
||||
# 管理 API
|
||||
|
||||
::alert{type="info"}
|
||||
本页是开发者进阶文档,主要用于自动化管理与运维集成。
|
||||
::
|
||||
|
||||
ProxyCast 提供远程管理 API,用于配置和监控服务。
|
||||
|
||||
## 认证
|
||||
|
||||
@@ -7,6 +7,10 @@ navigation:
|
||||
|
||||
# Amp CLI API
|
||||
|
||||
::alert{type="info"}
|
||||
本页是开发者进阶文档。若你不涉及 Amp CLI 集成,可跳过。
|
||||
::
|
||||
|
||||
ProxyCast 提供 Amp CLI 兼容的路由端点,支持将 Amp CLI 请求路由到本地 OAuth 凭证。
|
||||
|
||||
## 概述
|
||||
|
||||
@@ -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. 当前版本号
|
||||
|
||||
@@ -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. 定期清理长期失效连接
|
||||
|
||||
@@ -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. 先切换备用连接保障创作不中断
|
||||
|
||||
@@ -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 <command> [arguments]
|
||||
```
|
||||
|
||||
建议实现 `help` 命令:
|
||||
|
||||
```bash
|
||||
$ my-tool-cli help
|
||||
MachineIdTool CLI v1.0.0
|
||||
用法: my-tool-cli <命令> [参数]
|
||||
|
||||
命令:
|
||||
get 获取当前值
|
||||
set <value> 设置新值
|
||||
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/`
|
||||
- 开放平台:插件规范、接入流程、生态能力
|
||||
- 用户指南:插件安装与使用
|
||||
|
||||
@@ -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** | 生态繁荣、用户增长 |
|
||||
- 需要开发自定义插件的团队
|
||||
- 需要对接外部系统的开发者
|
||||
- 需要建设生态能力的合作方
|
||||
|
||||
## 快速开始
|
||||
## 快速入口
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 my-6">
|
||||
<a href="/open-platform/plugins" class="block p-4 border border-gray-200 dark:border-gray-700 rounded-lg hover:border-primary-500 transition-colors">
|
||||
<h3 class="font-semibold mb-2">🔌 开发插件</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">创建自定义插件扩展 ProxyCast 功能</p>
|
||||
</a>
|
||||
<a href="/open-platform/connect" class="block p-4 border border-gray-200 dark:border-gray-700 rounded-lg hover:border-primary-500 transition-colors">
|
||||
<h3 class="font-semibold mb-2">🔗 接入 Connect</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">中转商接入一键配置功能</p>
|
||||
</a>
|
||||
<a href="/open-platform/plugin-development" class="block p-4 border border-gray-200 dark:border-gray-700 rounded-lg hover:border-primary-500 transition-colors">
|
||||
<h3 class="font-semibold mb-2">📖 插件开发指南</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">详细的插件开发文档和规范</p>
|
||||
</a>
|
||||
<a href="/open-platform/connect-integration" class="block p-4 border border-gray-200 dark:border-gray-700 rounded-lg hover:border-primary-500 transition-colors">
|
||||
<h3 class="font-semibold mb-2">📖 Connect 接入指南</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">中转商接入的详细步骤</p>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
## 相关仓库
|
||||
|
||||
| 仓库 | 说明 |
|
||||
|------|------|
|
||||
| [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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 <command> [arguments]
|
||||
```
|
||||
|
||||
建议实现 `help` 命令:
|
||||
|
||||
```bash
|
||||
$ my-tool-cli help
|
||||
MachineIdTool CLI v1.0.0
|
||||
用法: my-tool-cli <命令> [参数]
|
||||
|
||||
命令:
|
||||
get 获取当前值
|
||||
set <value> 设置新值
|
||||
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. 提供回滚策略与变更日志
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
<a href="proxycast://connect?relay=myrelay&key=USER_API_KEY">
|
||||
一键配置 ProxyCast
|
||||
</a>
|
||||
```
|
||||
|
||||
### 方式二:JavaScript SDK
|
||||
|
||||
提供更好的用户体验:
|
||||
|
||||
```html
|
||||
<script src="https://proxycast.dev/sdk/connect.js"></script>
|
||||
|
||||
<button onclick="ProxyCast.connect({ relay: 'myrelay', key: userApiKey })">
|
||||
一键配置 ProxyCast
|
||||
</button>
|
||||
```
|
||||
|
||||
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. 版本兼容说明
|
||||
|
||||
@@ -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. **异步处理** - 复杂逻辑放到后台队列
|
||||
1. 统计成功率与取消率
|
||||
2. 跟踪错误类型占比
|
||||
3. 区分渠道来源效果
|
||||
|
||||
+36
-133
@@ -1,149 +1,52 @@
|
||||
---
|
||||
title: ProxyCast - 把你的 AI 客户端额度用到任何地方
|
||||
description: 一款基于 Tauri 的桌面应用,将 Kiro、Gemini CLI、Qwen 等 AI 客户端凭证转换为标准 OpenAI/Claude 兼容 API
|
||||
title: ProxyCast 文档中心
|
||||
description: 创作类 AI Agent 平台文档,从灵感到发布的一站式指南
|
||||
navigation: false
|
||||
---
|
||||
|
||||
<div class="max-w-4xl mx-auto">
|
||||
# ProxyCast 文档中心
|
||||
|
||||
<div class="text-center py-8">
|
||||
<h1 class="text-5xl font-bold text-primary-600 mb-4">ProxyCast</h1>
|
||||
<p class="text-3xl font-semibold text-gray-700 dark:text-gray-300 mb-2">把你的 AI 客户端额度用到任何地方</p>
|
||||
<p class="text-xl text-gray-600 dark:text-gray-400 mb-4">一款基于 Tauri 的桌面应用,将 Kiro、Gemini CLI、Qwen 等 AI 客户端凭证转换为标准 OpenAI/Claude 兼容 API</p>
|
||||
<p class="text-base text-gray-500 dark:text-gray-500 mb-10">凭证池管理 • 智能路由 • 协议转换 • 容错机制</p>
|
||||
<div class="flex gap-4 justify-center flex-wrap">
|
||||
<a href="/introduction/quickstart" class="inline-block px-8 py-3 bg-primary-600 text-white font-medium rounded-lg hover:bg-primary-700 transition-colors">快速开始</a>
|
||||
<a href="https://github.com/aiclientproxy/proxycast" target="_blank" class="inline-block px-8 py-3 border-2 border-gray-300 dark:border-gray-600 font-medium rounded-lg hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors">GitHub</a>
|
||||
</div>
|
||||
</div>
|
||||
ProxyCast 是创作类 AI Agent 平台。
|
||||
你可以在同一个工作台里完成对话、创作、图片生成、项目沉淀与资源复用。
|
||||
|
||||
<div class="text-center py-3 px-4 mb-6 bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg">
|
||||
<p class="text-yellow-800 dark:text-yellow-200">
|
||||
<strong>⚠️ 免责声明:</strong> 本工具仅限于个人合法使用,严禁用于非法盈利目的。初衷是帮助用户充分利用已订阅的 AI 服务 Token。
|
||||
<a href="/legal/disclaimer" class="text-primary-600 hover:underline ml-1">查看完整声明</a>
|
||||
</p>
|
||||
</div>
|
||||
## 从这里开始
|
||||
|
||||
## ✨ 核心特性
|
||||
1. [概述](/introduction/overview):先了解平台能帮你完成什么
|
||||
2. [安装指南](/introduction/installation):安装到本地桌面
|
||||
3. [快速开始](/introduction/quickstart):3 步走完首次创作
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 my-8">
|
||||
<div class="p-6 border border-gray-200 dark:border-gray-700 rounded-lg">
|
||||
<h3 class="text-xl font-semibold mb-3">🔑 凭证池管理</h3>
|
||||
<p class="text-gray-600 dark:text-gray-400">支持多种 AI 客户端凭证的统一管理,包括 Kiro、Gemini CLI、Qwen、Claude Code 等,自动检测和刷新 OAuth Token。</p>
|
||||
</div>
|
||||
<div class="p-6 border border-gray-200 dark:border-gray-700 rounded-lg">
|
||||
<h3 class="text-xl font-semibold mb-3">🔀 智能路由</h3>
|
||||
<p class="text-gray-600 dark:text-gray-400">基于模型名称的请求路由,支持负载均衡、优先级配置、健康检查和自动故障转移。</p>
|
||||
</div>
|
||||
<div class="p-6 border border-gray-200 dark:border-gray-700 rounded-lg">
|
||||
<h3 class="text-xl font-semibold mb-3">🛡️ 容错配置</h3>
|
||||
<p class="text-gray-600 dark:text-gray-400">内置熔断器、重试机制、超时控制,确保服务稳定性,优雅处理 API 故障。</p>
|
||||
</div>
|
||||
<div class="p-6 border border-gray-200 dark:border-gray-700 rounded-lg">
|
||||
<h3 class="text-xl font-semibold mb-3">⚡ 配置切换</h3>
|
||||
<p class="text-gray-600 dark:text-gray-400">一键切换 Claude Code、Codex、Gemini CLI 等客户端配置,快速适应不同使用场景。</p>
|
||||
</div>
|
||||
<div class="p-6 border border-gray-200 dark:border-gray-700 rounded-lg">
|
||||
<h3 class="text-xl font-semibold mb-3">📊 监控统计</h3>
|
||||
<p class="text-gray-600 dark:text-gray-400">实时监控请求统计、Token 使用追踪、详细的请求日志和性能指标。</p>
|
||||
</div>
|
||||
<div class="p-6 border border-gray-200 dark:border-gray-700 rounded-lg">
|
||||
<h3 class="text-xl font-semibold mb-3">🔌 API 兼容</h3>
|
||||
<p class="text-gray-600 dark:text-gray-400">完整支持 OpenAI Chat Completions API 和 Claude Messages API,无缝集成现有工具。</p>
|
||||
</div>
|
||||
</div>
|
||||
## 九大创作主题
|
||||
|
||||
## 🎯 支持的 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!"}]
|
||||
}'
|
||||
```
|
||||
|
||||
## 📖 文档导航
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 my-8">
|
||||
<a href="/introduction/overview" class="block p-4 border border-gray-200 dark:border-gray-700 rounded-lg hover:border-primary-500 transition-colors">
|
||||
<h3 class="font-semibold mb-2">📋 概述</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">了解 ProxyCast 的核心功能和价值</p>
|
||||
</a>
|
||||
<a href="/introduction/installation" class="block p-4 border border-gray-200 dark:border-gray-700 rounded-lg hover:border-primary-500 transition-colors">
|
||||
<h3 class="font-semibold mb-2">📥 安装指南</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">下载并安装 ProxyCast</p>
|
||||
</a>
|
||||
<a href="/introduction/quickstart" class="block p-4 border border-gray-200 dark:border-gray-700 rounded-lg hover:border-primary-500 transition-colors">
|
||||
<h3 class="font-semibold mb-2">🚀 快速开始</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">5 分钟内完成首次 API 调用</p>
|
||||
</a>
|
||||
<a href="/providers/overview" class="block p-4 border border-gray-200 dark:border-gray-700 rounded-lg hover:border-primary-500 transition-colors">
|
||||
<h3 class="font-semibold mb-2">🔧 Provider 配置</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">配置各种 AI 服务提供商</p>
|
||||
</a>
|
||||
<a href="/api-reference/overview" class="block p-4 border border-gray-200 dark:border-gray-700 rounded-lg hover:border-primary-500 transition-colors">
|
||||
<h3 class="font-semibold mb-2">📚 API 参考</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">完整的 API 端点文档</p>
|
||||
</a>
|
||||
<a href="/troubleshooting/common-issues" class="block p-4 border border-gray-200 dark:border-gray-700 rounded-lg hover:border-primary-500 transition-colors">
|
||||
<h3 class="font-semibold mb-2">🔍 故障排除</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">常见问题和解决方案</p>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
## 🌐 开放平台
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 my-8">
|
||||
<a href="/open-platform/overview" class="block p-4 border border-gray-200 dark:border-gray-700 rounded-lg hover:border-primary-500 transition-colors">
|
||||
<h3 class="font-semibold mb-2">🔌 插件系统</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">通过插件扩展 ProxyCast 功能,支持工具类、Hook 类等多种插件类型</p>
|
||||
</a>
|
||||
<a href="/open-platform/connect" class="block p-4 border border-gray-200 dark:border-gray-700 rounded-lg hover:border-primary-500 transition-colors">
|
||||
<h3 class="font-semibold mb-2">🔗 ProxyCast Connect</h3>
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400">中转商生态合作方案,一键配置 API Key,提升用户转化率</p>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
## 🤝 社区与支持
|
||||
|
||||
- **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) 开源。
|
||||
|
||||
</div>
|
||||
请在合法合规前提下使用本产品。
|
||||
完整说明见 [免责声明](/legal/disclaimer)。
|
||||
|
||||
+75
-234
@@ -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)
|
||||
|
||||
@@ -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 (
|
||||
<div>
|
||||
<WorkflowStatusPanel
|
||||
sessionId={sessionId}
|
||||
isWorkflowActive={workflowState.isWorkflowActive}
|
||||
isWorkflowInitialized={workflowState.isWorkflowInitialized}
|
||||
messageCount={workflowState.messageCount}
|
||||
visualOperationCount={workflowState.visualOperationCount}
|
||||
onInitializeWorkflow={handleInitWorkflow}
|
||||
onFinalizeWorkflow={workflowActions.finalizeSession}
|
||||
/>
|
||||
{/* 其他聊天组件 */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 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 的工作效率和可靠性,让复杂任务的执行更加有序和可控。
|
||||
Generated
+29
-15
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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<RwLock<Option<ProviderConfig>>>,
|
||||
/// 凭证桥接器
|
||||
credential_bridge: CredentialBridge,
|
||||
/// Agent 初始化状态缓存(避免每次都获取锁)
|
||||
initialized_cache: Arc<AtomicBool>,
|
||||
/// Provider 配置状态缓存(避免每次都获取锁)
|
||||
provider_configured_cache: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -127,6 +127,29 @@ pub fn get_session_sync(db: &DbConnection, session_id: &str) -> Result<SessionDe
|
||||
let messages =
|
||||
AgentDao::get_messages(&conn, session_id).map_err(|e| format!("获取消息失败: {e}"))?;
|
||||
|
||||
let tauri_messages: Vec<TauriMessage> = 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<SessionDe
|
||||
updated_at: chrono::DateTime::parse_from_rfc3339(&session.updated_at)
|
||||
.map(|dt| dt.timestamp())
|
||||
.unwrap_or(0),
|
||||
messages: messages
|
||||
.into_iter()
|
||||
.map(|message| convert_agent_message(&message))
|
||||
.collect(),
|
||||
messages: tauri_messages,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -170,7 +190,7 @@ pub fn delete_session_sync(db: &DbConnection, session_id: &str) -> 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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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<AsterMessageContent>)
|
||||
if let Ok(aster_contents) = serde_json::from_str::<Vec<serde_json::Value>>(content_json) {
|
||||
let mut text_parts: Vec<String> = Vec::new();
|
||||
let mut parts: Vec<ContentPart> = 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -464,15 +464,13 @@ pub fn cleanup_legacy_api_key_credentials(conn: &Connection) -> Result<usize, St
|
||||
})
|
||||
.map_err(|e| format!("查询旧凭证失败: {e}"))?;
|
||||
|
||||
for row_result in rows {
|
||||
if let Ok((uuid, name, provider_type)) = row_result {
|
||||
tracing::info!(
|
||||
"[清理] 将删除旧凭证: {} (name: {}, type: {})",
|
||||
uuid,
|
||||
name.as_deref().unwrap_or("未命名"),
|
||||
provider_type
|
||||
);
|
||||
}
|
||||
for (uuid, name, provider_type) in rows.into_iter().filter_map(|row_result| row_result.ok()) {
|
||||
tracing::info!(
|
||||
"[清理] 将删除旧凭证: {} (name: {}, type: {})",
|
||||
uuid,
|
||||
name.as_deref().unwrap_or("未命名"),
|
||||
provider_type
|
||||
);
|
||||
}
|
||||
|
||||
// 删除旧的 API Key 凭证
|
||||
|
||||
@@ -40,6 +40,17 @@ pub fn init_database() -> Result<DbConnection, String> {
|
||||
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)?;
|
||||
|
||||
@@ -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<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub input_schema: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AnthropicMessagesRequest {
|
||||
pub model: String,
|
||||
pub messages: Vec<AnthropicMessage>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub max_tokens: Option<u32>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub system: Option<serde_json::Value>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub temperature: Option<f32>,
|
||||
#[serde(default)]
|
||||
pub stream: bool,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub tools: Option<Vec<AnthropicTool>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub tool_choice: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
#[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<AnthropicContentBlock>,
|
||||
pub model: String,
|
||||
pub stop_reason: Option<String>,
|
||||
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<String>,
|
||||
}
|
||||
//!
|
||||
//! Types re-exported from `aster-models` crate (single source of truth).
|
||||
pub use aster_models::anthropic::*;
|
||||
|
||||
@@ -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<String>,
|
||||
}
|
||||
|
||||
#[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<ContentPart>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ChatMessage {
|
||||
pub role: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub content: Option<MessageContent>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub tool_calls: Option<Vec<ToolCall>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub tool_call_id: Option<String>,
|
||||
/// 推理内容(DeepSeek R1 等模型的思维链内容)
|
||||
/// DeepSeek Reasoner 在 Tool Calls 场景下要求此字段
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub reasoning_content: Option<String>,
|
||||
}
|
||||
|
||||
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::<Vec<_>>()
|
||||
.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<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub parameters: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
/// 工具定义
|
||||
///
|
||||
/// 支持多种工具类型:
|
||||
/// - `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<ChatMessage>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub temperature: Option<f32>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub max_tokens: Option<u32>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub top_p: Option<f32>,
|
||||
#[serde(default)]
|
||||
pub stream: bool,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub tools: Option<Vec<Tool>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub tool_choice: Option<serde_json::Value>,
|
||||
/// 思维链强度:none, low, medium, high
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub reasoning_effort: Option<String>,
|
||||
}
|
||||
|
||||
#[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<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub tool_calls: Option<Vec<ToolCall>>,
|
||||
}
|
||||
|
||||
#[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<Choice>,
|
||||
pub usage: Usage,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct StreamDelta {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub role: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub content: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub tool_calls: Option<Vec<ToolCall>>,
|
||||
}
|
||||
|
||||
#[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<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ChatCompletionChunk {
|
||||
pub id: String,
|
||||
pub object: String,
|
||||
pub created: u64,
|
||||
pub model: String,
|
||||
pub choices: Vec<StreamChoice>,
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 图像生成 API 数据模型
|
||||
// 图像生成 API 数据模型 (ProxyCast 特有)
|
||||
// ============================================================================
|
||||
|
||||
/// OpenAI 图像生成请求
|
||||
|
||||
@@ -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<Option<Workspace>, String> {
|
||||
pub fn get_by_path(&self, root_path: &Path) -> Result<Option<Workspace>, 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)
|
||||
|
||||
@@ -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:?}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 ====================
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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()),
|
||||
}],
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<ChatMode>,
|
||||
) -> Result<Vec<SessionResponse>, 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<SessionResponse> = 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<SessionResponse> = 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<SessionResponse, 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 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<bool, 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 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<i32>,
|
||||
) -> Result<Vec<ChatMessage>, 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<std::time::Instant> = 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 {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -825,8 +825,7 @@ export const EmptyState: React.FC<EmptyStateProps> = ({
|
||||
<ContentWrapper>
|
||||
<Header>
|
||||
<MainTitle>
|
||||
{themeHeadline.lead} <br />
|
||||
<span>{themeHeadline.focus}</span>
|
||||
{themeHeadline.lead}<span>{themeHeadline.focus}</span>
|
||||
</MainTitle>
|
||||
</Header>
|
||||
|
||||
@@ -1199,7 +1198,7 @@ export const EmptyState: React.FC<EmptyStateProps> = ({
|
||||
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"
|
||||
>
|
||||
开始生成
|
||||
<ArrowRight className="h-4 w-4 ml-2" />
|
||||
|
||||
@@ -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)}`);
|
||||
}
|
||||
},
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user