Skip to content

PLAN-FNOS-027 ZCode Start Plan 模型接入与账号额度 ​

字段内容
计划编号PLAN-FNOS-027
计划日期2026-10-24
对应需求FNOS-027 ZCode Start Plan 模型接入与账号额度
本轮功能FNOS-027-01、FNOS-027-02、FNOS-027-03、FNOS-027-04、FNOS-027-05、FNOS-027-06、FNOS-027-07、FNOS-027-08
计划状态已完成(自研 HTTP 通道在 DSH Web 与 DSH Desktop 均验证通过;纯文本 / 工具调用 / 多轮工具结果 / 图文 / 智能体团队 / 思考等级 / 限流退避已实测;发布相关任务按插件未发布单列)

计划目标 ​

按 FNOS-027 的功能编号实现一个不依赖 fnOS 宿主桥接的 DSH 插件 @tnnevol/dsh-zcode:

  • FNOS-027-01:宿主侧的 ZCode 账号登录(BigModel 国内 / Z.ai 海外两个家族)——浏览器在上游授权页完成登录后回跳到插件同源回调,宿主用授权码换取凭据并持久化,回调走 state 校验;不提供 API Key 登录;
  • FNOS-027-02:把账号权益(额度条目的 capabilities)作为模型清单真源,注册 DSH 模型供应商 ZCode(路由 dsh-zcode),并以稳定设备标识满足上游额度接口的必填头要求;
  • FNOS-027-03:按上游客户端配置把上下文窗口、最大输出、图片输入与思考等级投影到模型,缺失时使用保守默认值;
  • FNOS-027-04:Start Plan 回合由插件自己收发 Anthropic Messages 完成——请求的 system 必须按上游要求发出两段独立文本块(42 字符身份行 + 1211 字符行为提示词前缀),并按官方补齐 metadata / tool_choice / thinking / output_config 四个附加字段;业务码(3001 / 3006 / 3007 / 1113 / 1214 / 3012)映射为可读中文诊断;
  • FNOS-027-05:按「模型 × 周期」展示额度窗口与套餐,保留上游粒度,缺失显示未知;进度值按「总剩余 / 总量」聚合;
  • FNOS-027-06、FNOS-027-07:插件详情页(账号、额度、目录、设置)、对话输入区用量胶囊与登录态/偏好持久化;
  • FNOS-027-08:文档站说明页与菜单;市场源列表登记随 npm 发布执行。

技术边界:只新增插件与本仓库文档,不改 DSH 核心、其它插件与既有需求文档。FNOS-027-08 本轮完成页面与菜单;源列表登记、市场索引重生成与应用发布清单登记依赖 npm 发布,列为待执行任务。

本轮的关键约束:3012 的判据已由二分实测确定为请求的 system 形态,不是账号风控——system 必须是官方 agent 的两段独立文本块,system[0] 逐字 42 字符、system[1] 以 1211 字符行为提示词开头;单块无论怎么拼接全部返回 405 + 3012,两段独立块返回 200。请求头(22 个全试只有 authorization 必需)、请求签名(官方 agent 在 start-plan 模式下自己也不签名)、TLS 指纹、HTTP 版本、客户端证书与凭据来源逐项排除。因此不再托管官方运行时:插件自己组请求、自己解析 SSE,代价是两段前缀成为硬依赖——上游改字即整条通道失效,没有降级路径。工具由 DSH 侧执行并受其批准流程约束,不再有「工具归属不在 DSH」这条限制。

当前实现与目标设计 ​

领域当前实现目标实现迁移影响
供应商路由仓库内没有 ZCode 供应商;用户只能用内置 llm-pi-ai 手工声明 OpenAI 兼容路由,或直接在 ZCode 客户端里用只注册一个路由 dsh-zcode(显示名 ZCode),目录由账号权益驱动选择器新增一个 ZCode 分组;退出登录时该分组整体撤销;与手工配置的 zcode / zhipu 并存
模型清单来源手工配置必须逐条维护,且无法反映账号权益变化以 billing/balance 的 capabilities 为真源;client/configs 只补全能力;两者都不可读时回退内置清单并标记未经账号确认权益变化后刷新即生效,不需要改配置或升级插件;降级时界面说明来源
账号登录无上游授权页 + 同源回调:宿主生成 state 与授权地址 → 浏览器完成登录 → 回跳 /plugins/dsh-zcode/auth/callback → 宿主用授权码换取凭据账号卡片提供家族选择(两家族共用同一入口);不提供 Key 入口;回调需 state 校验
模型能力投影手工配置只能给一个「兼容」壳子上下文窗口、最大输出、图片输入、思考等级来自 client/configs;思考等级按 off / minimal / low → low、medium / high → high、xhigh / max → max 归并为上游三档容量与能力随账号配置变化;缺失时用保守默认值并说明
额度口径无按「模型 × 周期」逐条展示,日额度与一次性活动额度分列;进度值按「总剩余 / 总量」聚合明细不合并成一行;进度不是某一份额度的比例;不做金额换算
执行通道(Start Plan)插件在 Node 侧构造请求但 system 被拼成单块,被上游内容校验拒绝(405 + 3012);曾一度改为托管官方 zcode app-server 子进程插件自行收发 Anthropic Messages:system 发两段独立文本块(官方身份行 + 行为提示词前缀),补齐官方四个附加字段,自己解析 SSE移除对客户端发行包的运行时依赖;不再需要账号注入、数据目录对账与提交垫时;新增两段前缀常量作为硬依赖
执行通道(Ultra)无同一条自研通道,端点为 ultra/anthropic,用家族 MaaS 令牌按量计费;该端点不校验系统提示词,因此不注入前缀与 Start Plan 共用同一条 dsh-zcode 路由,按端点策略决定 baseUrl、凭据与是否注入前缀
通道数据与凭据无只有插件自有的凭据与偏好两个文件;不再有任何子进程数据目录不读写用户 ~/.zcode;升级后老环境的 zcode-bridge/ 可直接删除
模型标识目录 id 来自额度接口(全小写,如 glm-5.3-flash)目录层归一为官方书写(如 GLM-5.3-Flash),请求原样发出不再需要 agent registry 的大小写映射
工具归属—模型发起的工具调用回到 DSH,走 DSH 工具实现与批准流程;拒绝时如实回传拒绝结果用户可以审批与拒绝;不再需要「工具归属」硬规则注入与伪调用拦截
会话标题—由宿主自行生成,插件不再介入删除本地的标题请求分支
分发与文档仓库中没有该插件的页面、菜单条目与市场条目说明页 + 插件总览行 + 菜单条目 + 三份 SDD 文档;发布后登记市场源列表文档站与市场可见性随发布推进

供应商注册只有「未登录 / 已登录」两个状态,变化点在目录的来源与可信度,而不是供应商分组:

mermaid
stateDiagram-v2
  [*] --> 未登录
  未登录 --> 已登录: 授权页完成登录并回跳成功
  已登录 --> 权益目录: 额度接口可读
  已登录 --> 兜底目录: 额度接口不可读
  权益目录 --> 兜底目录: 接口失败且无上一份快照
  兜底目录 --> 权益目录: 刷新成功
  权益目录 --> 未登录: 退出登录
  兜底目录 --> 未登录: 退出登录

登录与首轮目录的时序:宿主在插件挂载时先给出一份内置清单,保证 headless 首轮对话不会落到空 provider 上;真实目录随后台刷新替换。

mermaid
sequenceDiagram
  participant Host as 插件宿主
  participant LLM as DSH 模型层
  participant Selector as 模型选择器
  participant Auth as 登录服务
  participant ZCode as ZCode 控制面
  Host->>LLM: registerAdapter('dsh-zcode')
  Host->>Host: 先用内置清单建立同步快照
  LLM-->>Selector: 出现 ZCode 分组(清单未经账号确认)
  Host->>Auth: 读取凭据并异步刷新目录
  Auth->>ZCode: 读取额度(携带账号 JWT 与稳定设备标识)
  ZCode-->>Auth: 套餐与按模型额度
  Auth-->>Host: 权益条目
  Host->>ZCode: 读取客户端配置补全能力
  Host->>LLM: 用新目录重建模型集合
  LLM-->>Selector: 清单与账号权益一致

执行通道只有「就绪 / 执行中 / 工具往返」几个状态,失败不伪装成功;变更点: 相比上一轮的托管方案,请求发送者从官方 agent 子进程变回插件自己:

mermaid
stateDiagram-v2
  [*] --> 不可用
  不可用 --> 就绪: 账号已登录且凭据有效
  就绪 --> 执行中: 提交回合
  执行中 --> 工具往返: 模型发起工具调用
  工具往返 --> 执行中: 工具结果回传(批准或拒绝)
  执行中 --> 就绪: 正常结束
  执行中 --> 失败: 请求被拒 / 超时 / 取消 / 网络失败
  失败 --> 就绪: 下一轮重新发起
  就绪 --> 不可用: 退出登录或凭据失效
  不可用 --> [*]

一轮对话的协议与数据流如下。变更点: 请求由插件组装:两段系统提示词 + 官方附加字段 + 转换后的消息与工具声明:

mermaid
sequenceDiagram
  participant DSH as DSH 会话
  participant Host as 插件宿主(HTTP 通道适配器)
  participant Tools as DSH 工具与批准流程
  participant ZCode as Start Plan 网关
  DSH->>Host: stream(options)
  Host->>Host: 转换消息与工具声明,取首条 system 作为追加段
  Note over Host,ZCode: 变更点:system 发两段独立文本块,第一段为 42 字符身份行
  Host->>ZCode: POST /v1/messages(SSE)
  ZCode-->>Host: message_start / content_block_* / message_delta / message_stop
  Host-->>DSH: 文本与思考增量、工具调用增量、usage
  DSH->>Tools: 执行工具调用并请求批准
  alt 用户批准
    Tools-->>DSH: 工具结果
    DSH->>Host: 携带 tool_result 续答
    Host->>ZCode: 续发请求(含 tool_result)
    ZCode-->>Host: 续答流
    Host-->>DSH: 续答内容
  else 用户拒绝
    Tools-->>DSH: 拒绝结果(is_error)
    DSH->>Host: 携带拒绝结果续答
    Host-->>DSH: 模型据此调整后的回复
  end

回合失败、超时与取消都以一条 finish 事件收尾(error / aborted),不产生空白助手消息;思考签名通过 replayState 跨轮带回,不进入可见正文。

影响范围分析 ​

需求功能代码模块配置与数据测试文档目标环境
FNOS-027-01src/host/auth.ts(登录状态机与凭据生命周期)、src/host/console-client.ts(授权码换取)、src/host/routes.ts(登录 / 回调 / 取消 / 退出)、src/contracts/$DSH_HOME/.dsh-zcode-auth.json(0600)登录态、非登录态、两个家族、回调 state 校验与授权码重放、无 Key 入口用例说明页「登录」小节DSH Web、DSH Desktop
FNOS-027-02目录服务、供应商注册、路由冲突诊断无新增用户配置;目录快照仅内存缓存权益清单、权益变化、兜底、路由冲突回归用例说明页「模型」小节DSH Web、DSH Desktop
FNOS-027-03目录归一化与模型投影(容量、思考等级、图片输入)无能力字段、思考等级映射、图片模态、缺配置降级用例说明页「模型能力」小节DSH Web、DSH Desktop
FNOS-027-04src/host/http/messages-client.ts(请求组装、SSE 解析、任务 ID 规范化)、src/host/http/translate.ts(消息 / 工具 / 图片转换与思考等级归并)、src/host/http/adapter.ts(LlmAdapter 实现、块状态与 replayState)、src/host/start-plan-prefix.ts(两段前缀与附加字段)、src/host/provider.ts(装配与附件读取接入)、src/index.ts(路由注册)无新增持久化;可选 DSH_ZCODE_CALLBACK_URL;会话数据格式不变请求形态(两段 system)、附加字段、SSE 事件、思考签名跨轮、图片 base64、工具往返、失败 / 取消、端点分支用例说明页「执行通道」「已知限制」与常见问题DSH Web(已验证)、DSH Desktop(待走查)
FNOS-027-05额度服务、宿主路由、额度卡片无持久化;快照带获取时间套餐、按模型窗口、日额度与一次性额度分列、失败态用例说明页「额度」小节DSH Web、DSH Desktop
FNOS-027-06输入区插槽组件、详情页四块卡片、目录卡片、用量聚合纯函数$DSH_HOME/.dsh-zcode-preferences.json三种胶囊策略、搜索、隐藏、刷新、聚合与明细一致性用例说明页设置表、模型目录与「百分比怎么算」小节DSH Web、DSH Desktop
FNOS-027-07凭据与偏好存储上述两个宿主文件重启后持久化与隔离用例说明页已知约束DSH Web、DSH Desktop
FNOS-027-08docs/plugins/、docs/.vitepress/config.mts、docs/public/plugins/market/plugins.txt 与四处索引无文档构建、菜单链接与源列表核对本需求的三份 SDD 文档与插件说明页文档站构建环境

架构与数据流 ​

插件分宿主与浏览器两侧:宿主侧负责凭据、账号权益目录、额度、自研 HTTP 通道与唯一供应商适配;浏览器侧只渲染详情页卡片与输入区胶囊,两者通过插件同源 Web 路由通信。登录、目录与额度请求由宿主发出,模型请求也由宿主发出(变更点: 上一轮由托管的 agent 子进程发出);浏览器不接触令牌。

mermaid
flowchart LR
  subgraph Client["DSH 浏览器半侧"]
    Page["插件详情页:账号 / 额度 / 目录(搜索、隐藏、刷新)"]
    Pill["对话输入区用量胶囊"]
  end
  subgraph Host["DSH 宿主半侧(@tnnevol/dsh-zcode)"]
    Routes["同源 Web 路由(含登录回调页)"]
    Auth["登录服务与凭据存储"]
    Catalog["目录服务(权益为真源)"]
    Usage["额度服务(模型 × 周期)"]
    Prefs["偏好存储"]
    Adapter["自研适配器(LlmAdapter)"]
    Client["Messages 客户端(两段 system + SSE)"]
    Translate["消息与工具转换"]
    Prefix["官方两段前缀常量"]
  end
  subgraph Upstream["ZCode(zcode.z.ai)"]
    OAuth["授权页与授权码换取"]
    Balance["Start Plan 额度 balance"]
    Configs["客户端配置 client/configs"]
    StartPlan["Start Plan 推理网关"]
    Ultra["Ultra 推理网关"]
  end
  Page --> Routes
  Pill --> Routes
  Routes --> Auth
  Routes --> Catalog
  Routes --> Usage
  Routes --> Prefs
  Auth --> OAuth
  Catalog --> Balance
  Catalog --> Configs
  Usage --> Balance
  Adapter --> Translate
  Adapter --> Client
  Client --> Prefix
  Client --> StartPlan
  Client --> Ultra

登录回调落在插件自己的同源路由上,因此浏览器整页跳转那一跳不经过 SPA:宿主直接返回一页极简结果页(禁止脚本、无外部资源),只显示成功或失败文案,不带任何令牌。

目录与额度的刷新都走「先看缓存是否过期,再决定是否打上游」的路径;额度接口失败只降级清单来源,不清空已经可用的目录:

mermaid
sequenceDiagram
  participant UI as 详情页 / 用量胶囊
  participant Routes as 插件 Web 路由
  participant Service as 目录与额度服务
  participant ZCode as ZCode 控制面
  UI->>Routes: 读取账号状态、目录与额度
  Routes->>Service: 判断缓存是否过期
  alt 已过期或用户强制刷新
    Service->>ZCode: 读取 Start Plan 额度(账号 JWT + 稳定设备标识)
    alt 额度不可读
      ZCode-->>Service: 失败原因
      Note over Service: 回退内置清单并保留上一份目录,标记清单未经账号确认
    else 额度可读
      ZCode-->>Service: 套餐与按模型额度
      Note over Service: capabilities 决定模型全集
    end
    Service->>ZCode: 读取客户端配置补全能力
    alt 客户端配置不可读
      ZCode-->>Service: 失败原因
      Note over Service: 容量与思考等级用保守默认值,并在界面说明
    end
    Note over Service: 按隐藏偏好过滤后重建供应商模型集合
  end
  Service-->>Routes: 目录快照、额度、获取时间与降级说明
  Routes-->>UI: 账号状态、模型目录、按模型额度

分阶段任务 ​

阶段一:宿主侧登录与凭据 ​

任务 ID对应需求/验收修改内容前置条件验证方式
PLAN-FNOS-027-T01-01FNOS-027-01 / AC-01、AC-02登录发起:按家族构造上游授权地址,宿主侧生成并保存一次性 state 与回调地址;把授权地址交给详情页,由页面在点击的同一手势内打开新标签(不在 await 之后打开,否则被弹窗拦截)无单测用桩控制面覆盖「发起成功」「上游拒绝」两条路径;页面侧断言授权地址来自接口返回值而非本地拼接
PLAN-FNOS-027-T01-02FNOS-027-01 / AC-02、AC-03登录回调:注册同源回调路由,校验 state 与有效期后调用授权码换取;成功写入凭据并清理进行中的登录;失败返回可读原因。回调页是浏览器整页跳转,因此用 state 而非 CSRF 头校验,并返回禁止脚本执行的结果页T01-01单测覆盖 state 不匹配、授权码重复使用、过期、上游换取失败四条路径;结果页无脚本、无外部资源、无令牌
PLAN-FNOS-027-T01-03FNOS-027-01 / AC-05、AC-06;FNOS-027-07 / AC-01凭据存储:宿主独占读写,文件 0600、目录 0700,原子写与文件锁,落盘文档带格式版本与字段白名单,未知字段视为格式漂移并拒绝;退出登录删除凭据无文件权限与格式断言;未知字段与旧版本文档被拒绝且不覆盖原文件;页面源码、网络响应与本地存储中查不到令牌明文;重启后登录态保持
PLAN-FNOS-027-T01-04FNOS-027-01 / AC-04登录入口收敛:路由只接受家族名,不提供 Key 提交分支;账号卡片已登录时只保留退出登录T01-01向登录路由提交 Key 形态请求被拒绝;页面 DOM 中不存在 Key 输入控件与等价文案

阶段二:模型目录与供应商适配 ​

任务 ID对应需求/验收修改内容前置条件验证方式
PLAN-FNOS-027-T02-01FNOS-027-02 / AC-01、AC-02额度解析:读取 data.plans[](plan_id / name / status / ends_at)与 data.balances[](capabilities / show_name / total_units / used_units / remaining_units / period_start / period_end / expires_at);从 capabilities 的 model: 前缀还原模型 id 并归一为官方大小写;没有 capability 的条目视为账号级记录、不生成模型;上游没有 period 字段,周期由窗口时长推导(Unix 秒)凭据可用(T01-03)用响应夹具断言模型全集、大小写归一、无 capability 条目被跳过、周期推导(日额度 86399 秒与约 1.95 天窗口两种形态)
PLAN-FNOS-027-T02-02FNOS-027-02 / AC-03清单来源与回退:额度可读时以权益为全集;不可读时回退内置清单(GLM-5.3-Flash、GLM-5.2、GLM-5-Turbo)并把来源标记为未经账号确认;未登录时也给一份内置清单保证选择器不是空的;任何一步失败都保留上一份可用快照并记录原因T02-01夹具覆盖「权益可读」「权益不可读」「未登录」「权益为空」「客户端配置不可读」五种情况;失败时目录不被清空
PLAN-FNOS-027-T02-03FNOS-027-03 / AC-01 至 AC-04能力投影:从 client/configs 的 data.builtinModels[] 取 contextWindow、maxCompletionTokens、reasoning.levels(对象映射 low / high / max)与 capabilities.vision;思考等级按 off / minimal / low → low、medium / high → high、xhigh / max → max 归并为上游三档,未声明思考时只保留关闭档;缺失时用 400000 上下文与 80000 最大输出的保守默认值;图片输入投影为 text / text+image 两种输入模态T02-01夹具断言 1000000 / 128000、三档思考等级、图片输入模态;缺配置时得到默认值并在快照里带说明
PLAN-FNOS-027-T02-04FNOS-027-02 / AC-01、AC-04;FNOS-027-01 / AC-05;FNOS-027-04 / AC-01供应商注册:只向模型层注册 dsh-zcode 一个路由,每次目录刷新更新模型集合;显示名固定为 ZCode(registry 在注册时缓存 providerInfo,不能依赖运行期状态);用户手工配置的 zcode / zhipu 不冲突,同名 dsh-zcode 冲突给出可诊断错误且不覆盖用户配置;退出登录时不注册该路由T02-03注册后选择器只出现一个 ZCode;预置手工路由时仍出现;同名冲突场景得到明确错误;退出登录后分组消失
PLAN-FNOS-027-T02-05FNOS-027-02 / AC-01;FNOS-027-03 / AC-04稳定设备标识:首次生成后缓存为进程内稳定值,并可注入已保存的值;额度、客户端配置与模型请求共用同一个标识(模型请求里同时写入 x-device-mid 头与 metadata.user_id),避免同一账号被当成新设备而要求重新授权T02-01同一进程内多次请求断言 x-device-mid 一致;注入固定值后沿用该值;模型请求的 metadata.user_id 内嵌同一标识
PLAN-FNOS-027-T02-06FNOS-027-02 / AC-02;FNOS-027-07 / AC-02目录缓存与刷新:快照在最短复用期内复用,过期才刷新;并发刷新合并为一次;强制刷新忽略复用期;刷新间隔按偏好设置,最小值 1 分钟,0 表示关闭自动刷新T02-02桩计时验证复用、合并与节流;偏好为 0 时不再产生定时请求

阶段三:自研 Anthropic Messages 通道与上游诊断 ​

任务 ID对应需求/验收修改内容前置条件验证方式
PLAN-FNOS-027-T03-01FNOS-027-04 / AC-01、AC-03两段前缀常量:把官方 agent 的身份行(42 字符)与行为提示词(1211 字符,含前导换行)固化为常量,并提供「两段前缀」的取用函数;官方四个附加字段(metadata / tool_choice / thinking / output_config)按官方值与结构构造,metadata.user_id 为内嵌设备与会话标识的 JSON 字符串T02-05单测锁定两段长度与逐字内容(42 / 1211);断言附加字段存在且结构正确;断言前缀取用返回两个元素而非拼接后的字符串
PLAN-FNOS-027-T03-02FNOS-027-04 / AC-01、AC-03请求组装:system 数组发两段独立块——第一段为身份行原文,第二段为「行为提示词 + 空行 + DSH 自己的 system」(DSH 无 system 时只用行为提示词);请求任务 ID 规范化为 6–64 字符(过短用设备标识补齐、过长截断),避免上游返回 1214;请求头带 authorization: Bearer 与 x-api-key(同值)、anthropic-version 与客户端身份头T03-01单测断言 system.length === 2、system[0] 逐字相等、system[1] 以行为提示词开头且可追加;断言 normalizeTaskId 的补齐、截断与合法值原样返回;断言请求头同值
PLAN-FNOS-027-T03-03FNOS-027-04 / AC-01、AC-06SSE 解析:按行解析 data: 载荷,覆盖 message_start / content_block_start / content_block_delta(text_delta、thinking_delta、signature_delta、input_json_delta)/ content_block_stop / message_delta / message_stop 与 ping;[DONE] 与空行跳过;无法识别的事件返回空而不是抛错;usage 在 message_start 与 message_delta 各报一部分,需按字段合并T03-02单测逐类事件断言解析结果;断言七类事件完整消费;断言 usage 合并后取到两部分的最大值而不是相互覆盖
PLAN-FNOS-027-T03-04FNOS-027-04 / AC-02、AC-05消息与工具转换:system / developer 消息跳过(由 system 字段承载);tool-call 块转 tool_use;工具结果消息转成带 tool_result 的 user 消息,相邻多条结果合并进同一条;图片块读出字节后转 base64 image 块,读取失败只跳过该图并记 warn,不影响同消息文本;工具声明转 input_schema;思考等级按三档归并写入 output_config.effortT03-04 前置 T03-02单测覆盖文本 / 工具 / 图片 / 空块投影、结果合并、参数 JSON 解析失败回退空对象、思考等级七档归并
PLAN-FNOS-027-T03-05FNOS-027-04 / AC-01、AC-05、AC-06适配器实现:实现 LlmAdapter 的模型列举、模型解析(含上下文窗口、默认最大输出、输入模态、思考档位)与取流;按块索引累积状态,block-end 必须带完整正文;思考签名单独累积、经 replayState 跨轮带回(不混进正文,否则泄漏到界面;不得含 undefined,否则宿主以 must be losslessly JSON-serializable 拒绝整条流);失败与取消各产出一条 finishT03-03、T03-04单测断言块正文完整、replayState 为纯 JSON 且无签名块写 null;断言取消产出 aborted、上游错误产出 error;断言语义化未知模型报错而不是静默兜底
PLAN-FNOS-027-T03-06FNOS-027-04 / AC-01、AC-03附件接线与供应商装配:把宿主附件服务的图片读取能力接到适配器(取字节并编码 base64、mediaType 取附件声明的类型);端点策略决定 baseUrl 与凭据类型——start-plan 用账号 JWT 且注入前缀,ultra 用家族 MaaS 令牌且不注入;每次请求重新读取当前模型集合与端点策略T03-05单测断言未接线时不产生空 image 块、接线后 image 块含 base64;断言 ultra 请求不带前缀;断言目录刷新后下一轮即用新模型集合
PLAN-FNOS-027-T03-07FNOS-027-04 / AC-03、AC-04、AC-07诊断与失败路径:3012 诊断为「系统提示词形态与上游版本不一致、需要重新采集前缀」并保留上游原文;3001 / 3006 / 3007 / 1113 / 1214 分别映射为可读中文说明;账号未登录、凭据失效、网络不可达、超时与取消各有独立文案;全部以错误或取消结束,不产生空白助手消息、不静默重试、不显示为完成;日志只记录状态与业务码,不记录请求体与令牌T03-06逐码夹具断言诊断文案;断言文案不出现「已绕过」「稍后自动恢复」;断言日志不含令牌与 prompt 原文
PLAN-FNOS-027-T03-08FNOS-027-04 / AC-05工具往返:模型发起的工具调用回到 DSH,由 DSH 执行并请求批准;批准后工具结果以 tool_result 回传续答(is_error 标记拒绝),拒绝时同样回传并让模型调整;连续两轮工具往返不丢上下文T03-05、T03-07单测断言 tool_result 消息结构与 is_error;实测走查 Bash 调用与审批弹出

已移除的实现:上一轮的 src/host/bridge/(stdio 协议客户端、运行时定位与数据目录、消息压平、会话与回合、端点分流)与其 6 个 spec 已整体删除;对应的账号注入、数据目录对账、提交垫时、静默失败三前提、单在途回合与撞锁自愈、会话标题本地生成、伪调用标记拦截等任务与约束一并作废(见变更记录)。

阶段四:插件详情页与用量胶囊 ​

任务 ID对应需求/验收修改内容前置条件验证方式
PLAN-FNOS-027-T04-01FNOS-027-01 / AC-01、AC-02、AC-03、AC-04账号卡片:未登录(家族选择与说明)、授权中(授权地址、复制按钮、剩余有效期)、已登录(账号与家族)、错误四种状态;点击登录时同步打开占位标签页再写入地址(避免弹窗拦截),失败时关闭占位页;已登录时不渲染 Key 登录入口T01-02、T01-04DSH Web 与 DSH Desktop 上逐状态目视 + DOM 断言;授权中刷新页面后授权地址不变
PLAN-FNOS-027-T04-02FNOS-027-05 / AC-01 至 AC-05额度卡片:账号当前生效套餐、每个模型的额度窗口(已用百分比、剩余量、周期、重置倒计时)、获取时间与刷新按钮;日额度与一次性活动额度分列;失败态显示原因且不显示 0%T02-01夹具覆盖两份套餐与四类窗口;失败态不显示 0%;把明细合并成单一百分比判为缺陷
PLAN-FNOS-027-T04-03FNOS-027-06 / AC-02、AC-03目录卡片:固定高度、列表内部滚动,搜索框与计数固定;逐模型显隐开关写入偏好;刷新与获取时间T02-04DSH Web 与 DSH Desktop 亮暗主题走查;隐藏后选择器不再出现该模型,恢复后重新出现
PLAN-FNOS-027-T04-04FNOS-027-06 / AC-04、AC-05用量聚合与胶囊:抽出纯函数按「总剩余 / 总量」聚合(选中模型时只聚合该模型名下窗口,匹配不到时退回全部);胶囊按 auto / always / off 显隐、显示聚合比例与最早重置时间;浮层逐条列出各份额度的剩余与重置T04-02 的额度数据纯函数单测覆盖单份、多份、总量为 0、剩余量缺失(用总量减已用兜底)、无重置时间;三种策略各断言一次;选中其它供应商模型时不显示、不请求额度
PLAN-FNOS-027-T04-05FNOS-027-07 / AC-02;FNOS-027-06 / AC-02设置区:胶囊策略、自动刷新间隔与推理端点的读写、校验与持久化;偏好损坏或字段漂移时回落默认值T01-03 的宿主文件约定重启后偏好保持;越界值夹到合法区间;坏文件不导致详情页不可用

阶段五:文档站与发布登记 ​

任务 ID对应需求/验收修改内容前置条件验证方式
PLAN-FNOS-027-T05-01FNOS-027-08 / AC-01、AC-02新增 docs/plugins/dsh-zcode.md;在插件总览加入一行并修正运行时插件数量表述;在 /plugins/ 菜单加入条目无文档构建通过;菜单与页面可达;说明页写明登录(回调)、执行通道(两段前缀与工具归属)与已知限制,不出现客户端依赖类过时表述
PLAN-FNOS-027-T05-02FNOS-027-08 / AC-03随 npm 发布执行:在插件市场索引源列表加入 @tnnevol/dsh-zcode;不手工改写生成的索引文件npm 发布成功源列表含该包;生成的索引文件未被手改
PLAN-FNOS-027-T05-03全部需求、计划与测试用例文档登记:docs/requirements/、docs/plans/、docs/tests/ 与本页,同步四个索引与四处菜单无pnpm run check -- --sdd 通过;文档构建通过
PLAN-FNOS-027-T05-04FNOS-027-08 / AC-03插件发布后重新生成市场索引并核对条目,随后登记到应用发布清单npm 发布成功;发布前确认目标版本可用索引条目与源列表一致;应用安装后插件可见

阶段六:验证与收尾 ​

任务 ID对应需求/验收修改内容前置条件验证方式
PLAN-FNOS-027-T06-01全部插件的类型检查、单测与构建阶段一至四pnpm --filter @tnnevol/dsh-zcode run check 与 build 通过;全量 15 文件 / 149 用例通过,tsc --noEmit 干净,ESLint 0 error
PLAN-FNOS-027-T06-02FNOS-027-01、FNOS-027-02、FNOS-027-03、FNOS-027-05 至 FNOS-027-07DSH Web 与 DSH Desktop 走查,按测试用例文档执行;包含两个家族的登录、权益目录、能力字段与按模型额度。DSH Web 已完成对话与工具体验走查,DSH Desktop 未执行T06-01用例结论回填 docs/tests/FNOS-027-dsh-zcode-plugin.md;Desktop 结果按待执行登记
PLAN-FNOS-027-T06-03FNOS-027-04 / AC-01 至 AC-07执行通道走查:真实账号确认纯文本、图文与思考等级、工具调用与审批、多轮工具结果、智能体团队子代理、失败 / 超时 / 取消与前缀失配诊断T03-08DSH Web 已通过纯文本、工具调用、多轮工具结果、图文与智能体团队;失败分支与 DSH Desktop 待执行
PLAN-FNOS-027-T06-04FNOS-027-08 / AC-04文档站构建与菜单链接核对T05-01 至 T05-03构建通过、菜单目标均存在;git diff --check 干净
PLAN-FNOS-027-T06-05全部版本更新:按仓库版本流程推进插件与应用版本(功能提交后独立版本提交)T06-01 至 T06-04版本串一致,发布流程可执行

交互和行为设计 ​

插件详情页 ​

入口为「插件管理 → ZCode → 详情页」。页面由上到下依次是账号卡片、额度卡片、模型目录卡片与设置区;所有操作只改插件自己的数据。

区块状态用户可见内容可用操作
账号卡片未登录两个账号家族(BigModel 国内 / Z.ai 海外)的说明与入口;不出现 Key 入口发起登录
账号卡片授权中授权地址、复制按钮、剩余有效期、账号家族取消登录
账号卡片已登录账号信息、账号家族;只显示退出登录退出登录
账号卡片错误失败原因与可执行的处置重试
额度卡片有数据当前生效套餐;每个模型的额度窗口(已用百分比、剩余量、周期、重置倒计时);获取时间刷新
额度卡片失败或未订阅失败原因与最近一次获取时间,或未订阅说明;两者都不显示 0%刷新
目录卡片有数据固定高度的滚动列表;固定的搜索框与计数;每行含名称、标识、容量、能力与逐模型显隐开关;清单来源说明搜索、隐藏/恢复、刷新
目录卡片兜底或失败说明当前清单来自内置兜底、未经账号确认,并给出失败原因刷新
设置区始终用量胶囊策略、自动刷新间隔、推理端点修改并保存

模型目录卡片 ​

目录卡片自身固定高度,只有模型列表区内部滚动;卡片头部与工具栏(搜索框、计数、刷新)不随列表滚动,长目录不会把整页撑高。

列表项内容
名称与标识模型显示名与网关模型 id(如 GLM-5.3);权益清单下同时可看到对应的 capability 原文
容量上下文窗口与最大输出;来自上游客户端配置或保守默认值
能力思考等级、图片输入、工具调用;未声明时显示为不可用
显隐逐模型开关;隐藏后该模型不再出现在选择器
  • 搜索覆盖名称、标识与能力说明;计数显示当前搜索结果数,已隐藏数量另行标注。
  • 清单来源在卡片头部说明:来自账号权益,或来自内置兜底且未经账号确认。
  • 目录刷新失败时列表保留上一份快照并显示原因;未登录时展示内置兜底清单并提示登录。

额度卡片 ​

Start Plan 的额度粒度是「模型 × 周期」,卡片逐条组织,不合并成一行:

列内容
模型额度条目对应的模型显示名(如 GLM-5.3);没有 capability 的账号级条目单独标注
周期上游原样(daily / one_time 等),不翻译成自定义窗口名
用量已用百分比、剩余量;总量为 0 时显示 0% 而不是无效数值
重置有周期结束或到期时间时显示倒计时,并随时间递减

本账号的两份套餐分别提供日额度(GLM-5.3 3,000,000、GLM-5.3-Flash 5,000,000)与一次性活动额度(GLM-5.3 200,000,000、GLM-5.3-Flash 300,000,000),因此同一模型会出现两个窗口——这是预期展示,不是重复数据。

用量胶囊 ​

胶囊位于对话输入区右侧,与其它状态控件同行,不遮挡输入框。三种策略的切换关系如下:

mermaid
stateDiagram-v2
  [*] --> auto
  auto --> always: 用户选择常驻
  always --> auto: 用户改回自动
  auto --> off: 用户关闭
  off --> auto: 用户改回自动
  always --> off: 用户关闭
  off --> always: 用户选择常驻
  note right of auto: 仅在选中 ZCode 模型时显示
  note right of off: 隐藏并停止自动刷新
  • auto:默认值。只在当前选中的模型属于 ZCode 供应商时显示;其它供应商模型不显示,也不触发额度请求。
  • always:只要插件已登录就常驻显示,与当前选中的供应方无关;没有额度数据时显示未知,不补 0%。
  • off:完全不显示,并停止额度自动刷新;详情页额度卡片不受影响,仍可手动刷新。

策略变化在宿主侧持久化,下一次进入会话或下一次对话即按新策略显示,无需重启 DSH。

进度值的算法(变更点: 上一轮取单份额度,多条额度并存时显示错误——实测出现「剩余 0%」但账号仍有大量额度):

环节行为
选窗口按选中模型的 capability 后缀或显示名匹配;匹配不到时退回全部窗口
求和对参与计算的窗口累加总量与剩余量;剩余量缺失时用「总量 − 已用」兜底,不把未知当 0
取比例总剩余 / 总量,夹到 0–100;没有任何总量时按 100% 处理
重置提示取最早的一个重置时间作为胶囊的「何时重置」
明细浮层仍逐条列出每份额度的剩余与重置时间,聚合不损失信息

执行通道 ​

选中 ZCode 模型后,请求由插件组装并发出,规则如下:

关注点行为
先决条件账号已登录且凭据有效;缺失时给出可读原因并终止本轮
系统提示词system 固定发两段独立块:第一段为 42 字符身份行原文,第二段为「1211 字符行为提示词 + 空行 + DSH 自己的 system」(无 DSH system 时只用行为提示词)
附加字段与官方一致地带 metadata(user_id 内嵌设备与会话标识)、tool_choice、thinking、output_config.effort
请求标识会话标识规范化为 6–64 字符,过短用设备标识补齐、过长截断
端点start-plan 注入前缀、用账号 JWT;ultra 不注入前缀、用家族 MaaS 令牌
上下文消息按 Anthropic 形态转换;工具结果挂在 user 消息里,相邻多条合并;图片以 base64 image 块发出
输出文本、思考与工具参数增量转成 DSH chunk;用量按 message_start 与 message_delta 合并
思考签名单独累积并经 replayState 跨轮带回;不进正文、不含 undefined
工具由 DSH 执行并请求批准;拒绝时以 is_error 回传,模型据此调整
收尾失败、超时与取消各产出一条 finish;失败以错误结束,不产生空白回复

思考等级按 off / minimal / low → low、medium / high → high、xhigh / max → max 归并;该端点没有「不思考」档,因此 off 也落到 low。

文案与命名 ​

  • 供应商名称固定为 ZCode,路由 id 固定为 dsh-zcode。
  • 账号家族名称固定为 BigModel(国内)与 Z.ai(海外);需要说明差异时写「授权页域名不同」,不写成「两套账号体系」。
  • 额度窗口按上游周期名与模型名表达,例如「GLM-5.3 · 每日」「GLM-5.3 · 一次性」;不混用「日额度」「活动额度」之外的别名。
  • 上游限制使用业务码与原文短语(request has been blocked due to unusual activity.、model not allowed),不翻译成模糊的「网络问题」或「权限不够」。3012 的文案指向「系统提示词形态与上游版本不一致」,不再写成「账号被风控」或「对话无法完成」。
  • 执行通道的说明使用确定对象:写「插件自行发送 Anthropic Messages 请求」「工具由 DSH 执行」,不写「本机」「代理」这类无法指代或与事实不符的说法;也不再把「需要安装客户端」「工具由 ZCode agent 执行」写进说明。
  • 「清单来源」按可信度说明是账号权益还是内置兜底;兜底时另附「未经账号确认」,不写成「降级」以免被理解为功能受损。

数据、权限和错误处理 ​

持久化 ​

数据位置权限读取与恢复策略
账号凭据(账号 JWT、家族访问令牌、账号信息与家族)$DSH_HOME/.dsh-zcode-auth.json文件 0600,目录 0700只由插件宿主读写;解析失败或格式版本不符时按未登录处理并给出可诊断错误,不覆盖原文件;凭据不含过期时间时不做本地过期判定,留 30 秒提前量处理已知过期的临界情况
插件偏好(胶囊策略、刷新间隔、隐藏模型、推理端点)$DSH_HOME/.dsh-zcode-preferences.json文件 0600缺失或损坏时回落到默认值;越界值夹到合法区间;隐藏模型按模型 id 记录
目录与额度快照进程内存—目录与额度分别缓存;进程重启后重建,不落盘,避免把过期数据当成事实
上一轮的桥接数据目录已移除($DSH_HOME/zcode-bridge/ 不再创建)—通道改为自行发送后不再需要子进程与 provider 配置;旧环境残留目录可直接删除,不包含用户会话历史

权限 ​

  • 不新增 DSH 权限项,也不申请 fnOS 宿主权限;插件做宿主侧文件读写、对 zcode.z.ai 的出站请求,不托管任何子进程。
  • 同源 Web 路由只接受同源页面或回环地址发来的请求;跨站请求一律拒绝,凭据与目录响应不回显令牌。
  • 登录回调是浏览器整页跳转,无法携带 CSRF 头,因此改用一次性 state 校验,并由宿主返回禁止脚本执行、无外部资源的结果页。
  • 凭据文件权限被放宽或属主不可读时,按共享包的既有判定给出可诊断错误,不静默忽略。

错误处理 ​

场景用户可见恢复动作
未登录账号卡片显示两个家族的登录入口与说明发起登录
授权取消或链接过期回到未登录并说明原因重新发起
回调 state 不匹配结果页提示该链接不属于本次登录回到详情页重新发起
授权码已被使用结果页提示授权码只能使用一次重新发起
登录接口不可达账号卡片显示连接失败与账号家族检查网络后重试
凭据缺失或已过期账号卡片回到未登录并提示重新登录重新登录
额度接口不可读目录回退内置清单并标注未经账号确认;额度卡片显示未知与失败原因,不显示 0%刷新或稍后重试
客户端配置不可读模型仍可用,容量与思考等级使用保守默认值并说明刷新
账号权益里没有可用模型回退内置清单并说明账号可能未订阅 Start Plan在 ZCode 侧确认套餐后刷新
参数错误(3001)会话或卡片显示上游原文与说明;设备标识异常时提示重新登录以恢复重新登录
模型未授权(3006)会话显示 model not allowed 与「当前账号无该模型权益」的说明;不自动换模型刷新目录确认权益
需要人机校验(3007)会话显示上游原文与「需在官方客户端完成校验」的说明在官方侧完成校验后重试
额度耗尽(1113)会话显示上游原文与额度状态;额度卡片同步反映已用比例等待周期重置或切到有余额的 Ultra 端点
请求任务 ID 不合法(1214)会话显示上游原文与「会话标识长度不合法」的说明重新发送;持续出现需修实现
系统提示词形态不符(3012)会话显示「网关拒绝了本次请求(3012):Start Plan 端点会校验请求里的系统提示词,当前前缀可能已与上游版本不一致,需要重新采集官方提示词」升级到包含最新前缀的插件版本;插件不提供绕过方式
网络不可直达 zcode.z.ai会话与卡片显示连接失败检查网络后重试
回合超时会话显示超时原因重发或新开会话
用户取消会话显示「请求已取消」直接重发
工具被拒绝模型收到拒绝结果并调整做法,会话不视为失败需要时重新批准
图片读取失败跳过该图并记 warn;同消息文字照常发出重新上传图片
用户手工配置了同名 dsh-zcode详情页说明冲突来源与处置方式;插件不注册、不覆盖用户配置用户移除同名配置后重试

依赖、风险和决策 ​

依赖 ​

依赖版本用途
@deepseek-ai/dsh-llm0.2.1-rc.2LlmAdapter 契约、流事件与用量类型、重试策略兜底
@deepseek-ai/dsh-attachment0.2.1-rc.2读取图片附件字节(转 base64 后随请求发出)
@deepseek-ai/dsh-host-webserver0.2.1-rc.2插件同源 Web 路由与登录回调页
@tnnevol/dsh-plugin-kitworkspace凭据文件权限判定
@tnnevol/dsh-semi-uiworkspace详情页与胶囊的组件与主题
ZCode 授权、额度与客户端配置接口上游在线服务登录、权益目录与能力
ZCode 网关的官方两段系统提示词上游客户端行为(2026-10-25 采集)Start Plan 端点放行的必要条件,固化为常量
@earendil-works/pi-ai1.1.0仅作为思考等级语义与模型对象的参考实现;请求不再由它发出

风险 ​

风险影响缓解
两段前缀是上游提示词原文上游改字即整条通道硬失败(3012),没有降级路径常量与长度(42 / 1211)由单测锁定;3012 文案直接指向「需重新采集前缀」;上游更新后按发布流程发新版本
自行发送意味着放弃 pi-ai 的能力图片重放、prepareCall 协商、部分重试与超时策略不再由 pi-ai 提供相关行为由插件自己实现并单测固定;按官方 LlmAdapter 契约逐项核对(自定义与走默认的边界见测试文档)
适配器默认实现返回空值易被误判为缺实现排查成本高已核对:prepareCall / providerRetryPolicy / imageRequestTarget / imageRequestPricing 走官方默认属正确行为,其中重试策略由宿主 ?? resolveRetryPolicy(...) 兜底
思考签名处理错误混进正文会显示 [signed:…];含 undefined 会让宿主拒绝整条流签名单独累积并只经 replayState 携带;逐块映射为纯 JSON,无签名块写 null
图片能力声明了但未接线图片被静默丢弃,模型答非所问且无报错(实测踩到过一次)装配层显式接入附件读取;未接线时不产生空 image 块;用例断言图片确实随请求发出
上游协议字段可能漂移事件名、附加字段或用量字段变化会让解析失效SSE 解析对未知事件返回空而不是抛错;用量字段兼容 snake_case 与 camelCase;升级后以实测冒烟并更新文档
请求任务 ID 长度受限(6–64)过短返回 1214,容易被误判为鉴权问题normalizeTaskId 统一补齐与截断,并由单测锁定
X-Device-Mid 缺失返回 3001,易被误判为代码缺陷排查成本高把 3001 单独归类为参数错误并在诊断里点明设备标识;单测用缺少该头的响应夹具固定行为
额度接口强制要求稳定设备标识标识变化会让同一账号被当成新设备,反复要求重新授权首次生成后缓存为进程内稳定值,并支持注入已保存值;核对模型请求与额度请求使用同一标识
模型清单来自账号权益,字段漂移会改变可用模型目录与额度解析失败模型全集有内置兜底;解析层以夹具固定已知形态,失败时降级并说明,不抛错到界面
额度按「模型 × 周期」表达,与固定三窗口的直觉不同用户把两个窗口看成重复数据,或把聚合看错卡片按模型与周期分列并标注周期原文;胶囊说明是聚合值且浮层可看明细
账号 JWT 不带 exp无法在本地预判过期上游给出时间才判定并留 30 秒提前量;未给出时以请求失败为准并提示重新登录
思考等级映射有损(上游只有三档)用户选的等级与上游档位不是一一对应按七档归并为三档;未声明思考时只保留关闭档;说明页写明映射
登录回调依赖可回跳的地址反向代理或改写过 origin 时回调落不到 DSH默认按本次请求的 origin 推导;支持 DSH_ZCODE_CALLBACK_URL 显式指定;失败时结果页提示重新发起
两个家族的授权页域名不同用户选错家族后拿不到令牌账号卡片写明国内 / 海外差异;登录失败时提示可切换家族重试
运行环境无法直连 zcode.z.ai登录、目录与请求全部不可用明确提示连接失败并停止重试;不内置代理,不静默回退到其它供应商
凭据文件格式漂移旧文件导致插件无法启动落盘文档带版本与字段白名单,未知字段直接拒绝而不静默忽略;失败时按未登录处理且不覆盖原文件
npm 上目标版本已被占用发布失败发布前核对目标版本,必要时先推进版本

决策 ​

决策选择否决方案原因
登录形态只有账号授权(上游授权页 + 同源回调),两个家族各一个选项同时提供 API Key 登录Start Plan 的模型请求只接受账号身份,Key 形态没有可用路径
登录链路桌面授权码 + 同源回调(浏览器完成登录后回跳插件路由换取凭据)设备授权 + 后台轮询两条链路换来的凭据完全相同,而授权码链路在浏览器里一步完成,不需要在宿主侧维持轮询定时器,也不依赖用户回到页面等待
供应商路由名唯一路由 dsh-zcode(显示名 ZCode)用 zcode / zhipu这两个名字可能已被用户在内置目录里手工声明;dsh- 前缀避开用户配置
模型清单真源账号权益(额度条目的 capabilities)内置静态清单;或客户端配置里的模型表权益是唯一能反映套餐变体、活动赠送与到期的来源。客户端配置只用于补全能力
权益不可读时的行为回退内置清单并把来源标记为未经账号确认直接展示空目录;或报错阻断空目录会让选择器出现空分组;内置清单至少保留结构,配合来源说明不误导用户
额度粒度按「模型 × 周期」逐条展示合并成单一总百分比日额度与一次性活动额度可能同时存在,合并会掩盖「日额度用完但活动额度还有」
进度值算法「总剩余 / 总量」聚合,明细保留取单份额度(如优先日额度)单份口径会把账号实际可用量显示错,实测出现过「剩余 0%」但仍有大量额度
思考等级映射上游三档(low / high / max):off / minimal / low → low、medium / high → high、xhigh / max → max把七个等级原样透传上游端点只认三档且没有「不思考」档,透传未支持的值会得到 400
设备标识首次生成后进程内稳定,可注入已保存值每次请求新生成额度接口要求稳定标识,否则同一账号被当成新设备并反复要求重新授权
Start Plan 执行通道插件自行收发 Anthropic Messages,按上游要求发两段独立 system 块并补齐官方附加字段① 托管官方 zcode app-server 子进程;② 在 Node 侧复刻请求签名与客户端身份;③ 内置代理或反向代理转发二分实测确认 3012 只与 system 形态有关,请求头、签名、TLS、HTTP 版本、客户端证书与凭据来源均无关;因此不需要复刻签名,也不需要托管官方运行时。方案 ②③ 属于伪造与转发,既非必要也不合规
客户端依赖不再依赖 ZCode 客户端发行包继续托管客户端运行时自行发送后不需要子进程、provider 配置、账号注入与数据目录对账,安装门槛消失
工具归属由 DSH 执行并受 DSH 批准流程约束由 ZCode agent 原生执行(托管方案)自行发送后工具声明与结果都在 DSH 侧闭环,用户可审批可拒绝,行为可预期
思考签名承载只经 replayState 跨轮带回拼进思考正文;或丢弃签名拼进正文会泄漏到界面;丢弃会让上游拒绝续发
图片输入读取附件字节转 base64 image 块只声明能力不接线;或传本地路径上游协议要求 base64;不接线会静默丢图且无报错(实测缺陷)
失败呈现区分业务码分别提示统一显示「调用失败」3006、3007、1113、1214、3012 的处置完全不同,笼统提示会让用户做错动作
界面承载方式插件详情页自定义区块设置弹框的官方配置表单账号、额度与目录都是交互型区块,官方配置 schema 表达不了(按插件 UI 规范第 2 档)
市场索引维护只加源列表,发布后重生成手工改写生成的索引文件索引由官方生成器从 npm 产物读取,手改会与源列表漂移

测试、打包、发布和回滚 ​

  • 包级验证:插件类型检查、单测与构建;全量 15 文件 / 149 用例通过,tsc --noEmit 干净,ESLint 0 error。重点覆盖:两段 system 形态与长度、附加字段、SSE 七类事件、normalizeTaskId、消息 / 工具 / 图片转换、思考等级七档归并、思考签名 replayState、用量聚合、模型投影与显示名。SDD 文档检查与文档站构建见下;测试用例设计见测试用例文档 FNOS-027,本页不展开用例表。
  • DSH Web:pnpm run start -- --web(DSH_HOME 指向仓库 .dsh),用启动日志里带 token 的地址访问;覆盖两个家族的登录、权益目录、能力字段、按模型额度、胶囊策略,以及文本 / 图文 / 工具调用 / 多轮工具结果 / 智能体团队。走查证据:纯文本回合 4 秒、无 3012;工具调用正确发起 Bash 且 DSH 权限审批正常弹出;多轮 tool_result 正确续答;图文回合 7 秒读出图中文字与数字;思考签名 24 字符经 replayState 跨轮传递;智能体团队子代理 27 秒完成并回传「子代理通」(1 轮 3 步、57.8K tok、缓存命中 68%)。
  • DSH Desktop:使用上游检出的开发态 Desktop(fork-pj/deepseek-harness),通过渲染进程调试端口取证;重点核对系统浏览器打开授权页与回跳、目录卡片固定高度与滚动、胶囊位置与亮暗主题,以及自研通道在同一 profile 下的可用性(尚未执行,结果按待执行登记)。
  • 文档站:pnpm run check -- --docs(或 pnpm run build -- --docs、pnpm exec vitepress build docs)与 git diff --check;逐项核对新增菜单与页面链接目标存在。
  • 打包与发布:按仓库版本流程更新版本(功能提交与版本提交分开),随后发布插件;发布后重新生成市场索引,并登记到应用发布清单。发布说明需写明 Start Plan 请求依赖上游两段系统提示词、上游更新后需升级插件,避免用户误以为是账号或网络故障。
  • 回滚:停用或卸载插件即可撤销 ZCode 供应商注册,模型选择器回到手工配置方式;说明页、插件总览行、菜单条目与市场源列表按提交回退。插件自有的凭据与偏好文件只有用户明确要求时才删除;升级到本版本后可删除遗留的 zcode-bridge/ 目录。
  • 禁止删除:用户会话历史、其它供应商的凭据与配置;本插件不持久化目录与额度,无需清理这两类数据。

参考资料 ​

来源用途
https://zcode.z.ai/api/v1/oauth/token授权码换取凭据(data.token 与 data.<family>.access_token)
https://zcode.z.ai/api/v1/oauth/cli/init、…/oauth/cli/poll/<flowId>设备授权链路的请求形状与状态机(作为对照事实记录,当前实现不走该链路)
https://zcode.z.ai/api/v1/zcode-plan/billing/balanceStart Plan 套餐与按模型额度;X-Device-Mid 必填与 3001 的触发条件
https://zcode.z.ai/api/v1/client/configs模型能力(上下文窗口、最大输出、思考等级、图片输入)
https://zcode.z.ai/api/v1/zcode-plan/anthropic/v1/messagesStart Plan 推理端点:两段 system 前缀与官方附加字段的放行条件
https://zcode.z.ai/api/v1/ultra/anthropic/v1/messagesUltra 推理端点:同一通道的按量计费分支,不校验系统提示词
官方客户端行为与两段系统提示词原文(2026-10-25 采集)42 字符身份行与 1211 字符行为提示词;请求头形态;四个附加字段
zai-org/ZCode(HEAD 3c5b2276,v0.17.0)的 official-coding-plan-gateway.ts官方把模型流量改写为 ultra/anthropic 的依据
@deepseek-ai/dsh-llm@0.2.1-rc.2LlmAdapter 契约、流事件、replayState 序列化约束与重试策略兜底
@earendil-works/pi-ai@1.1.0模型对象与思考等级语义的参考实现(请求不再由它发出)
仓库规范 docs/charter/*-spec.md需求、计划、测试用例与菜单的要求

完成状态 ​

阶段状态完成条件
阶段一 宿主侧登录与凭据待完成两个家族的授权页登录、回调 state 校验、凭据存储与无 Key 入口通过单测与桩验证;真实浏览器全流程待走查
阶段二 模型目录与供应商适配待完成权益目录、回退、能力投影、单路由注册、设备标识与刷新通过单测;路由冲突回归通过
阶段三 自研 Anthropic Messages 通道与上游诊断待完成(实现与单测完成;DSH Web 纯文本 / 工具调用 / 多轮工具结果 / 图文 / 智能体团队已通过,失败分支与 DSH Desktop 待走查)两段 system 形态、附加字段、SSE 事件、转换、签名与工具往返通过单测;DSH Web 完成实测;失败路径不伪装成功
阶段四 插件详情页与用量胶囊待完成四块卡片、固定高度目录、按模型额度、聚合进度与胶囊在 DSH Web 与 DSH Desktop 渲染并通过用例
阶段五 文档站与发布登记待完成T05-01 至 T05-03 完成;T05-04 待插件发布后执行
阶段六 验证与收尾待完成用例执行结论回填,构建与版本检查通过;DSH Web 已验、DSH Desktop 与发布项按待执行登记

插件宿主实现在同一分支落地(登录、目录、能力、额度、自研 HTTP 通道与单路由已实现),真实账号的接口级实测、DSH Web 的对话与智能体团队验证已完成;DSH Desktop 与发布相关任务尚未执行。各阶段完成时在本页变更记录追加说明,不提前修改完成状态。

变更记录 ​

日期变更说明
2026-10-24建立 PLAN-FNOS-027依据 FNOS-027 拆出六个阶段 28 个任务:宿主侧登录与凭据、模型目录与供应商适配、推理请求与上游诊断、详情页与用量胶囊、文档站与发布登记、验证与收尾。登记 13 条风险与 11 条决策,其中「登录只有设备授权」「模型清单以账号权益为真源」「额度按模型 × 周期分列」「上游限制如实诊断不绕过」是本轮的关键技术判断;T05-04 以 npm 发布为前置,不在本轮完成。
2026-10-24执行通道改为托管官方 app-server 并回填实测当轮判断为「直连 HTTP 恒被 3012 拦截」,因此改为托管官方 zcode app-server 子进程,新增 T03-01 至 T03-07(协议客户端、运行时与数据目录、会话回合、消息压平与标题、组合适配器、Ultra HTTP 通道、失败不伪装成功),并登记通道限制:工具由 ZCode agent 原生执行、标题本地生成、单在途回合与撞锁自愈。该方案已被下一条变更取代。
2026-10-25执行通道改为插件自行收发 Anthropic Messages(覆盖托管方案)二分实测确定 3012 的判据是请求的 system 形态:必须是官方 agent 的两段独立文本块——system[0] 逐字 42 字符、system[1] 以 1211 字符行为提示词开头;单块无论怎么拼接全部 405 + 3012,两段独立块返回 200。请求头(22 个全试只有 authorization 必需)、请求签名、TLS 指纹、HTTP 版本、客户端证书与凭据来源逐项排除。据此删除 src/host/bridge/ 整个目录与其 6 个 spec,新增 src/host/http/(messages-client.ts / translate.ts / adapter.ts)与 src/host/start-plan-prefix.ts;阶段三整体改写为 T03-01 至 T03-08(前缀常量、请求组装、SSE 解析、消息与工具转换、适配器、附件接线与端点分支、诊断与失败路径、工具往返)。连带变化:不再依赖 ZCode 客户端;工具由 DSH 执行并受批准流程约束(原「工具由 ZCode agent 原生执行」作废);原「单在途回合」「会话标题本地生成」「静默失败三前提」「数据目录对账」「提交垫时」全部作废;新增「任务 ID 6–64 字符」「两段前缀依赖上游版本」两条约束与风险;登录链路改为授权码 + 同源回调(T01-01 / T01-02 改写);阶段四新增用量聚合任务(T04-04 改为「用量聚合与胶囊」)。DSH Web 实测:纯文本 4 秒、工具调用带审批、多轮 tool_result 续答、图文 7 秒、SSE 七类事件、签名 24 字符跨轮;单测 15 文件 / 149 用例通过,tsc --noEmit 干净,ESLint 0 error。
2026-10-25补登图片接线、契约核对与智能体团队图片输入曾因能力已声明但读取未接线而静默丢图,修复后接入宿主附件服务并改为异步转换,实测读出图中文字与数字;T03-06 相应明确「未接线时不产生空 image 块」,风险表新增该失败模式。登记适配器契约核对结论:providerInfo / listModels / resolveModel / stream 为自定义实现,prepareCall / providerRetryPolicy / imageRequestTarget / imageRequestPricing 走官方默认实现,后两者返回空值属正确行为(宿主 ?? resolveRetryPolicy(...) 兜底)。T06-03 补智能体团队走查项:子代理是独立模型会话,复用同一条取流与工具调用路径,实测 27 秒完成并回传「子代理通」(1 轮 3 步、57.8K tok、缓存命中 68%,无 3012),因此该用例同时验证多会话场景下适配器完备。

基于 VitePress 构建