Cevzi API 发布交接 源码:f077d004b1c3cdfb40d2a6c33e810df5a358f0ce 后端版本:20261109T074725Z 数据库 schema:160 # API 四项整改交接 本文件说明后端实现与接入变化。具体上线版本、验证结果以发布回执为准,不将代码完成视为线上验收通过。 ## 1. 普通聊天、错误恢复 原 POST /api/v1/employees/:id/chat、任务查询、重试和 SSE 路径继续使用,保留原请求字段和事件序号。 Go 返回的旧式错误字符串会被 OpenAI SDK 解包成字符串。Python 现在识别已知错误码,不再全部归为 AGENT_UPSTREAM_FAILED。仅在原物理调用完整返回、用量及售价结算成功、未输出答案、未执行业务工具且原截止时间有余量时,内部模型代理允许一次格式重生成;未知计费、网络中断和部分输出不自动重放。历史已扣费任务不自动重新执行。 交接中的 MAC 内置服务问题仍需客户端技术员处理:peerAsk 的 productChat 恢复分支、驱动拒绝、编辑消息重试时的游标保留。这些代码位于已打包客户端,不会因 API 更新而改写。 ## 2. 人民币余额与动态售价 用户充值人民币余额。新模型调用的报价使用 Admin 当时已生效的已发布模型售价,沿用输入、输出、缓存、阶梯或其他已配置计量维度;存在该用户、该模型的单独定价时优先使用该配置。不使用固定人民币兑换 Token 比例,也不在程序中另加固定加价率。模型发布和用户单独定价沿用现有 Admin 流程;未发布草稿不参与调用报价。 每次物理调用保存售价快照。普通聊天的新消息受理时解析该模型当前已发布版本,因此 Admin 发布新通用售价后,下一条新请求使用新版本售价,不需要重绑员工。已受理的任务及其幂等恢复保留原模型版本,该任务后续的通用报价也按原版本;用户专属价由每次新物理报价读取。已冻结报价的调用仍按原快照结算,不用新售价重算历史消费。充值由原支付服务核验成功到账,模型调用先预留、按实际用量结算、释放差额,同一凭据重复结算不重复扣款。未知费用保留预留,不按零消费释放。跨月迟到结算归属原调用月份。 资金来源按整次调用的预留选择:套餐 Token(含原规则计入的注册赠送及人工补发额度)和套餐模型费用上限都能完整覆盖本次预留时,优先使用套餐;任一不足时,尝试由现金余额承担整笔预留。单次调用不分段混抵,不先用尽剩余套餐再从现金扣差额。未用套餐额度保留;由现金承担的调用不重复消耗套餐、赠送或人工补发额度。现金不足以覆盖整笔预留时,该次模型调用仍会被拒绝。 原订阅资格约束继续生效。订阅过期时,即使人民币余额充足,模型执行仍返回 PLAN_UNAVAILABLE,额度原因是 SUBSCRIPTION_EXPIRED;充值余额不等于续订套餐。任务受理也不代表供应商已派发或执行成功,真实模型派发仍需通过售价和足额预留检查。 前端需要同步以下字段含义与恢复行为;本次不更换接口路径或请求字段: - GET /api/v1/usage/summary?quotaVersion=1 继续返回 quota-ux/v1。金额和数量保持十进制字符串,余额、预留及可用金额在同一只读快照内计算。quota.balance 的 unit=MICRO_CNY、unitsPerWhole="1000000";quota.usage.modelCost 的单位是 CNY,前端应按各自 unit 显示。 - quota.balance.modelUsageRelation=CONNECTED 表示人民币钱包已接入模型计费,不代表当前有余额、订阅有效或模型一定可执行。旧积分钱包不自动兑换 Token;不要把旧 credits 的数值并入人民币模型余额。订阅过期时保留 PLAN_UNAVAILABLE/SUBSCRIPTION_EXPIRED 的处理,不因 CONNECTED 或充值成功自动消除订阅错误。 - 预付余额参与额度说明时,不同模型及输入输出售价没有统一 Token 分母。quota.usage.tokens 的 recorded/settled/reserved 继续表达记录用量、已确认用量和预留;limit/remaining 返回 UNKNOWN,quota.usage.tokenLimitBasis=PLAN_THEN_MODEL_SALE_PRICE_BALANCE。前端显示人民币可用金额及实际 Token 用量,不将 UNKNOWN 当作 0 或无限额度,不计算虚假的 Token 百分比。套餐 Token 已耗尽时,未使用的套餐费用上限不算作可消费人民币。 - 充值核验成功只增加余额,不会自动重发历史请求。用户重试应沿用原请求身份、消息及附件;已受理任务继续使用原任务查询和恢复入口,不因充值或调价创建另一任务。余额足够受理任务后,若实际调用的整笔预留仍不足,应显示后端返回的额度限制,不能仅据余额大于零显示执行成功。 ### 套餐用量与错误提示 - 用量菜单与套餐用量进度取 `GET /api/v1/usage/summary` 的 `display.usedPercent`。带 `quotaVersion=1` 时取 `quota.usage.display.usedPercent`。百分比以 0 到 100 的数值表示常规进度,按当月已结算的套餐 Token 计算,四舍五入到两位小数。降档后已用量可能高于新上限。无限或没有有效正数上限时返回 `null`,已结算 Token 仍可从 `settledTokens` 读取。套餐未生效时版本化响应可以省略 `display`。 - 菜单和用户套餐进度只显示上述套餐用量,套餐卡片隐藏模型费用额度。旧费用和预留字段供账务、兼容读取及额度说明,界面不根据它们显示“用量待核实”,也不从充值金额推算 Token。已有接口路径和请求参数沿用原契约。 - HTTP 错误与 SSE 失败事件用 `message` 展示中文,聊天历史用 `errorMessage`,运行快照 `GET /api/v1/runs/{id}/snapshot` 用新增的 `message`。机器码继续用于判断流程。原失败的 `details.quota.reason=QUOTA_RESERVED` 表示发起当时有额度预留。 - 同步收到同一运行的 SSE 失败和快照时,使用 runId 合并失败状态。原任务和消息保留可查询状态。 ## 3. 同一智能体或群只保留一个逻辑聊天 普通私聊按用户、租户及智能体收敛为一个固定会话,群聊按群收敛。省略 conversationId、传新候选 ID 或调用原群会话创建入口都不再产生新的聊天分支。历史消息、会话行、任务、运行、资产及财务引用保留原始记录。WORKBENCH、群执行及成员协作的私有运行上下文不合并进个人聊天。 历史自有 conversationId 继续作为别名访问,历史消息及上下文按时间汇合。使用已存在旧别名的聊天响应保留该别名的展示范围;新候选 ID 返回真实固定 ID。前端应使用后端返回的 conversationId,按消息 ID 去重,停止主动创建和展示多对话入口。工作引用仍保留原执行身份,不用展示别名重新拼接 taskId/runId。 群内已有记忆、摘要及可访问的产物回执可从固定聊天继续读取,原有上下文条数和长度预算保留。新群工作使用统一幂等键;历史请求改用自有旧别名或省略会话时,优先恢复原工作和原事件,不重建任务。旧键对应多个不同历史任务且无法唯一恢复时返回 IDEMPOTENCY_CONFLICT。定时工作、语音及协作任务继续保留原执行会话和权限证明。 转交回执的导航使用接收方固定聊天及对应签名游标,原消息和私有转交证明继续保留原会话。前端应使用回执返回的 targetScope、targetHistoryCursor 跳转,不用原执行会话 ID 自行拼接游标。 旧会话日志序号不能直接当作固定会话日志序号。服务端验证旧签名后返回既有 409 SYNC_RESNAPSHOT_REQUIRED,前端应清理该范围的旧游标并重新读取快照;不能重新提交用户消息。chat-submissions 列表的新不透明游标采用时间和 ID 排序,旧 v1 游标也返回该重取快照错误。请求、事件及业务 ID 不因重取快照改变。 ## 4. 理解上下文、管理目录和公开数据 短确认承接最近未完成请求及其明确范围;已完成或已取消事项不因“是的”重新执行。管理目录返回真实自有对象及总数,并明确是否截断;可执行候选不再冒充全部智能体。对象归属、主智能体保护及现有删除权限继续由后端校验,成功只能依据真实执行回执报告。 专业分析不再被普通闲聊的 80 字限制压缩。涉及当前公开市场、价格、新闻和政策时,可使用后端已有的有界公开 HTTPS 检索与读取,无需电脑权限;来源日期与查询时间分开描述。网页是资料,不能授予平台写权限。网页读取后只允许继续读取或总结真实来源,不能把网页内容变成删除、发消息或其他写操作。未核验数据不能冒充最新行情。 原动作批次上限及混合检索与写入的限制继续生效。没有新增无限批量删除权限;本次截图只用于复现,未据此删除真实账号资源。真实支付、金融数据质量和已打包客户端能力应分别依据对应真实验收记录判断。 ## 5. 真实验收发现的追加修复 内部模型代理的结构化结果校验实际返回 MODEL_STRUCTURED_OUTPUT_INVALID。Python 将这个固定错误码规范为已有 MODEL_INVALID_RESPONSE,沿用前述严格的一次格式重生成条件。没有完整结算凭据、已输出答案、已执行工具或原截止时间不足时仍不自动重试;不据已结算账本推断原始错误内容。 当前已发布技能目录有 876 项,通用角色创建传输约 286KB,超过内部原有 128KiB、500 项边界。仅角色编译、预览与技能目录匹配的内部接口改用 1MiB、2000 项独立上限,保留完整目录和先鉴权规则。APP/MAC 原有创建来源继续沿用原契约,公开员工创建接口地址和请求字段不变。 公开网页检索允许从本轮用户原文中选择连续的中文、英文关键词组合,仍不改写查询、不外发历史或私有目录,保留原有候选字节数和最多三次读取限制。无关结果不能作为行情依据;模型应在剩余读取预算内换用原文中的核心主题查询并核验正文。该能力不等于已接入证券实时行情服务,没有取得真实数据时继续明确说明缺失。 图片提示长度使用供应商适配器的实际限制。GET /api/v1/creative/capabilities 的 models 新增可选 promptMaxCharacters,按 mode 返回已知的 Unicode 字符数上限;群内给模型的目录按当前 mode 提供数值。字段缺失表示未知,不能当作无限。当前 MiniMax 原生图片模型对应上限为 1500。 模型规划应在真实上限内紧凑表达已确认要求,不直接截断长提示或降低人物、画幅等规格。自动路由继续只使用已发布、已验证、已定价且当前有权限的候选。无法容纳原提示且没有其他合格候选时,保留 MEDIA_PROMPT_TOO_LONG,不再一律显示 MEDIA_MODEL_UNAVAILABLE;显式选模和锁定规则保留。 前端技术员需要识别 MEDIA_PROMPT_TOO_LONG 及 retryable=false。提示长度拒绝沿用 HTTP 409,聊天沿用原 SSE 失败事件与群错误回执;有明确限额时 details.mediaPrompt 返回 maxCharacters、actualCharacters、unit=UNICODE_CODE_POINTS。选模时的权限拒绝保留 HTTP 403 和原权限码(如 MODEL_DATA_SCOPE_DENIED),权限服务不可用保留 HTTP 503 / MODEL_POLICY_UNAVAILABLE,不能泛化为长度问题或无供应商。显示服务端说明和实际限制,保留用户原文、已有产物及原任务记录;不能以原输入盲目重发或显示已生成成功。本次没有更换接口路径或添加必填请求字段。 ## 6. 公开检索的普通聊天来源与失败说明 普通聊天受理和预编译上下文都保留本轮原话,检索目录的 currentUserMessage 使用这份原话。聊天历史、角色说明和任务摘要不能替代来源;查询与引用继续受原消息、真实读取回执及既有权限校验约束。 用户要求先查公开资料时,普通聊天提示要求先执行公开搜索或读取来源,再根据实际回执回答。普通对话的搜索词未逐字来自本轮原话时,已有的一次格式修复会提供可选的原文片段。行情数字和来源链接以实际读取结果为准。 指定单一日期的 A 股大盘收盘查询由后端执行。聊天原话用于判定范围,站内搜索只传交易日期和固定的公开检索词。后端读取新华财经同日盘后收评原文,逐项返回上证指数收盘点位、涨跌幅、沪深两市成交额和原文链接,缺项单独列出。成交额注明报道口径。客户端沿用现有聊天接口及回执格式,无需改变问法或提交额外参数。 公开读取的固定错误码为 WEB_READ_SCOPE_DENIED(权限或范围拒绝)、WEB_READ_FAILED(已有读取未通过核验)、WEB_READ_UNAVAILABLE(读取服务不可用)、WEB_FINAL_CHECK_UNAVAILABLE(最终核验服务不可用)。内部回调分别使用 403、409、503、503;公开聊天仍沿用 SSE run.failed 及任务查询返回错误码,不能把 SSE 的 HTTP 200 视为任务成功。上述回调错误不会触发额外的格式重生成或读取重试,也不能跳过引用校验。只有核验成功响应中 valid=false 的引用格式问题继续沿用已有的一次格式修复。 平台删除动作回执使用“删除”说明已执行的 DELETE 操作,避免删除成功后笼统显示“更新”。操作权限、幂等和数据保留规则不变。具体发布版本及线上金融数据是否可核验,仍以实际验收记录为准。 ## 7. 普通聊天的文档读取与结果恢复 POST /api/v1/employees/:id/chat 继续使用原 message、attachments(已上传的资产 UUID)、conversationId、idempotencyKey 和 retryOfRunId。未请求电脑操作的 CHAT 对话中,现有读取器支持的 DOCX、XLSX 等附件进入受权正文读取及普通 Product 任务,不再仅因它是 Office 文件而强制走 Fusion。显式电脑操作、其他会话用途、未支持文件及已存在的 Fusion 幂等请求继续保留各自原通道;上传文件不授予电脑权限。 读取仍检查当前用户、租户、READY 状态、实际字节、大小及 SHA。提取正文保留已有数量和字符边界;截断时模型必须说明读取范围,不能声称已读取全文。原资产不修改。混合文本、文档与媒体分别传入原执行上下文,历史保留原附件 UUID 及顺序,不把正文另写入公开消息元数据。失败任务沿原 retryOfRunId 恢复原来源,同一重试显式携带或省略原附件应恢复同一请求,不再因内部附件分型产生另一份幂等身份;变更来源仍拒绝。 正常文档请求的格式、损坏和大小错误使用已有 INVALID_CHAT_DOCUMENT、CHAT_DOCUMENT_LIMIT 等固定码及原失败事件,不归为电脑附件桥接权限不足。ATTACHMENT_UNAVAILABLE 的用户说明统一使用“附件”;错误码和权限边界不变。HTTP 200 的 SSE 连接不代表执行成功,应读取 run.completed、run.failed 等终态。 主智能体个人聊天中,自动选模遇到无法处理本轮图片的默认模型时,按图片任务用途选择已发布的候选。文字识别可选择专用 OCR,普通看图走视觉候选。模型额度、图片归属和已付费识别结果的重放校验继续生效。 文档生成进度不等于文件已生成。已受理的原任务在断线后使用 GET /api/v1/chat-runs/:runId/events?after=<已收到的序号> 续读,按原 runId、sequence 去重。agent.product_action.completed 的 receipt 和 run.completed 的 productActions 使用已有 document.generate / document.download 产物回执;会话历史 GET /api/v1/conversations/:id/messages 使用 metadataJson.productActions。文件继续通过 GET /api/v1/assets/:id 与 /api/v1/assets/:id/content 受权读取。已有文件无需重新调用模型生成;较晚的新任务不能替代原任务的恢复身份。 公开历史读取对已撤回的旧 media.compose 回执做精确兼容:保留原消息和事件,但不把缺少可核验任务的旧动作投影为可信新执行结果;同一历史中的有效 Word 文件继续正常投影。执行入口、模型可复用回执、其他未知动作及已知动作的损坏校验不因此放宽。本次不新增接口路径、必填字段、自动付费重放或新的执行权限。 ## 8. 桌面单聊内置浏览器 兼容桌面客户端在 `POST /api/v1/employees/:id/chat` 增加可选 `builtinBrowser`。其中 `contract` 为 `cevzi-builtin-browser/v1`,`mode` 为 `BUILT_IN`,`contextId` 为本轮 UUID,`available` 为布尔值。后端把它绑定到原认证会话、用户、租户、员工、会话和运行。主智能体及普通员工的个人对话均使用这份绑定。浏览器工具按本轮需要发现,普通问答沿用原模型回答。 原 Product SSE 新增 `browser.request`。`run.started` 之后按实际工具进度发送,`builtinBrowser` 内含 `contract`、`contextId`、`requestId`、`method`。`tools/list` 查询当前客户端的实际 OpenAI function 目录,`tools/call` 使用其中名称和参数结构。用户的授权、取消和浏览器接管继续由原执行面处理。目录和网页内容只作为本轮资料。 客户端通过 `POST /api/v1/chat-runs/:id/browser-results` 回传已发请求的结果。接受后返回无正文的 HTTP 204,同内容重传也返回 204,异内容返回 409。正文最多 33 MiB,单条文字最多 50 KiB,单轮图片 data URL 编码累计最多 32 MiB。超过接收范围时返回 413。当前文本路径无法读取工具图片时返回 `BUILTIN_BROWSER_IMAGE_MODEL_REQUIRED`。 断开后继续使用原 `GET /api/v1/chat-runs/:id/events?after=<已确认序号>`。已持久接受的工具请求从续读中过滤,其余事件保留原序号。旧客户端轮次失效时可对同一待处理请求提交 `BUILTIN_BROWSER_SCOPE_MISMATCH` 终止回执。授权拒绝、操作未确认和取消以原运行终态结束。浏览器已实际发出工具请求的运行通过原 SSE 恢复,用户检查页面后可发起一轮新操作。 浏览器工具进入执行后,最终回复以已确认的实际结果为依据。执行时间遵循原运行预算,工具等待可取消。写入和消费回执使用短事务,等待在事务外进行。该协议适用于桌面个人对话。实际客户端联调和生产版本以本次发布回执为准。 已确认的浏览器操作回执可用于一次模型终答格式修正,修正沿用本轮预算和原回执。服务端记录终答校验的字段名和步骤序号。浏览器请求、回执及续读接口沿用现有协议。 ## 9. 主智能体承接已建立的群 主智能体的普通个人对话继续使用 `POST /api/v1/employees/:id/chat`。后端根据同一业务上下文中已提交的建群回执、当前有效的群与成员判断能否复用,并校验归属、租户和个人会话。名称和成员用于辅助确认,多个候选需要用户明确选择。另建同名团队需要本轮真实的另建要求。 复用在原事件和 `productActions` 中返回真实 `groupId`,可选 `reused=true` 表示已沿用该群。同一私聊中对原群执行 `group.member.add`,且所选成员全已在群内时,也会返回 `reused=true`,回复显示成员已在群内。每条用户指令仍有自己的运行身份,同请求重放使用原幂等记录。已归档的群退出复用范围。 用户交办具体工作时可在原群安排任务,并用已有通知路径回到发起私聊。群主通过第 10 节的设置接口管理常驻负责人和自动私聊汇报。 ## 10. 群常驻负责人和自动私聊汇报 群主可使用 `GET /api/v1/groups/{id}/report-settings` 读取设置,使用同路径 `PUT` 提交修改。两个方法使用现有 Bearer 登录和群权限校验。返回 HTTP 200,包含 `leaderEmployeeId`(UUID 或 null)、`autoReport`(布尔值)和 `revision`(整数)。历史群默认返回 null、false 和 0。 PUT 要求同时提供 `leaderEmployeeId`、`autoReport` 和 `expectedRevision`。负责人必须是本群中仍有效且由群主拥有的智能体。显式 null 清除负责人,此时 autoReport 必须为 false。不同内容的过期修订返回 409 `GROUP_REPORT_REVISION_CONFLICT`,客户端重新 GET 后再提交。重复提交相同内容返回当前设置。非本群有效负责人的提交返回 409 `GROUP_REPORT_LEADER_INVALID`,无设置权限返回 403,群不可访问返回 404,格式错误返回 400。 设置对新建的群工作任务生效,任务已明确指定的执行负责人仍优先。对默认路由,已设置的有效负责人优先;负责人离开后沿用原群任务路由。开启汇报后,每个任务在核验完成并进入 COMPLETED 时,将保存的结果摘要发送一次到群主与该负责人的固定个人对话。正文最多摘录原结果前 2000 个字符,历史消息 metadataJson 包含 `groupId`、`groupWorkTaskId` 和 `groupSourceMessageId`。群主可据此追溯完整结果。交付使用原任务的有效会话及既有对话同步,其他群成员不能读取这条私聊。修改设置或负责人离开会停发尚未交付的旧任务汇报。 日常群聊、任务的中间状态和原单项任务通知沿用已有规则。原群消息、成员和群工作接口保持兼容。新增设置入口须由客户端技术员按此契约接入。 ## 11. 主智能体过期运行收尾 只读答复已在 Control 保存、Product 完成阶段已返回且未落库时,后端在截止时间之后接续收尾,写入答复并释放会话占用。续读仍使用原 runId,原回执和已提交的模型终态保留。