@bty/customer-service-cli

中文文档
0.8.5发布于 2026/11/01ES Module

AI Customer Service CLI - Agent friendly

原始使用文档
文档目录39 节
  1. 安装
  2. 通过 npm 全局安装(推荐)
  3. 从源码构建
  4. 源码入口与多行配置
  5. 默认 API 地址
  6. API 地址优先级
  7. 快速开始
  8. 同时登录 dev 与线上
  9. 全局选项
  10. 本地配置 ( .cs-cli.json )
  11. 工作空间优先级
  12. 使用方式
  13. set-workspace 写入规则
  14. 环境变量锁定(sandbox / CI)
  15. 命令权限
  16. 命令速查表
  17. 认证 ( auth )
  18. 配置 ( config )
  19. 工作空间 ( workspace )
  20. Agent 管理 ( agent )
  21. 系统配置 / 设备( system-config / device )
  22. 场景动作 ( sa )
  23. 工具 ( tool )
  24. 商品管理 ( product )
  25. 媒体上传 ( media )
  26. 活动管理 ( activity )
  27. 工单管理 ( issue )
  28. 聊天记录 ( chat-history )
  29. FAQ 知识库 ( faq )
  30. 扩展知识库 ( knowledge )
  31. 会话管理 ( conversation )
  32. Agent 调试 ( debug )
  33. 工作空间 ( workspace )
  34. 修复记录 ( repair-record )
  35. 运维操作记录 ( ops-record )
  36. 商品变更事件消费 ( change-consumer )
  37. 运营监控 ( monitor )
  38. 模型 Token 成本( token-usage ,需超级管理员(SYSTEM_ADMIN))
  39. 数据看板 ( dashboard )

AI 客服 CLI

供客户、内部人员与 Agent 调用的 AI 客服命令行工具。所有输出默认为 JSON 格式,便于程序解析。

安装

通过 npm 全局安装(推荐)

npm install -g @bty/customer-service-cli

安装后即可直接使用 cs-cli 命令。

从源码构建

pnpm install
pnpm build

构建产物位于 dist/bin.js,可通过 cs-cli 命令调用。

源码入口与多行配置

推荐在 packages/customer-service-cli 目录用 pnpm exec tsx src/bin.ts <args> 跑源码;生产配置写入须先取得明确授权,备份目标字段,写后回读并逐字核对。多行 SA 使用 UTF-8 文件(--situation-file / --action-file),Agent 补丁使用 --data @patch.json,文件读取保留 CRLF、末尾换行和字面反斜杠。

仓库的 pnpm --filter @bty/customer-service-cli --silent dev <args> 也保留真实换行。它通过本包启动器解码 pnpm 9 的原始 JSON 参数,并用无 shell 的 Node/tsx 运行 CLI,避免 pnpm 9 把 LF 变成字面 \n 或展开 $() 等内容;支持 macOS/Linux 的 POSIX shell + pnpm 9(仓库固定 9.15.4)。Windows、npm/yarn、其他 pnpm 大版本或不能解析的生命周期参数会停止执行,请改用上述 pnpm exec 入口。不要删掉 package.json 中 dev 脚本末尾的 #。

默认 API 地址

未传 --env 或使用 --env prod 时可使用以下内置地址;--env dev 需要先配置该环境的服务地址:

服务默认地址
客服 APIhttps://customer-servhub-api.betteryeah.com
Dashboard 只读 API客服 API 地址追加 /observability
AI APIhttps://ai-api.betteryeah.com
Customer Agenthttps://customer-agent.bantouyan.com
任务中心(learning-center)https://learning-center.betteryeah.com;--env dev 内置 https://dev-learning-center.betteryeah.com,无需配置
Langfusehttp://192.168.40.10:3000

AI API 同时服务于登录认证(auth login / auth whoami),不再区分独立的 "认证 API" 字段。

如需覆盖,可通过 cs-cli config set 修改:

cs-cli config set --cs-api https://your-api.example.com

Dashboard 命令会自动请求该地址下的 /observability/v1/dashboard/**。

API 地址优先级

未传 --env 时(等同线上,见下方「同时登录 dev 与线上」),每个 API 地址的读取顺序为 环境变量 > config.json > 内置默认值。环境变量为 undefined 或空字符串 "" 都视为未设置,继续向下 fallback。显式环境只读对应环境的配置;prod 可使用内置地址,dev 缺配置会报错,避免请求落到生产。

环境变量覆盖字段默认值
CS_CS_API_URLcustomerServiceApiUrlhttps://customer-servhub-api.betteryeah.com
CS_AI_API_URLaiApiUrl(同时服务 auth 调用)https://ai-api.betteryeah.com
CS_CUSTOMER_AGENT_URLcustomerAgentApiUrlhttps://customer-agent.bantouyan.com
CS_CS_ADMIN_URLcsAdminUrlhttps://customer-service-admin.betteryeah.com
CS_LEARNING_CENTER_URLlearningCenterUrlhttps://learning-center.betteryeah.com

快速开始

# 登录
cs-cli auth login --phone 13800000000 --password yourpassword

# 查看当前用户
cs-cli auth whoami

# 设置默认工作空间
cs-cli config set-workspace <workspace_id>

# 列出 Agent
cs-cli agent list

同时登录 dev 与线上

全局 --env dev|prod 选择本次命令的 API 地址、登录态和默认工作空间,放在一级命令前。不传 --env 就是线上,与 --env prod 共用同一份配置和登录态;只有 dev 必须写 --env dev。每个环境登录一次即可交替执行,无需反复改配置:

# 一次性配置 dev;替换为部署提供的真实地址
cs-cli --env dev config set --cs-api <dev客服API地址> --ai-api <dev登录及AI地址>
# 使用 Customer Agent / cs-admin 命令时再配置相应服务
cs-cli --env dev config set --agent-api <devCustomerAgent地址> --admin-api <dev后台地址>

cs-cli --env dev auth login --phone 13800000000 --password yourpassword
cs-cli --env prod auth login --phone 13800000000 --password yourpassword
cs-cli --env dev config set-workspace <dev工作空间ID> --global
cs-cli --env prod config set-workspace <线上工作空间ID> --global

cs-cli --env prod agent list
cs-cli --env dev agent list
cs-cli --env dev config get
cs-cli --env prod auth whoami
# 只退出 dev,prod 登录态仍可使用
cs-cli --env dev auth logout
  • 全局配置和凭据分别存入 ~/.cs-cli/environments/dev/ 与 ~/.cs-cli/environments/prod/。CS_CLI_HOME 只替换根目录;两个环境仍位于其 environments/ 子目录。凭据文件权限为 0600。
  • 登出、过期和 401 只清理发起请求的环境;未登录时提示带同一 --env 的登录命令。Dashboard 地址仍从该环境的客服 API 派生。
  • 未传 --env 按整个目录二选一,不拼两处的文件:environments/prod/ 目录存在(用过 --env prod 就有)就整体用 prod;没有 prod 目录、根目录有旧单环境文件时整体用根目录(与升级前一致,不用重登);两处都没有时用 prod。读写、401 / 过期清理都在选中的那个目录里;清掉 prod 凭据后仍是 prod(提示登录),不会落回根目录。有了 prod 目录后根目录旧 config.json 里的自定义地址、默认工作空间不再生效,要在 prod 里重新设置。
  • 未传 --env 的 auth logout 两处都清,根目录旧登录态一并清掉。显式 --env prod 只用 prod 目录、不看根目录,dev 永远不借用根目录或 prod。
  • 通用 CS_AUTH、CS_WORKSPACE_ID、CS_AGENT_ID、CS_CS_API_URL、CS_AI_API_URL、CS_CUSTOMER_AGENT_URL、CS_CS_ADMIN_URL、CS_LEARNING_CENTER_URL 没有环境归属,非空时与显式 --env 混用会报错,且不发请求。sandbox / CI 继续不传 --env 使用原注入方式;多环境调用先清除这些变量并配置各自环境。
  • config get 返回当前 environment(未传时为 prod)、实际使用的配置目录 configDir 及全局、本地配置。

Langfuse 通过 debug trace --langfuse-env dev|prod 单独选择;默认跟随全局 API 环境,未选 API 环境时默认 prod。旧的 debug trace <id> --env dev 仍只选择 Langfuse,API 环境保持原配置;若要同时选择 API 环境,必须把全局 --env 放在一级命令前。旧参数与 --langfuse-env 值冲突时拒绝执行。

cs-cli --env dev debug trace <trace_id>
cs-cli --env prod debug trace <trace_id> --langfuse-env dev

全局选项

选项说明默认值
--table以表格形式输出(默认 JSON)false
--env <dev|prod>本次 API 环境,独立配置与登录态prod(线上)
--workspace <id>覆盖默认工作空间 ID配置文件中的值
--request-timeout <ms>单个 HTTP 请求超时(毫秒);--timeout 是相关子命令的轮询窗口60000

本地配置 (.cs-cli.json)

支持在项目目录下放置 .cs-cli.json 文件,为不同项目配置不同的工作空间。

工作空间优先级

优先级来源说明
0CS_WORKSPACE_ID 环境变量env lock,最高优先级,override 硬失败(见下方"环境变量锁定")
1--workspace <id> 参数命令行临时覆盖
2.cs-cli.json (本地配置)当前目录或祖先目录
3~/.cs-cli/environments/<env>/config.json全局默认配置(未传 --env 见上方「同时登录 dev 与线上」的目录规则,可能是 prod 或根目录旧文件)

使用方式

# 在项目目录下初始化本地配置
cs-cli config init

# 设置工作空间(自动写入本地 .cs-cli.json)
cs-cli config set-workspace <workspace_id>

# 强制写入全局配置
cs-cli config set-workspace <workspace_id> --global

CLI 从当前目录向上查找 .cs-cli.json,找到第一个即使用其中的 workspaceId。

显式 --env 只读取同一文件的 environments.dev 或 environments.prod;缺该项则使用该环境的全局默认工作空间,不借用旧顶层 workspaceId 或另一环境。本地与全局默认值在查询参数及 HTTP workspace header 中使用同一优先级。config set-workspace 写入所选环境,保留另一环境和旧字段。未传 --env 仍读写旧顶层字段,与升级前一致。

.cs-cli.json 格式:

{
  "workspaceId": "ws-abc123",
  "workspaceName": "某客户项目"
}

同一目录保存两环境的格式:

{
  "environments": {
    "dev": { "workspaceId": "ws-dev", "workspaceName": "开发环境" },
    "prod": { "workspaceId": "ws-prod", "workspaceName": "线上环境" }
  }
}

set-workspace 写入规则

  • 当前目录或祖先目录存在 .cs-cli.json → 写入本地配置
  • 不存在 .cs-cli.json → 写入全局配置
  • 使用 --global → 强制写入全局配置

每次写入后会提示写入的目标路径。

环境变量锁定(sandbox / CI)

当 sandbox、CI 等非交互环境预先注入以下环境变量时,cs-cli 会透明地把 env 作为凭据与上下文来源,并拒绝任何运行时 override(--workspace / --agent / auth login 等),避免下游脚本在上下文被静默切换时产生未定义行为。

环境变量作用
CS_AUTH登录凭据(等同 access token)。存在即视为"已锁定"
CS_WORKSPACE_ID锁定工作空间 ID
CS_AGENT_ID锁定默认 agent ID

处理逻辑:

  1. env 优先:只要环境变量有值,cs-cli 就从 env 读取,忽略本地 credentials.json / .cs-cli.json / 全局配置。
  2. override 硬失败:锁定后如果再通过 --workspace / --agent / auth login / auth logout / config set-workspace 传入不一致的值,cs-cli 立刻报错退出,不会静默覆盖。
  3. 幂等传值:override 与 env 值完全一致时允许通过(便于脚本显式断言)。

使用示例:

export CS_AUTH="<your-access-token>"
export CS_WORKSPACE_ID="ws-abc123"
export CS_AGENT_ID="agent-xyz"

cs-cli agent list     # 直接运行,无需 auth login
cs-cli --workspace ws-other agent list   # ❌ 报错:CS_WORKSPACE_ID 已被锁定

要解除锁定,清空对应环境变量即可(unset CS_AUTH CS_WORKSPACE_ID CS_AGENT_ID)。

命令权限

客户与内部人员继续使用各自账号执行 auth login,共用登录体系。CLI 仅维护下表的 27 条内部受限命令,按当前账号的服务端 role_code 检查权限;未命中清单的命令不新增 CLI 角色校验,沿用原有登录与工作空间权限。

CLI 权限允许的角色命令范围
普通不增加平台角色要求商品、SA、FAQ、知识、会话、调试、看板等业务命令;包括 product feedback get/save/accept/restore/revoke/mode/disable-image/enable-image
内部普通DEVELOPER、ADMIN、SYSTEM_ADMINchannel-metric query/backfill、monitor fields、monitor tickets list/delete、全部 ops-record 与 special-project 子命令、普通 key 的 system-config get
内部高级ADMIN、SYSTEM_ADMINagent fork
系统管理员SYSTEM_ADMINagent engine get/set、device list、token-usage summary、monitor agents/workspaces/statistics 与 monitor snapshots hourly/daily/daily-range

system-config get 的以下四个 key 要求 SYSTEM_ADMIN:installer_package_api_keys、sop_main_engine_config、sop_main_engine_request_config、sop_main_engine_flow_service_config;其他 key 要求内部普通权限。SHOP_MANAGER、ASSISTANT 及未知角色不能执行内部命令。平台角色通过 CLI 检查后,服务端仍会执行原有业务和资源权限校验。

执行内部命令前,CLI 使用当前环境的登录凭据请求客服 API GET /v1/user/profile,不把角色写入凭据文件,也不跨进程缓存。角色无法确认或请求失败时,不执行目标业务命令;仅注入 CS_AUTH 而未设置 workspace 时,也能查询角色。auth、config、帮助和普通命令不增加此请求,auth whoami 仍返回原用户中心身份信息。

仅受限命令的 --help 增加权限标签。角色不足时输出 JSON 错误并以退出码 1 结束;未登录或 Token 失效为 2,网络或服务器错误为 3。本限制作用于本版 CLI;服务端接口与旧版 CLI 的行为未作调整。

本版移除了测试集与节点模板命令组,相关子命令不再注册;Sol 的 debug replay / debug overlay 流程保留。

命令速查表

认证 (auth)

命令说明
auth login --phone <手机号> --password <密码>登录
auth logout退出登录
auth whoami查看当前登录用户

配置 (config)

命令说明
config set [--cs-api <url>] [--ai-api <url>] [--agent-api <url>] [--admin-api <url>] [--learning-center <url>]设置当前环境的 API 地址
config get查看当前配置(含全局和本地)
config init在当前目录初始化本地配置 (.cs-cli.json)
config set-workspace <workspace_id> [--global]设置默认工作空间

工作空间 (workspace)

命令说明
workspace list列出所有工作空间
workspace points-consumes-daily [--start <YYYY-MM-DD>] [--end <YYYY-MM-DD>]按天查询工作空间积分消耗(默认最近 30 天)

workspace points-consumes-daily 需要可用的工作空间上下文(--workspace、本地 .cs-cli.json 或全局 defaultWorkspaceId)。

# 查询最近 30 天(默认)
cs-cli workspace points-consumes-daily

# 指定日期范围(含 start/end)
cs-cli workspace points-consumes-daily --start 2026-04-01 --end 2026-04-23

Agent 管理 (agent)

命令说明
agent list [--keyword <名称>] [--page N] [--page-size N] [--fields <路径,...>] [--raw]列出 Agent 列表;--keyword 按名称模糊搜索;--fields 裁每一条记录;--raw 不遮蔽凭据
agent get <config_id> [--fields <路径,...>] [--raw]获取 Agent 详情;--fields 只输出指定字段;--raw 不遮蔽凭据
`agent update <config_id> --data <json@file>`
agent fork --source-customer-config-id <id> --target-workspace-id <id> [选项]复制 Agent;CLI 要求内部高级权限(ADMIN 或 SYSTEM_ADMIN);同空间仍校验当前用户权限,跨空间服务端仍仅允许 SYSTEM_ADMIN
agent engine get <config_id>查看 Agent 独立层引擎版本(顶层 + 设备定向;null 按 classic 跑),需超级管理员(SYSTEM_ADMIN)
agent engine set <config_id> --to v2|v3|v4 [--device <设备ID>] / --device <设备ID> --clear切换引擎版本(写线上);不带 --device 为整体切换并清掉设备定向;返回切换前版本

agent list 每条都带完整 customer_config,单页可达数十万 token;只要 id 和名字时用 agent list --keyword <店名> --fields config_id,config_name。--fields 逗号分隔,点号取嵌套(如 customer_config.xxx),路径途经数组时作用到每个元素,不存在的路径直接省略,输出保持原嵌套结构;list 作用于 .data.items 每一条,分页字段保留;返回体没有 items 数组时往 stderr 打警告并对整个返回体裁剪。不带 --fields 时输出除凭据遮蔽外与之前相同。

agent get / agent list 默认按键名遮蔽凭据字段,值替换为 [REDACTED len=N]。规则比 debug trace 窄,只看键名、不扫正文:整键 token / session / authorization(仅字符串值)/ ak / sk / dsn / database_url,或键名(去掉 _、- 并转小写后)以 secret、password、passwd、access_token、refresh_token、api_token、auth_token、security_token、bearer_token、session_token、id_token、session_key、api_key、app_key、access_key、secret_key、private_key、cookie(s)、credential(s) 结尾;命中的数字值也遮(平台 appkey 常是纯数字),布尔、null、空串和空对象 / 数组不遮,值是 JSON 字符串时按同一规则处理其中的键。max_token、keep_session、need_authorization、cookie_rule、password_hint 这类键以及 prompt 正文里的 Cookie: 曲奇 不会被遮。agent update --data 里出现 [REDACTED len=N] 时会在调用接口前拒绝,所以带遮蔽占位的内容不能回传,只传要改的字段。确实需要真实值时加 --raw 关闭遮蔽:输出含明文凭据,不要贴进对话、日志或工单。

agent fork 必须显式指定来源 Agent 配置 ID 和目标工作空间 ID。--copy-product-data、--copy-activity-data 默认开启,可分别用 --no-copy-product-data / --no-copy-activity-data 关闭。--clone-tools 会复制来源 Agent 当前已绑定的全部工具(包括系统工具和自定义工作流工具),默认不复制;多数场景建议开启。--copy-authorized-shop-id 让克隆的工具沿用来源工具的店铺授权 authorized_shop_id,默认清空;仅与 --clone-tools 同用生效,只在用户明确要求全量复制工具时开启。--shop-id 可显式指定目标店铺 ID。

agent engine 读写的是 Agent 独立层的 version(v2=classic / v3=Luna / v4=Sol),这是 sop 收到的 extra.version 的唯一来源;判断引擎不要用 /effective 的合并结果。店铺还要在 sop_main_engine_config 的 internal 路由里(system-config get sop_main_engine_config),版本才会生效。

agent engine get/set、device list 和 token-usage summary 要求超级管理员(SYSTEM_ADMIN)账号。system-config get 按 key 区分权限,见下表;角色不足时应由具备相应权限的账号执行。

系统配置 / 设备(system-config / device)

命令说明
system-config get <key>读一条全局 system_config;普通 key 要求内部普通权限,四个敏感 key 要求 SYSTEM_ADMIN(见「命令权限」)
device list [--workspace-id <id>] [--channel <渠道>] [--equipment-id <id>] [--page N] [--page-size N]需 SYSTEM_ADMIN;分页列出设备,返回的 version 是客户端版本,不是引擎版本

场景动作 (sa)

命令说明
sa list --agent <id> [--intent <意图>] [--first-label <标签>] [--second-label <标签>]列出场景动作
sa search --agent <id> --keyword <关键词>搜索场景动作
sa create --agent <id> --first-label <一级标签> --second-label <二级标签> --situation <场景> --action <动作> [--transfer] [--intent <意图>]创建场景动作
sa update --agent <id> --id <SA_ID> --first-label <一级标签> --second-label <二级标签> --situation <场景> --action <动作> [--transfer]更新场景动作
sa delete --agent <id> --id <SA_ID> --first-label <一级标签> --second-label <二级标签>删除场景动作
sa versions --agent <id> --id <SA_ID>查看修改记录

sa create/update 的场景必须从 --situation <文本> 与 --situation-file <路径> 中选一个,动作必须从 --action <文本> 与 --action-file <路径> 中选一个;两字段均必传,可混用文本与文件。文本参数含字面 \n 且没有真实 CR/LF 时会在调用 API 前拒绝,不会自动替换;有意写入字面 \n 请放入文件。--situation/--action @file 仍是普通文本,不读取文件。sa update 仍为全量更新,标签及转人工等字段需按备份回填。

# 本包目录,示例使用已配置的 dev;仅在确认范围与备份后执行
pnpm exec tsx src/bin.ts --env dev --workspace <workspace_id> sa update \
  --agent <agent_id> --id <SA_ID> --first-label <一级标签> --second-label <二级标签> \
  --situation-file ./situation.md --action-file ./action.md

工具 (tool)

命令说明
tool list --agent <id>列出该 Agent 配置已绑定的工具(custom + system)
tool create --agent <id> --name <名称> --key <标识> --source-id <flow_id> [--description <描述>] [--source-type <类型>] [--invocation-mode <模式>] [--input-vars <json>]创建绑定工作流(flow)的自定义工具
tool update <tool_id> [--name <名称>] [--key <标识>] [--description <描述>] [--source-id <flow_id>] [--invocation-mode <模式>] [--input-vars <json>]更新工具(仅透传实际提供的字段)
tool delete <tool_id>删除(软删除)指定工具
tool workflow list [--keyword <关键词>]搜索可绑定的工作流(flow),取 source_id
tool workflow detail <flow_id>查看工作流入参,辅助填 --input-vars
tool workflow create --name <名称> --code <code|@file> [--description <描述>] [--input-vars <json|@file>] [--no-publish] [--code-node-name <名称>] [--version-desc <描述>]创建 START→CODE→END 骨架工作流,CODE 节点承载工具代码(仅 JavaScript),默认自动发布
tool workflow update <flow_id> --code <code|@file> [--no-publish] [--version-desc <描述>]只更新工作流唯一 CODE 节点的代码(其它节点原样保留),默认自动发布
tool workflow run <flow_id> [--input <json|@file>]运行已发布的工作流(HTTP 同步执行),返回 task_id / status / run_result
tool workflow delete <flow_id> --yes硬删除工作流(不可恢复);缺 --yes 拒绝执行
tool workflow describe输出 CODE 节点(JavaScript)使用文档:入口/变量注入/返回值/内置包/SDK,依据官方文档整理

tool 命令组包装 customer-servhub-api 现有 /v1/tool 接口,管理 Agent 的自定义/覆盖工具;CLI 不改变服务端工具表或 sop-engine 的工具执行逻辑。--invocation-mode 取值 must_invoke / on_demand(默认)/ on_demand_async,非法值在发请求前本地报错;tool create --input-vars 接受 JSON 字符串,形如 {"order_id":{"description":"订单号","type":"string","required":true}},对应工作流入参描述;workspace_id 由当前工作空间自动回填。

tool workflow create/update/run/delete 直连 BetterYeah 平台(ai-api)程序化管理工作流本体:create 生成固定 START→CODE→END 三节点骨架并把代码写进 CODE 节点、默认发布,返回 flow_id 供 tool create --source-id 绑定;update 只暴露 CODE 节点代码的修改;run 是 HTTP 同步执行(自动经 GET /v1/workspaces/getKey/{ws} 用登录态换应用态 Access-Key 再调 execute_flow,替代平台画布的 wss 通道),--input 的键对应 START formConfig 的 variableName(默认 {});delete 是硬删除、必须显式 --yes。create/update 发布时可用 --version-desc 附版本描述(平台版本历史里可见,便于区分 CLI 改动;--no-publish 时忽略)。CODE 节点只支持 JavaScript(CommonJS require,不支持 ES Module)。--code / --input-vars 的值以 @ 开头时按文件路径读取(如 @./tool.js)。注意 tool workflow create --input-vars 覆盖的是 START 节点的 formConfig 入参声明,与 tool create --input-vars(工具记录的 input_var_descriptions)是不同字段。tool workflow describe 输出依据官方 JavaScript&Python 节点文档整理的 CODE 节点使用文档(入口 main()、变量注入、返回值约定、内置包、BetterYeah SDK),AI 编写工具代码前应先读。

商品管理 (product)

命令说明
product list --agent <id> [--keyword <关键词>] [--status <状态>] [--tag <标签>]列出商品
product get --agent <id> --product-id <商品ID>获取商品详情(自动获取 db_id)
product update --agent <id> --product-id <商品ID> --update <json|@file>更新商品信息
product shelf --agent <id> --status <上架|下架|预售> (--ids <id,id> | --ids-file <path>) [--concurrency <n>] [--yes]批量设置商品状态(上架 / 下架 / 预售,写「商品状态」列,写后回读校验)
product update-sku --agent <id> (--sku <SKU名称> | --sku-id <id>) --update <json|@file>更新 SKU 信息(--sku-id 优先于 --sku)
product add --agent <id> --data <json|@file> [--source <type>] [--no-identify]直接传入结构化商品数据(JSON 数组)异步学习(manual / identify 默认开启)
product learn --agent <id> --url <URL...> [--source <type>] [--no-identify]通过商品 URL 异步学习(manual / identify 默认开启)
product identify-all --agent <id>一键增强学习当前 Agent 下所有待增强商品
product sync-taobao --agent <id> [--skip-hash-check] [--sync-type <full|incremental>]触发淘宝店铺商品同步
product sync-taobao-item --agent <id> --product-id <商品ID>触发单个淘宝商品同步
product related-knowledge list --agent <id> --product-id <商品ID>列出商品详情绑定的 QA / 扩展知识库文件
product related-knowledge add --agent <id> --product-id <商品ID> --type <qa|common> (--file <文件名> | --file-id <id> --partition-id <id>)给商品追加关联知识库文件
product related-knowledge remove --agent <id> --product-id <商品ID> --type <qa|common> --file-id <id>移除商品绑定的指定知识库文件
product related-knowledge set --agent <id> --product-id <商品ID> --bindings <json|@file>覆盖商品绑定的全部知识库文件
product supplement list --agent <id> --product-id <商品ID>列出商品补充知识条目(含每条的 question / answer / images / videos)
product supplement add --agent <id> --product-id <商品ID> --question <Q> --answer <A> [--image <path|url>...] [--video <path|url>...] [--dry-run] [--backup <path>]新增一条补充知识(Q/A + 可选图片/视频);本地媒体自动上传公开 OSS,URL 直写;read-modify-write 保留旧条目
product supplement append-media --agent <id> --product-id <商品ID> --index <n> [--image ...] [--video ...] [--dry-run] [--backup <path>]向指定下标条目追加图片/视频,其它条目原样保留、去重合并

product update 支持更新的字段包括:卖点、补充知识、tag、参数、轮播图识别结果、商品详情页识别结果 等。--update 接受 JSON 字符串或 @文件路径。

product add 与 product learn 走同一个上传接口(/v1/knowledge/products/upload),区别在于载荷:add 传结构化商品数据 product_items(已抓好的商品详情 JSON 数组),learn 传 product_urls(让后端去抓)。--data 接受 JSON 字符串或 @文件路径;传单个对象会自动包成数组,传 JSON 基本类型(数字 / 字符串等)会直接报错;--source 默认 manual,--no-identify 关闭自动识别。

product learn 提交商品详情页 URL 进入异步学习队列(/v1/knowledge/products/upload),返回 flow_id 和 knowledge_ids。--url 可多值,用空格分隔;--source 默认 manual;传 --no-identify 可关闭自动识别。

product identify-all 对接 POST /v1/knowledge/products/identify/all,会为当前 Agent 一键提交所有“已可用但尚未增强”的商品进入增强学习队列。它不是全量重学;当没有待增强商品时,服务端会返回“暂无需要识图的商品”。

product sync-taobao / product sync-taobao-item 调用 customer-servhub-api 的授权店铺同步接口,要求 --agent 已唯一绑定一个淘宝授权店铺。前者支持 --sync-type full|incremental,默认 full;后者按 product_id 补同步单个淘宝商品。

注意:这两个命令仅对已开通“高级工具”的店铺 Agent 生效。未开通高级工具时,即使 --agent 已绑定淘宝授权店铺,请求也可能在服务端失败。

product related-knowledge 管理商品详情的“关联知识库”文件级绑定。--type qa 对应 FAQ 知识库,--type common 对应扩展知识库。add / remove 会先读取当前绑定,再通过服务端全量替换接口写回;重复添加或移除不存在的文件保持幂等。--file <文件名> 会按当前 Agent 的知识库文件列表做精确匹配;文件名不存在或不唯一时,改用 --file-id + --partition-id 显式模式。

product supplement 维护商品「补充知识」的带图/视频问答(结构为 { question, answer, images: [URL], videos: [URL] }),与前端商品详情页的补充知识上传一致。写入采用 read-modify-write:先 product get 读取并解析当前补充知识,本地合并后再调既有 /v1/knowledge/product/update,绝不用新增项覆盖旧条目。--image / --video 可重复传多个,值可以是本地文件(先经 /v1/upload_sts 取 STS 凭证上传公开 OSS,key 为 /ai/knowledge/supplement/${timestamp}_${filename})或已有 http(s) URL(直写不重复上传)。图片限 image/* ≤ 10MB、视频限 video/* ≤ 200MB,超限或类型不符在发起上传请求前直接失败。--dry-run 只输出将写入的最终 JSON、不落库、不上传;--backup <path> 在写前把当前补充知识快照到本地文件。append-media 仅向 --index 指定的条目追加媒体,去重合并,其它条目原样保留。

单文件上传也可单独用 media upload(见下方「媒体上传」小节),拿到公网 URL 后再作为 --image / --video 的值传入。

# 更新卖点
cs-cli product update --agent <id> --product-id <商品ID> --update '{"卖点":"新卖点内容"}'

# 更新标签
cs-cli product update --agent <id> --product-id <商品ID> --update '{"tag":"[\"春季新品\",\"热卖\"]"}'

# 添加商品补充知识
cs-cli product update --agent <id> --product-id <商品ID> --update '{"补充知识":"[{\"question\":\"问题\",\"answer\":\"回答\"}]"}'

# 更新 SKU 补充知识(按 SKU 名称定位)
cs-cli product update-sku --agent <id> --sku "颜色分类:粉红" --update '{"补充知识":"说明内容"}'

# 更新 SKU 补充知识(按 sku_id 定位,推荐)
cs-cli product update-sku --agent <id> --sku-id 6072595054179 --update '{"补充知识":"说明内容"}'

# 给商品绑定一个 FAQ 文件
cs-cli product related-knowledge add --agent <id> --product-id <商品ID> --type qa --file "常见问题.xlsx"

# 显式 ID 模式绑定扩展知识文件
cs-cli product related-knowledge add --agent <id> --product-id <商品ID> --type common --file-id 622474 --partition-id 12345 --file-name "售后规则.md"

# 查看商品当前补充知识条目
cs-cli product supplement list --agent <id> --product-id <商品ID>

# 新增一条带图问答(本地图片自动上传,已有 URL 直写)
cs-cli product supplement add --agent <id> --product-id <商品ID> \
  --question "尺码怎么选?" --answer "参考尺码表,拍下留言身高体重" \
  --image ./size-chart.png --image https://xxx.com/a.png

# 先 dry-run 预览最终写入 JSON,不落库
cs-cli product supplement add --agent <id> --product-id <商品ID> \
  --question "Q" --answer "A" --video ./demo.mp4 --dry-run

# 向第 0 条补充知识追加媒体,写前备份
cs-cli product supplement append-media --agent <id> --product-id <商品ID> \
  --index 0 --image ./extra.png --backup ./supplement-backup.json

媒体上传 (media)

命令说明
media upload --file <path> [--type <image|video>] [--path-prefix <prefix>] [--dry-run]上传单个本地图片/视频到公开 OSS,返回可访问 URL

media upload 把单个本地文件上传到公开 OSS(resource_bucket),返回公网 URL,供 product supplement 的 --image / --video 复用。凭证走 GET /v1/upload_sts(返回 AES-CBC 加密,CLI 内解密),上传 key 为 <path-prefix>/<timestamp>_<filename>,--path-prefix 默认 /ai/knowledge/supplement。--type 缺省时按扩展名推断;图片限 image/* ≤ 10MB、视频限 video/* ≤ 200MB,超限/类型不符在发起上传前直接拒绝。传入的 --file 如果本身是 http(s) URL 会被拒绝(无需上传)。--dry-run 仅校验并输出将要上传的信息、不实际上传。

# 上传本地图片,拿到公网 URL
cs-cli media upload --file ./banner.png --type image

# 自定义路径前缀 + 预览(不实际上传)
cs-cli media upload --file ./demo.mp4 --path-prefix /ai/knowledge/supplement --dry-run

活动管理 (activity)

活动 V2(Issue #34)增删改查 + per-tenant V2 总开关。服务端 customer-servhub-api /v1/activity*;契约详情参见 docs/devkit/specs/2026-05-28-activity-v2-api-reference.md。

命令说明
activity list --agent <id> [--page N] [--page-size N] [--search <text>]列出活动(返回 total / v2_activity_enabled / items[])
activity by-product --agent <id> --product-id <id>按 product_id 反查当前生效活动(仅 enabled、product_scope='all' 必入)
activity create --data <json|@file>创建活动(payload 见 IActivityWritePayload)
activity update <activity_id> --data <json|@file>整体更新活动(products 整组替换,非增量)
activity set-enabled <activity_id> --enabled <true|false>切换单条活动启用状态(仅写 enabled)
activity delete <activity_id>软删活动 + 级联软删关联
activity v2-enabled --agent <id> --enabled <true|false>per-tenant 启停 V2 链路
  • --agent <id> 对应服务端 customer_agent_config_id(与 sa / product 命令同口径)。
  • activity create / update payload 必填:customer_agent_config_id、activity_name、effective_type、activity_rule;effective_type=time_range 要求 start_time + end_time;product_scope='specific'(缺省)要求 products ≥ 1。
  • 业务失败(参数非法 / 跨 workspace / 不存在)服务端返 HTTP 200 + code:400,CLI 转为 exit 1 并打印 INVALID_PAYLOAD: …。
# 列出活动
cs-cli activity list --agent <cfg_id> --search 返现

# 按商品反查
cs-cli activity by-product --agent <cfg_id> --product-id 914494989518

# 创建活动(从文件读 payload)
cs-cli activity create --data @activity.json

# 整体更新
cs-cli activity update 6 --data @activity.json

# 列表行 toggle 启用
cs-cli activity set-enabled 6 --enabled false

# 软删活动
cs-cli activity delete 6

# 为某 agent 启用 V2 链路
cs-cli activity v2-enabled --agent <cfg_id> --enabled true

工单管理 (issue)

命令说明
issue list [--agent <id>] [--status <状态>] [--priority <优先级>] [--start <日期>] [--end <日期>]列出工单
issue get <issue_id>获取工单详情
issue create --title <标题> --content <内容> [--priority <优先级>] [--tags <标签>]单条创建工单
issue create --file <path> | --stdin [--dry-run] [--concurrency <n>] [--yes]批量创建工单(JSON 协议见下)
`issue update <issue_id> --data <json@file>`
`issue update --ids <a,b,c> | --ids-file --data <json@file> [--dry-run] [--concurrency ] [--yes]`
issue update-owner <issue_id> --owner <user_id|花名>单条改派负责人(花名自动解析)
issue update-owner --ids <a,b,c> | --ids-file <path> --owner <user_id|花名> [--dry-run] [--yes]批量改派负责人(走 cs-admin BFF,原子改派 + 自动 Feishu/DingTalk 通知,单批 ≤ 200)
issue stats [--start <日期>] [--end <日期>]各工作空间 Issue 统计(open/closed/total)
issue comment list <issue_id>列出工单评论
issue comment add <issue_id> --content <内容>添加评论

批量写约定(update / update-owner / create --file)

  • --ids "a,b,c" 与 --ids-file path.txt(一行一个 id,# 注释、空行忽略)互斥;与单条 <issue_id> 互斥。
  • --owner 同时接受 user_id(≤ 7 位纯数字)和工程师花名。花名经 cs-admin /api/account-roles 解析(KA + SMB 合并去重,5 分钟内存 cache),同名 / 模糊歧义会报错列 candidates。--owner 拒绝 11 位手机号(Issue #49,老 --owner-phone 0.5.0 起硬删)。
  • --dry-run 在所有批量子命令上都不会调写接口;create --file --dry-run 会真跑 user_name → conversation_id 反查,以便提前发现 NOT_FOUND / AMBIGUOUS。
  • N ≥ 20 且 stdout 是 TTY 时弹二次确认(输入 yes);非 TTY 必须显式 --yes,否则拒收。
  • 末尾报告统一 schema:{version:"1", total, success_count, failed_count, skipped_count, aborted, success_ids[], failed[{id,code,msg}], skipped[{id,reason}]}。退出码:0 全成功 / 1 全失败 / 2 部分失败 / 130 SIGINT。
  • update-owner --ids 走 cs-admin BFF POST /api/workbench/issues/batch-owner 单次调用(原子),返回 {updated, skipped:[{issueId, reason}], notify[]},与 update 的 runBatch 报告 schema 不同(保留 BFF 原样)。
  • 双后端单 token:servhub Bearer JWT 同时通过 cs-admin BFF 鉴权(实测验证),无需额外登录。

issue create --file JSON 协议

文件解析交给上游(LLM/Agent/脚本)整理成下面这份结构化 JSON,CLI 只做校验 + 反查 + 拼装 + 批量创建。

{
  "version": "1",
  "workspace_id": "ws_xxx",          // 顶层,对所有 issue 生效;缺省时落到默认 workspace
  "issues": [
    {
      "title": "客户反馈:A 问题答非所问",   // 必填
      "priority": "high",              // 必填,critical|high|medium|low
      "expected": "应该回答 X",          // 必填,CLI 把它写进 content 的 ## Expected 段
      "description": "上下文描述",       // 可选,拼在 expected 前面
      "conversation_id": "conv_xxx",   // 与 user_name 二选一
      "user_name": "张三",              // 仅给昵称时,CLI 调 /v1/chat/conversations?user_name= 反查
      "tags": ["badcase"],             // 可选
      "source_type": "manual_review",  // 可选
      "source_data": {"reviewer": "..."} // 可选
    }
  ]
}

CLI 把 description + expected 拼成 content:

{description}(如有)

## Expected
{expected}

user_name 反查规则(5 分钟内存 cache,key = ${workspaceId}|${userName}):

  • 1 条命中 → 用其 conversation_id
  • 0 条 → 该 issue 标记 NOT_FOUND,整批拒收(防止半批进创建)
  • 多条 → 该 issue 标记 AMBIGUOUS,提示改传显式 conversation_id

priority 不在枚举内、title/expected 缺失等 → 客户端直接拒收(不打任何接口)。

聊天记录 (chat-history)

查询客户导入的聊天记录,用于 SA(场景动作)清洗,非 Agent 自身的对话记录。

命令说明
chat-history --agent <id> [--page N] [--page-size N]查询客户导入的聊天记录

FAQ 知识库 (faq)

命令说明
faq list --agent <id>列出 FAQ 文件
faq content --agent <id> --file <文件名> [--keyword <词>] [--page-size <n>] [--next-group-id <id>]列出文件内答案组(含 answer_group_id / 问题 / 答案)
faq add --agent <id> --file <文件名> --questions <问题1,问题2> --answers <答案=xxx>添加 FAQ 内容
faq update --agent <id> --file <文件名> --group-id <id> [--questions <...>] [--answers <...>] [--delete-chunks <id1,id2>]更新已有 FAQ 答案组(--questions / --answers / --delete-chunks 至少一个)
faq delete --agent <id> --file <文件名> --group-id <id>删除 FAQ 答案组
faq bind-products list --agent <id> (--file <文件名> | --file-id <id> --partition-id <id>)列出 FAQ 文件绑定的商品
faq bind-products add --agent <id> (--file <文件名> | --file-id <id> --partition-id <id>) --product-id <商品ID...>给 FAQ 文件追加绑定商品
faq bind-products remove --agent <id> (--file <文件名> | --file-id <id> --partition-id <id>) --product-id <商品ID...>从 FAQ 文件移除绑定商品
faq bind-products set --agent <id> (--file <文件名> | --file-id <id> --partition-id <id>) --product-id <商品ID...>覆盖 FAQ 文件绑定的全部商品

faq content 走 GET /mebsuta/api/v1/dataset/{knowledge_id}/faq_contents,列出文件内的答案组及其 answer_group_id,是 faq update / faq delete 拿 --group-id 的来源(faq list 只给文件,文件内的 group-id 要靠这条命令查)。支持 --keyword 搜索、--page-size 分页、--next-group-id 游标续翻。

faq update 按 answer_group_id 定位目标组,先读回这组的现值,只覆盖显式传入的字段,再 POST 同一个 faq_contents/save 接口完成字段替换、问题替换与 chunk 级删除。--questions 整组替换问法,没列出的原问法会被删掉。读不到现值、合并后没有问题或没有非空答案时拒绝保存。faq delete 走 DELETE /faq_contents/{group_id} 整组删除。

faq bind-products 固定写入 knowledge_type=qa 的商品绑定关系,适合从 FAQ 文件视角批量维护关联商品。--file 为精确文件名匹配;文件名不唯一时请传 --file-id 和 --partition-id。

扩展知识库 (knowledge)

Agent 关联的通用规则知识库(suffix_type=_common),与 FAQ / 商品知识并列的第三类知识源,支持段落(chunk)级 CRUD,统一走 /mebsuta/api/v1/dataset/{id}/contents/perform-operations。

命令说明
knowledge list --agent <id> [--page N] [--page-size N]列出 Agent 关联的扩展知识库文件
knowledge content list --knowledge-id <id> [--page-size N] [--direction up|down]列出段落(chunk)
knowledge content add --knowledge-id <id> --content <text|@file> [--keyword <k...>] [--after <chunk_id>]新增段落
knowledge content update --knowledge-id <id> --chunk-id <id> [--content <text|@file>] [--keyword <k...>] [--enable | --disable]更新段落(四个变更字段至少一个;未指定 --enable / --disable 时自动保留当前启停状态,避免后端 enable 必填校验失败)
knowledge content delete --knowledge-id <id> --chunk-id <id>删除段落
knowledge bind-products list --agent <id> (--file <文件名> | --file-id <id> --partition-id <id>)列出扩展知识文件绑定的商品
knowledge bind-products add --agent <id> (--file <文件名> | --file-id <id> --partition-id <id>) --product-id <商品ID...>给扩展知识文件追加绑定商品
knowledge bind-products remove --agent <id> (--file <文件名> | --file-id <id> --partition-id <id>) --product-id <商品ID...>从扩展知识文件移除绑定商品
knowledge bind-products set --agent <id> (--file <文件名> | --file-id <id> --partition-id <id>) --product-id <商品ID...>覆盖扩展知识文件绑定的全部商品

knowledge content add / update 的 --content 支持 @路径 前缀从文件读取纯文本(不是 JSON)。--keyword 为 variadic 选项,空格分隔多个关键词。

knowledge bind-products 固定写入 knowledge_type=common 的商品绑定关系,适合从扩展知识文件视角批量维护关联商品。add / remove 会 read-modify-replace,重复添加或移除不存在的商品保持幂等。

会话管理 (conversation)

命令说明
conversation list [--agent <id>] [--equipment-id <设备ID>] [--user <用户名>] [--start <日期>] [--end <日期>] [--query-content <文本>]搜索会话;--start/--end 按会话 updated_at 过滤(按时段算转人工率用 transfer-human);--query-content 按消息内容搜索,必须同时给起止时间
`conversation records <conversation_id> [--page-size N] [--direction prevnext] [--current-id | --all]`
conversation context-search (--query <文本> | --user <用户名>) [--limit <1~500>] [--start <时间>] [--end <时间>]通过上下文内容或买家用户名模糊搜索对话记录(返回匹配消息详情,时间范围最多 3 天)
conversation find-order <订单号> --agent <id> --start <时间> --end <时间>按订单号反查会话与 record_id;超过 3 天自动按 3 天分段顺序查询,总跨度最多 31 天
conversation transfer-human --agent <customer_agent_config_id> --start <时间> --end <时间> [--only-abnormal]查询转人工会话及对应转人工消息记录(时间范围最多 7 天,自动 cursor 翻页;--only-abnormal 仅保留异常会话)

Agent 调试 (debug)

命令说明
debug ask --agent <id> (--text <消息> | --messages <json|@file>) [--user <用户名>] [--url <图片URL>] [--conversation <会话ID>] [--mock <json|@file>] [--expect <file>] [--data-overlay <json|@file> | --overlay <dir>] [--timeout <秒>] [--poll-interval <毫秒>]向 Agent 发送消息并等待回复
debug reproduce <record_id> [--agent <id>] [--mock <json|@file>] [--expect <file>] [--data-overlay <json|@file> | --overlay <dir>] [--replace-last <文本>] [--image <URL>] [--timeout <秒>] [--poll-interval <毫秒>] [--dry-run]根据 record_id 复现 Agent 回复(自动获取上下文);--replace-last / --image 换掉最后一条买家消息
debug data snapshot --agent <id> [--product-id <商品ID...>]生成可传给 --data-overlay @file 的 debug 数据覆盖 JSON
debug record <record_id...> [--out <file.ndjson>]获取记录的调试信息(flow_info);多个 id 时最多 3 路并发,--out 按 NDJSON 每行一条写盘(附 engine / flow_engine),stdout 只给汇总;返回中包含 trace_id;Sol 引擎有存档时另有 sol_trace_id 与 sol_trace(服务端 view=diagnosis 的原样结果)
debug trace <trace_id> [--langfuse-env <dev|prod>]根据 Langfuse Trace ID 获取完整 Trace 详情(经所选环境的服务端代理);Sol 轮次另附 sol_trace(服务端 view=diagnosis)
debug trace (<st-…> | --record <record_id>) [--view summary|prompt|lean|full|otel] [--call <node>] [--out <file>]Sol 引擎单轮完整 prompt 存档(服务端展开并逐字节校验);默认摘要
debug trace --date <YYYY-MM-DD> [--agent <id>] [--out <dir> [--label <l>]... [--node <n>]... [--limit <n>]]某天 Sol 存档按 workspace + agent 合并好的调用文件:列条数 / 下载并筛选
debug replay export (--trace <id...> | --record <id...> | --conversation <id> [--until <N>]) --out <case.json>导出同一会话的 Sol 轮次上下文及商品快照;--conversation 按会话自动收集 Sol trace
debug replay append --case <case.json> --after <N> --text <text...> [--clock <iso>] --out <new-case.json>离线:保留前 N 轮,接一轮自定义买家消息(只能 rollout 跑)
debug replay open --case <case.json> [--mode rollout|original] [--products <snapshot.json>] [--mocks <mocks.json>] [--products-patch <patch.json>] --out <run.json>初始化本地运行文件,默认沿用 dev 状态逐轮执行;可带工具 mock 与商品局部补丁
debug replay next --run <run.json>执行下一轮并保存完整结果与状态
debug replay run --run <run.json> [--until <N>]从保存的进度继续,逐轮落盘
debug replay fork --run <run.json> --at <N> [--products <snapshot.json>] [--mocks <mocks.json>] [--products-patch <patch.json>] --out <new-run.json>保留前 N 轮与对应状态,在新文件继续验证
debug replay inspect --run <run.json> [--turn <index>] [--view <view> | --path <pointer>] [--offset <N>] [--limit <N>] [--out <file>]只读本地摘要/卡片/工具/原文,按需取证
debug replay tools --run <run.json...> [--tool <name...>] [--turn <index>] [--limit <N>]只读:多个运行文件的逐工具调用次数、调用率、数据来源与缺录制
debug replay compare --baseline <run.json> --candidate <run-b.json> [--expect <expected.json>] [--ab] [--out <file>]同输入字段差异与显式断言(含 called / not_called 工具调用断言),区分执行和验证;两边 case.overlay hash 不同时默认拒绝,--ab 声明为配置 A/B
debug mock init --case <case.json> --out <mocks.json>从回放包已录制的工具调用生成 tool-mock/v1 骨架(fill;回放 / sol-local 用)
debug overlay init (--case <case.json> | --agent <id>) --out <dir> [--base current|incident] [--turn <N>] [--product <id...>]只读:把回放基线拉成可编辑的覆盖目录(Sol 含 tools.json;--product 预填 products_patch.json)
debug overlay build [--case <case.json>] --overlay <dir> [--out <file>] [--format sol|v1|online]离线:把覆盖目录合并进 case 的 overlay 段(含 tools),并写 products_patch / tool_mocks(classic 输出 debug_data_overlay v1);--format online 输出线上模拟用的 {version, servhub, sol},不需要 --case,--out 可省(结果直接打印)

debug ask 会自动创建调试会话、发送消息、轮询等待 Agent 回复,默认最大等待 30 秒,默认轮询间隔 2000ms。--text 与 --messages 二选一:--text 发送单条消息,--url 只在 --text 模式下作为附图 URL;--messages 传入完整消息列表(JSON 或 @文件)重放多轮对话,既接受 JSON 数组,也接受 conversation records 原始 { "msg_list": [...] } 对象。--conversation 可复用已有 debug 会话继续对话;--mock 可传工具结果 mock;--expect 对本轮线上回复做断言;--data-overlay 可传 debug_data_overlay JSON 或 @文件;--overlay <dir> 直接用覆盖目录现场生成线上模拟覆盖(Sol,与 --data-overlay 互斥)。

debug reproduce 根据一条回复记录自动复现 Agent 回复:通过 recordId 获取关联会话和 Agent 配置,拉取完整会话记录并截取目标 record 之前的上下文,使用原始用户名创建新 debug 会话并发送。默认最大等待 60 秒,默认轮询间隔 2000ms。--agent 可指定另一个 Agent 复现同一段上下文(A/B 对比);--mock、--expect 和 --data-overlay(或 --overlay <dir>,见「Sol 线上模拟」)会在复现发送时透传;--replace-last / --image 换掉最后一条买家消息;--dry-run 仅输出截断后的 msg_list(含替换结果)、mock 和 overlay,不发送。

debug data snapshot 生成 debug_data_overlay v1 JSON,适合把当前 Agent 的 SOP / 商品 / 活动等数据固定成一次 debug 覆盖输入,再通过 debug ask --data-overlay @file 或 debug reproduce --data-overlay @file 复跑。--agent <id> 必填;--product-id <商品ID...> 可重复传多个商品 ID,只导出指定商品,不传则分页导出全量商品。命令输出写到 stdout,通常重定向到文件保存。

# 只导出指定商品相关 overlay
cs-cli debug data snapshot --agent <id> --product-id 586812046546 > overlay.json

# 使用 overlay 跑一次 ask
cs-cli debug ask --agent <id> --text "https://item.taobao.com/item.htm?id=586812046546 这个商品名称是啥" --data-overlay @overlay.json

Sol 逐轮回放:先用生产环境的 CLI 配置运行 replay export,按轮次顺序传入同一会话的 1 到 50 个 sol_trace_id 或回复 record_id。导出依赖存档中的轮前状态、客户资产和商品数据;缺少可执行上下文的历史存档会由服务端明确报错。导出包顶层附 export_report(sol-replay-export-report/v1),逐轮标出回放会不会停:blocked 表示严格与 lenient 都会停,warn 表示严格会停、lenient 可继续(含跳过轮);有 warn/blocked 时 export 在 stderr 打印逐轮摘要(轮号、状态、规则码),stdout 与退出码不变。授权了推荐工具却没捕获 recommend_route 的轮由导出自动补(先借同包邻轮,借不到补空路由),来源记入 export_report.recommend_route_filled,不用再手工补。replay open 只生成本地 run.json,内嵌完整 case;消息卡片、未知字段与原时间戳均原样保存。

执行 next / run 时使用当前 CLI 环境的客服 API 和登录态;服务端仅在 dev 开放执行。预先按上面的多环境步骤分别配置并登录,生产导出使用 --env prod,执行使用 --env dev。rollout(默认)沿用 dev 每轮产生的状态,适合改了商品选择逻辑后验证后续轮次;original 每轮恢复对应线上状态,适合独立对照。

# dev 与 prod 已分别配置 API、工作空间并登录
cs-cli --env prod debug replay export --record <第一轮回复ID> <第二轮回复ID> --out case.json
cs-cli debug replay open --case case.json --out run.json
cs-cli --env dev --request-timeout 180000 debug replay next --run run.json
cs-cli --env dev debug replay run --run run.json --until 2

# 保留完成的第一轮,从其 dev 状态继续新分支;--at 0 从初始上下文开始
cs-cli debug replay fork --run run.json --at 1 --out run-b.json
cs-cli --env dev debug replay run --run run-b.json

# 新逻辑会查询 B:补入包含 B 的原始商品数据,再从同一个 checkpoint 分叉
cs-cli debug replay fork --run run.json --at 1 --products products-B.json --out run-products-B.json
cs-cli --env dev debug replay next --run run-products-B.json

open / fork --products snapshot.json 把原始商品数据对象固定到 case.products,显式作为所有后续轮次的数据源;商品 ID/SKU 查询和卡片生成仍由真实 Sol 代码执行。其余消息、客户身份、前 N 轮与 checkpoint 保持原样。快照应覆盖改动后会查到的商品及所需 SKU、库存、摘要;缺范围由服务端报错,不自动补空结果。不传 --products 则使用各轮自己的录制数据,库存等时点数据不会跨轮自动合并。

只想改几件商品(改状态 / 补库存或总结 / 补活动与关联知识)时,不必重写整份快照:在 case.json 顶层加 products_patch(products-patch/v1)即可,按商品 id 合并行、整块替换 SKU / 库存 / 总结、覆盖短链,并按商品集合补 enrichment;格式见 docs/devkit/specs/2026-10-27-590-sol-工具mock.md「商品局部补丁」。sol-local 对应 shop.products_patch 与 run --products-patch。不想手改 case 时,open / fork --products-patch patch.json 把补丁写进 case.products_patch,--mocks mocks.json(tool-mock/v1)写进 case.tool_mocks;两者都先按契约校验,非法时不建运行文件。fork 只替换给出的那一项,其余沿用原运行文件。

复现第 N 轮之后的回复:只知道会话 id 时,export --conversation <id> [--until N] 按时间顺序读 AI 回复的 record 诊断、收集去重后的 sol_trace_id 再导出(人工回复没有 Sol trace,自动跳过;超过 50 轮必须 --until)。要看「第 N 轮之后买家换一种说法 / 追问一句会怎么回」,用 append 离线造一轮:

cs-cli --env prod debug replay export --conversation <conversation_id> --until 3 --out case.json
cs-cli debug replay append --case case.json --after 3 --text "那 1.8 米的有现货吗" --out case.next.json
cs-cli debug replay open --case case.next.json --out run-next.json                # 只能 rollout
cs-cli --env dev --request-timeout 180000 debug replay run --run run-next.json
  • 合成轮复制第 N 轮的 request / context(资产、识图、商品快照不变),在对话末尾接上买家文本消息(多个 --text 即连发),时钟默认第 N 轮 + 60 秒(--clock 可指定),去掉只对原轮有效的 QA 预取录制与线上结果,tool_records 清空,并标 synthetic。第 N 轮之后的原有轮次丢弃。
  • rollout 会丢掉第 N 轮线上 AI 回复、接在 dev 回复之后;第 N 轮到合成消息之间线上真实发生的人工 / 平台消息不会带上。
  • 合成轮没有工具录制:模型调了非商品工具会 422 缺录制,用 --mocks 给这些工具配 fill 规则;商品工具走商品快照。含合成轮的 case 拒绝 --mode original。

--until N 表示执行到完成 N 轮,包含第 N 轮;不传则跑完。每轮用独立 request_id 关联同步终态,并原子保存结果及 checkpoint。failed / skipped 也作为该轮结果保存;HTTP 错误或返回关联不符时保留上一个已完成 checkpoint,再次执行即可从该处恢复。export / open / fork 不覆盖已有文件。运行文件使用同目录 .lock 防止并发推进;进程异常退出后,确认没有回放进程才可删除残留锁。文件包含客户上下文,默认权限为 0600。

供 AI 执行的输出与取证:next/run 默认仅返回进度、最后一轮 response_status、回复预览、焦点商品及卡片/工具/告警数量。execution_status=completed 表示命令完成,verification_status=not_evaluated 表示尚未判断业务预期;即使本轮 Sol 是 failed/skipped,仍完整存档并在摘要中明确显示。完整 response、trace、checkpoint 保存在 saved_to 指向的 run 文件。

inspect 只读本地文件,不需要联网或登录。--turn 使用从 0 开始的索引;不传则分页读取已完成轮次摘要。视图为 summary|response|cards|tools|trace|checkpoint|request|raw;cards 读取 checkpoint 中的 tool_result 事实载荷(包含沿用的历史事实),没有记录时提供 run_record 卡片摘要;原始业务载荷可取 /response/llm_payload。tools 来自 trace 的工具执行。--path 从本轮完整结果按 JSON Pointer 取字段(覆盖 view),支持 /→~1、~→~0 转义。未执行轮次可查 request。数组默认 10 项,--offset/--limit 分页,返回 total/next_offset;超过 12,000 bytes 的视图仅给标记截断的预览,可缩小路径或 --out 完整保存所选视图/数组页,未知字段不改写。

cs-cli debug replay inspect --run run.json
cs-cli debug replay inspect --run run.json --turn 0 --view cards --limit 5
cs-cli debug replay inspect --run run.json --turn 0 --view tools
cs-cli debug replay inspect --run run.json --turn 0 --path /checkpoint/head/focus_skus
cs-cli debug replay inspect --run run.json --turn 0 --view trace --out turn-0-trace.json
cs-cli debug replay compare --baseline run.json --candidate run-b.json --out comparison.json
cs-cli debug replay compare --baseline run.json --candidate run-b.json --expect expected.json --out verified.json

compare 要求 source、mode、逐轮 trace ID 和 request 相同,允许显式更换数据。比较共同已执行前缀的状态、回复、转人工、标签、事实卡及载荷、工具有效参数/结果、焦点商品/订单/SKU/场景;忽略卡片抓取时刻与工具耗时。case_equal/data_equal 和两份运行摘要用于标明输入包及数据是否一致;完成长度不同则 comparison_status=incomplete。默认只报差异位置和数量,完整 before/after 与断言证据可用 --out 保存,或通过 inspect 按位置读取。无 --expect 一律 not_evaluated,不把“无差异”判作“正确”。

预期文件只做显式逐轮字段断言(默认相等比较),不执行代码或自动语义评分;每条可加 op:equals(默认)/ not_equals / contains / not_contains / length / startswith / in,字段缺失一律判失败:

{"schema":"sol-replay-expect/v1","assertions":[
  {"turn_index":0,"path":"/checkpoint/head/focus_product_ids","equals":["B"]},
  {"turn_index":1,"path":"/checkpoint/head/focus_product_ids","equals":["B"]}
]}

断言工具调用用 op: "called" / "not_called",不写 path(或写 /tool_calls),equals 为 {tool, input?, include_prefetch?}:tool 接受配置名或 canonical 名(faq_knowledge = fetch_qa);input 对模型给的入参做子集匹配;默认只认模型调用(取自 trace.llm_calls 输出的 tool_calls,不含 read_block);引擎自己发起的执行——预取、选品轮按 must_invoke 补发的 product_recommendation 等——不算,include_prefetch: true 时任何执行都算。debug ask / debug reproduce --expect 同样可用,线上证据取 run_record.tool_calls,input_source=prefetch 的不算模型调用;补发的执行同样标 input_source=model,按本轮告警 recommendation_forced 认出来,不算模型调用(debug replay tools 里记 forced)。

{"schema":"sol-replay-expect/v1","assertions":[
  {"turn_index":2,"op":"called","equals":{"tool":"order_query"}},
  {"turn_index":2,"op":"not_called","equals":{"tool":"faq_knowledge","input":{"query":"运费"}}}
]}

debug replay tools --run run-1.json run-2.json ... 汇总多个运行文件:每个工具的 model_calls、turns_called、call_rate(调用轮数 / 已执行轮数,同一 case 多跑几次即调用率)、executions 按数据来源(recorded 录制 / mock / overlay 覆盖知识词法检索 / snapshot 商品快照 / prefetch 预取)计数、missing_recording(缺录制)与 failed,calls 给逐轮明细(--limit 截断)。回放里预取的非商品工具也按录制记 recorded,所以引擎发起(预取、must_invoke 补发)的次数要用 executions − model_calls 估。

全部声明断言满足才是 verification_status=passed;不相等或字段不存在为 failed,所需轮次尚未执行为 incomplete。这里的通过仅覆盖声明的断言,可用于验证 A→B 以及下一轮继续 B;回复质量仍需业务标准。比较命令成功时外层 success=true;断言失败/未完成额外设置退出码 1。无预期的差异报告和断言通过退出码为 0。

缺数 HTTP/业务 422 会在 CLI error 中保留受控的 reason/retryable/missing/next_action/truncated,例如 missing=[{"kind":"catalog","ids":["B"],"fields":["rows","covered_product_ids"]}]。snapshot_data_incomplete 对应 supply_snapshot,输入损坏的 replay_invalid_input 对应 repair_case;两者均 retryable=false。AI 应按 fields 补齐原始快照再 open/fork,或修复 case,随后从保存的轮次继续;重复同一请求不会产生缺失数据。诊断只含字段名和受控实体标识,不含凭据、任意上游异常或完整工具参数;非法诊断退回固定失败信息,不更新失败轮的 checkpoint。

所有回放命令默认 JSON 的最终输出信封(包含路径等元数据)按 12,000 bytes 控制。超限时返回 truncated=true、data.artifact 与 next_action=read_artifact,完整输出转存为权限 0600 的本地临时证据文件;运行文件和显式 --out 仍保留完整数据。AI 应先读取 artifact;需长期保存时将其复制到任务目录。非法或缺失结构化诊断的 422 始终使用固定文案,不回显上游 message。

回放配置覆盖(#442):在本地改 SA、FAQ、扩展知识、customer_config、工具、商品后重跑,不写线上。

cs-cli --env prod debug replay export --record <record_id> --out case.json
cs-cli --env prod debug overlay init --case case.json --out ov/ --product <商品id>   # 只读;默认 --base current
# 编辑 ov/sa.json、ov/faq.json、ov/common_knowledge.json、ov/customer_config.json、ov/tools.json、ov/products_patch.json
cs-cli debug mock init --case case.json --out ov/tool_mocks.json        # 可选:新增工具或要替换工具返回值时
cs-cli debug overlay build --case case.json --overlay ov/ --out case.ov.json
cs-cli --env dev debug replay open --case case.ov.json --out run-ov.json && cs-cli --env dev debug replay run --run run-ov.json
cs-cli debug replay compare --baseline run.json --candidate run-ov.json --ab
  • overlay init 生成 sa.json(SA 全量)、faq.json(FAQ 当前全集)、common_knowledge.json(扩展知识当前全集)、customer_config.json(深合并补丁,初始 {})和 .base.json(基线元信息)。不写 request 及其中凭据。
  • --base current:取同一 Agent 最近一轮 Sol 回复的资产,再用 sa list、agent get 的当前值修正,差异写进 stale_fields(只核对 SA 和 flow_instruction 槽位;所选回复超过 24 小时会告警,其他配置可能已改过);找不到 Sol record 时退回事故快照,.base.json 标 fallback: "incident" 并在 stderr 告警。--base incident:取 case 第一轮(或 --turn N)的资产。
  • FAQ 条目 id 写成 <file_id>-<answer_group_id>,知识条目写成 <file_id>-<chunk_id>。
  • overlay build 只写和基线不同的 SA,定位写 id(内容哈希),不写每轮排序编号 ref;sa.json 里 ref / id 重复会报错(复制条目当新增时去掉 ref 和 id)。faq.json / common_knowledge.json 相对 init 有改动(含新增、删除)时整集写入,回放里对应的检索改为本地词法检索(报告标 lexical_approx);没改或删掉文件时不写,仍用录制结果。标准 QA 不覆盖,报告固定写 qa_assets: "baseline"。整份商品快照仍用 replay open/fork --products,改几件商品用下面的 products_patch.json。
  • 工具(Sol):overlay init 另写 tools.json——回放资产 tool_entries 去重后的工具行全量(同一 canonical 名有多行时自定义行优先),基线存进 .base.json 的 tools_baseline。可改 description、input_var_descriptions、invocation_mode(must_invoke / on_demand / on_demand_async)、usage_guidance、selection_hint 等字段,也可加一行新工具或删掉一行(或写 "delete": true)。build 按 canonical 名与基线 diff:改了的只写改动字段,删掉的写 {tool, delete: true},新增整行写入 overlay.tools,引擎同时同步请求的 tools[](授权集合)。字段从行里删掉不会清空(浅合并,要清空写空字符串);Sol 自持工具(build_apply_link、fetch_product_supplement、改备注 / 改地址等)只读 usage_guidance;usage_guidance / selection_hint 回放能验证但 tool update 写不了;这些情况 build 在 stderr 提示。
  • 新增工具在回放里没有录制,模型一调就 422 缺录制:用 debug mock init 生成 ov/tool_mocks.json 并给它加规则(fill / override),build 原样写进 case.tool_mocks;没配 mock 时 build 提示。
  • 商品(Sol):overlay init --product <id...> 按商品 id 从 case 商品快照预填 products_patch.json(products-patch/v1:目录行去掉 商品id,可改 参数 / 卖点 / 补充知识 / 标题等列;该商品全部 SKU 行;总结;库存),快照里没有的商品写空行并告警。build 对预填基线最小化:目录行只留改动列,SKU / 库存 / 总结整块比较,没改的商品不写;enrichment(按商品集合补活动 / 关联知识)与 short_links 原样保留;结果写进 case.products_patch,全没改则不写。
  • --format v1 不支持工具、商品补丁和工具 mock,三个文件存在时列进 skipped。
  • 执行端 sop-engine 早于 overlay.tools 支持时会静默忽略工具覆盖(hash 仍然通过);next / run 发现 overlay_report.applied 没有 tools 时在摘要 overlay_warnings 和 stderr 告警,这时工具改动没生效。
  • hash 与引擎同口径:去掉 hash 后键按码点排序、无空白分隔、非 ASCII 原样、UTF-8,取 sha256。
  • 每轮结果带 overlay_report(applied / missing / retrieval)。同样的 case 可直接给 sol-local run --case case.ov.json。
  • classic 店:overlay init --agent <id>,overlay build 输出 debug_data_overlay v1,交给 debug reproduce --data-overlay @file。v1 的 FAQ / 知识只带相对基线改动或新增的条目;v1 表达不了的改动(含删除条目)列在 skipped。

--data-overlay 生效检查:debug ask / debug reproduce 带 --data-overlay(或 --overlay <dir>)时,发送前按目标 Agent 的顶层引擎(读不到时 reproduce 看原 record)拦截引擎不读的非空子树,退出码 2、不发送:sop 子树只有 classic 读(Sol 店会提示改用 sol 子树或 --overlay,Luna 的 SA / FAQ / 知识覆盖走 debug replay),sol 子树只有 Sol 读。发送后逐条读回 debug_data_overlay 回报并输出 debug_data_overlay_report(applied / missing / unused / sol 的 hash、base、检索口径);applied(sop、servhub、sol)全空时退出码 3,引擎回报 sol.invalid(子树不合法,本轮按无覆盖执行)时打印原因并退出码 3。

Sol 线上模拟(#610):在本地改 Sol 店的 SA、工具、标准 QA、FAQ、扩展知识、商品、开关、customer_config、违禁词后,用线上真实服务跑一轮,不写线上配置。覆盖只随这一次 debug 请求生效。

cs-cli --env prod debug overlay init --agent <config_id> --out ov/      # 只读:拉当前 SA / FAQ / 扩展知识作基线(也可 --case 用回放基线)
# 编辑 ov/sa.json、ov/faq.json、ov/common_knowledge.json、ov/customer_config.json;可选 ov/switches.json、ov/qa_items.json、ov/forbidden_words.json、ov/tools.json、ov/products_patch.json
cs-cli --env prod debug overlay build --overlay ov/ --format online     # 可选:只看生成的 {version, servhub, sol}(加 --out 写文件)
cs-cli --env prod debug ask --agent <config_id> --text "问题" --overlay ov/
cs-cli --env prod debug reproduce <record_id> --replace-last "换个问法" --overlay ov/ [--image <url>] [--dry-run]
  • --overlay <dir> 等于先 overlay build --format online 再 --data-overlay;和 --data-overlay 互斥(同时传退出码 1)。目录相对 init 基线没有任何改动、文件格式错误时报错、不发送。
  • 输出形状:{"version":1,"servhub":{customer_config?,forbidden_words?},"sol":{version:1,base,hash,sa?,tools?,qa_items?,faq?,common_knowledge?,products_patch?,switches?}}。没有 sol 内容时整个 sol 省略。sol 不含 customer_config 与 assets_replace;sol.hash 与 --format sol 同一套规范化 JSON sha256。
  • sa / tools / products_patch 与 --format sol 同一套 diff(只发改动;SA 定位写 id)。faq / common_knowledge 是补丁:只发改动、新增的条目;基线里有而目录里没有的条目(或写了 "delete": true)发 {id, delete:true, match_*};改动条目带基线原文 match_questions(FAQ 原问法)/ match_content(知识原正文),引擎靠它在真实检索结果里定位。原文存在 .base.json 的 knowledge_baseline,旧版 init 生成的目录没有它:补丁照发但不带 match_*,skipped 里提示重新 init。
  • 可选文件,缺了就不发对应项,格式错误明确报错:
    • switches.json:{"full_product_detail":bool,"order_promise_ship_time":bool,"image_rule_transfer":bool},只允许这三个布尔开关。
    • qa_items.json:数组,条目 {ref?|id?, questions?, answer_text?, delete?};带 ref / id 的是改或删,不带的是新增(必须同时给 questions 与 answer_text)。
    • forbidden_words.json:字符串数组,整体替换线上违禁词表,进 servhub.forbidden_words。
  • init --agent 只读拉 SA / FAQ / 扩展知识基线(servhub 读口),不拉工具行也不预填商品:没有 case 快照时 tools.json / products_patch.json 不会生成,要改工具或商品就手写增量文件(工具行只写要改的字段,删除写 "delete": true;build 提示「没有工具基线,按增量原样发送」)。要拿到工具基线与商品预填,用 init --case <case.json>(回放资产快照)。
  • sol.base=incident 的覆盖在线上仍套在当前线上资产上,不是事故时刻的资产(条目对不上的会在 missing 里);ask / reproduce 发送前打印一行提示。
  • 带 overlay 或 --mock 时,输出里始终有本轮 tool_calls:{model, prefetch, forced} 三组,每项 {tool, status, source, args},stderr 同步打印 [tool-calls] model=N prefetch=N forced=N。prefetch 是引擎预取(input_source=prefetch / prefetch_mock),forced 是选品轮 must_invoke 补发(按本轮告警 recommendation_forced 认出),两者都不算模型调用,口径与 called / not_called 断言一致。统计落库晚于回复,取不到 flow_info 时 stderr 提示「tool_calls 为空不代表没调用」。
  • reproduce --replace-last <文本> 把上下文里最后一条买家消息的文本换掉,--image <url> 换 / 加图片(可同用),其余上下文不变;--dry-run 展示替换后的 msg_list 与 replaced_last,不发送。上下文里没有买家消息时报错。
  • 判读顺序:先看 debug_data_overlay_report.records[].applied(改动有没有生效)、missing(条目对不上)、unused(声明了但本轮没读到),再看 tool_calls(本轮实际调了什么)和回复。

工具 mock(Sol):debug ask --mock @mocks.json / debug reproduce --mock @mocks.json 会把工具返回值替换成声明的数据(真实工具 handler、工具录制采集与 flow 点上报都不执行),模型仍自行决定是否、何时调用;买家的真实链路不带这个字段。模型调用本身仍会产生 token 成本。回放(debug replay / sol-local)与实时共用同一份 tool-mock/v1 契约:

{
  "schema": "tool-mock/v1",
  "rules": [
    {"id": "order-signed", "tool": "order_query", "mode": "override", "call": 1,
     "input": {"order_id": "123456"},
     "response": {"status": "success", "result": [ ... ]}}
  ]
}
  • mode=override 压过回放录制;mode=fill 只补缺失(默认)。旧的 {工具名: {status, result}} 与 [{tool_name, result}] 仍可用,等价 fill。
  • call 是该工具本轮第几次调用(1-based),input 是入参子集(匹配有效输入:模型可见参数 + 被拆到网关侧通道的 query / product_ids);多条规则按声明顺序取第一条。
  • 命中与未命中都可见:结果带 tool_mock_report{applied[{tool,call,rule,mode}], unused[{rule,tool,reason}]},reason 为 tool_not_called / input_mismatch / recording_present。实时请求里规则非法时不打断本轮,按无 mock 执行并在 warnings 记 tool_mock_invalid;回放 / sol-local 的规则非法则直接判用例非法(422 / 退出 2)。
  • 从已有回放包生成可编辑骨架:cs-cli debug mock init --case case.json --out mocks.json(按轮次 / 调用序号展开,response 取自录制,改完即可用)。
  • 批量:sol-local bench run --tool-mocks mocks.json [--products-patch patch.json] --strict-mocks,整集未命中的规则会让命令非零退出。

线上回报与断言:debug ask / debug reproduce 带 --mock 时,同步响应与返回 data 都带 tool_mock_report;报告同时写进回复的 flow_infos,之后用 debug record <record_id> 也能查到(OSS 不可用时 DB slim 版仍保留该字段)。规则非法时没有报告,单独返回 tool_mock_warnings(code=tool_mock_invalid),stderr 同时打印 applied / unused / invalid 摘要。

--expect <file> 复用 sol-replay-expect/v1,对本次线上回复做单轮断言;turn_index 只支持 0,其余 op / 字段缺失判失败的规则与 debug replay compare --expect 完全一致。断言路径相对线上证据对象:

路径内容
/response/messages本次调试会话里各条助手回复文本
/response/transfer_to_human回复记录上的转人工标记(未取到时为 null)
/response/transfer_decisionSol run_record.transfer_decision(有存档时)
/tool_mock_report{applied, unused};可断言 /tool_mock_report/unused 的 length 为 0
/warnings引擎告警列表;tool_mock_invalid 也在里面
/cardsSol 本轮卡片(来自 flow_infos,没有时为 [])
{"schema":"sol-replay-expect/v1","assertions":[
  {"turn_index":0,"path":"/response/messages","op":"contains","equals":"已签收"},
  {"turn_index":0,"path":"/response/transfer_to_human","equals":false},
  {"turn_index":0,"path":"/tool_mock_report/unused","op":"length","equals":0}
]}

断言失败或 incomplete 时设置退出码 1;全通过为 0。这里只验证声明的断言,回复质量仍按业务标准判断。

cs-cli debug mock init --case case.json --out mocks.json
cs-cli --env dev debug ask --agent <id> --text "帮我查下订单 123456" --mock @mocks.json

Sol 完整 prompt 存档(debug trace 的第二种 id):Sol 引擎(路由 v4)每轮把每次 LLM 调用发给模型的原样 messages / tools 存到 OSS(30 天),debug record 返回的 sol_trace_id(st-YYYYMMDD-<uuid>)即存档 id。存档格式与各种视图都由服务端定义,CLI 只传参、写文件(设计见 docs/devkit/specs/2026-09-23-sol-trace-完整prompt回溯与AI取数.md §9.20)。只接受登录用户,且需有该存档所属 workspace 的权限。

  • 单轮:--view summary(默认)给身份 / 结局 / labels / decision / 每次调用一行。--view diagnosis 是给客服助手的更短卡片(无身份 id、无工具入参,不超过 4KB)。要原文再取 prompt(--call 选,默认第一次 main)、lean、full 或 otel。verified 是服务端哈希校验结果。
  • 按天:每天北京时间 02:30 合并前一天,当天的请用单轮(先在 Langfuse 按结局 tag 筛出轮次,再拿 sol_trace_id)。workspace 取全局 --workspace / 默认配置。不带 --out 只列各 agent 的轮数;--out <dir> 下载服务端展开好的调用文件到 <dir>/<date>/<workspace>/<agent>/calls.jsonl(一次调用一行,lean 形态,每行带轮次上下文、labels、decision)。--label(可重复,AND)按结局标签筛轮次,如 transfer、repair、llm-error、status:failed、warn:<告警码>;--node 只保留某类调用;--limit 限制轮数(跨 agent 累计)。
# 某条回复为什么这么回:record 里直接带 decision;要原文再看 prompt
cs-cli debug record <record_id>
cs-cli debug trace --record <record_id> --view prompt
cs-cli debug trace st-20260923-<uuid> --view prompt --call repair

# 批量:昨天某 agent 所有转人工轮次的主调用
cs-cli --workspace <workspace_id> debug trace --date 2026-09-23 --agent <agent_id> --out ./sol-trace --label transfer --node main

debug trace(v0.4.0 起,行为变更)不再由 CLI 直连 Langfuse REST API,改为请求 customer-servhub-api 的 GET /v1/debug/langfuse/trace/{trace_id}?env=<env>,走 CLI 标准 Bearer 鉴权,由服务端按 env 选择 Langfuse 凭据并代理拉取 Trace。Trace ID 从 debug record 返回的 trace_id 字段获取。

工作空间 (workspace)

命令说明
workspace list列出当前账号可访问的工作空间
workspace points-consumes [--page <n>] [--page-size <n>]分页查询积分账户消耗流水,固定返回 extra 调试字段
workspace points-consumes-daily [--start <YYYY-MM-DD>] [--end <YYYY-MM-DD>]按天查询积分消耗趋势
  • debug trace --langfuse-env <dev|prod>:指定 Langfuse 环境,默认跟随全局 API 环境;未传全局 --env 时默认 prod。非法值报错并以非 0 退出,不发请求。
# 默认 prod 环境
cs-cli debug trace <trace_id>

# 指定 dev 环境
cs-cli debug trace <trace_id> --langfuse-env dev

迁移(v0.4.0 BREAKING):config set --langfuse-host / --langfuse-public-key / --langfuse-secret-key 及 CLIConfig.langfuseHost / langfusePublicKey / langfuseSecretKey 已移除;环境变量 LANGFUSE_BASE_URL / LANGFUSE_PUBLIC_KEY / LANGFUSE_SECRET_KEY 在 CLI 侧不再被读取。~/.cs-cli/config.json 中相关字段可直接删除。Langfuse 连接信息(含 dev/prod 双环境凭据)现由 customer-servhub-api 服务端的 system_config 表 langfuse_config 行统一管理(不再读服务端环境变量 / 内置常量),CLI 侧无需也无法再配置。

修复记录 (repair-record)

命令说明
repair-record list [--issue <工单ID>] [--agent <AgentID>] [--workspace <工作空间ID>] [--page N] [--page-size N]列出修复记录
repair-record create --issue <工单ID> --agent <AgentID> --action <修复动作> [--agent-name <名称>] [--type <类型>] [--status <状态>] [--duration <毫秒>] [--result <JSON>] [--workspace <工作空间ID>]创建修复记录
repair-record update <record_id> --data <json|@file>更新修复记录

--status 可选值:pending、success、failed、partial。

repair-record update 的 --data 支持的字段:repair_action、repair_result(JSON 对象)、repair_type、repair_status、duration_ms。

repair_result 结构

--result 或 --data 中的 repair_result 字段应为结构化 JSON,用于记录 AI 修复的完整推理过程,支持未来 AI 自我进化。

字段类型说明
failure_typestring问题分类: wrong_answer / missing_answer / hallucination / wrong_routing / slow_response / other
root_componentstring归因组件: sa_policy / faq / product_knowledge / customer_config / prompt / multiple / unknown
inputstring触发问题的用户输入
expectedstring期望的正确回复
actualstring实际的错误回复
diagnosis_reasoningstringAI 的诊断推理过程:排查了什么、怎么定位根因、排除了哪些可能性(最高价值字段)
diagnosis_confidencestring诊断置信度: high / medium / low
hypotheses_consideredarray考虑过的假设列表,每项含 hypothesis、evidence_for、evidence_against、verdict
fix_strategystring修复策略: create_sa / update_sa / delete_sa / update_faq / add_faq / update_product / update_config / multi_step
fix_reasoningstringAI 的修复决策推理:为什么选这个方案、为什么不选其他方案、预期风险和收益
alternatives_rejectedarray被否决的方案列表,每项含 approach、reason
changesarray变更快照,每项含 component、action、target_id、before、after
target_fixedboolean目标问题是否修复
regression_summarystring回归验证结果摘要
retry_historyarray重试记录,每项含 round、what_failed、lesson、adjustment
duration_msnumber修复总耗时(毫秒)
repair_statusstring最终状态: success / failed / partial
resolved_datestring修复完成时间(ISO 格式)

加粗的两个字段(diagnosis_reasoning 和 fix_reasoning)是对 AI 自我进化价值最大的:没有它们只能做模式匹配,有了它们才能做推理。

运维操作记录 (ops-record)

本组全部命令要求内部普通权限(DEVELOPER、ADMIN 或 SYSTEM_ADMIN)。

命令说明
ops-record list [--workspace <工作空间ID>] [--agent <AgentID>] [--page N] [--page-size N]列出运维操作记录
ops-record get <record_id>获取运维操作记录详情
ops-record create --workspace <工作空间ID> --agent <AgentID> [--workspace-name <名称>] [--agent-name <名称>] [--path <文件路径>] [--remark <备注>]创建运维操作记录
ops-record update <record_id> --data <json|@file>更新运维操作记录
ops-record delete <record_id>删除运维操作记录(软删除)

ops-record update 的 --data 支持的字段:workspace_name、agent_name、path、remark。

创建记录时 operator_id 和 operator_name 自动从当前登录用户获取,无需手动指定。

商品变更事件消费 (change-consumer)

客服运维助手订阅并消费商品变更事件(pull 模式)。后端走 /v1/change-consumers/*,CLI 标准 Bearer 鉴权。默认 consumer_key=ops_agent_assistant。

标准工作流:sub create 创建订阅 → delivery list 轮询待消费项 → delivery claim 认领 → 处理 → delivery complete 回写。

命令说明
change-consumer sub create --workspace-id <id> [--agent-config <id>] [--events <list>] [--resource-type product] [--consumer-key <key>] [--consumer-name <名称>] [--disabled] [--data <json|@file>]创建订阅(最简只需 --workspace-id;--agent-config 缺省表示该工作空间全部商品事件)
change-consumer sub list [--workspace-id <id>] [--agent-config <id>] [--consumer-key <key>] [--enabled <true|false>] [--page N] [--page-size N]查询订阅列表
change-consumer sub update <subscription_id> --data <json|@file>更新订阅(enabled / events / filters / consumer_name)
change-consumer delivery list [--workspace-id <id>] [--agent-config <id>] [--consumer-key <key>] [--statuses <list>] [--cursor-created-at <iso>] [--cursor-delivery-id <id>] [--limit N]查询待消费项(不传 --statuses 时后端默认返回 pending/claimed/failed;--cursor-* 做增量拉取)
change-consumer delivery claim <delivery_id> --claimed-by <id> [--consumer-key <key>] [--lease-seconds N]认领待消费项(已被其他实例认领且未过期时认领失败)
change-consumer delivery complete <delivery_id> --status <completed|ignored|failed> [--result-action <action>] [--result-note <note>] [--last-error <error>] [--consumer-key <key>] [--data <json|@file>]回写处理结果
  • sub create 默认 --events product.updated,product.deleted、--resource-type product;--disabled 创建为停用态(默认启用)。
  • delivery complete 的 --status 仅接受 completed / ignored / failed,其它值直接报错退出;不要长时间停留在 claimed 不回写。
  • --result-action 建议值:supplemental_knowledge / product_association / rerun_product_study / refresh_recommended_qa / ignore_change / manual_follow_up。
  • 各子命令 --data <json|@file> 为高级用法,提供时覆盖对应结构化选项。
# 1. 创建订阅(该工作空间全部商品 更新/删除 事件)
cs-cli change-consumer sub create --workspace-id <ws> --events product.updated,product.deleted

# 2. 轮询待消费项
cs-cli change-consumer delivery list --workspace-id <ws> --statuses pending

# 3. 认领
cs-cli change-consumer delivery claim <delivery_id> --claimed-by ops-assistant-1

# 4. 处理后回写
cs-cli change-consumer delivery complete <delivery_id> --status completed \
  --result-action supplemental_knowledge --result-note "已补充商品知识"

运营监控 (monitor)

直接调用 /v1/operation 底层接口,返回原始数据,由调用方决定如何聚合统计。fields、tickets list/delete 要求内部普通权限;其余六个数据查询命令要求 SYSTEM_ADMIN。

字段说明

命令说明
monitor fields [resource]查看监控资源的指标字段说明;本地静态输出,仍要求内部普通权限

Agent 生命周期

命令说明
monitor agents [--page N] [--page-size N]Agent 生命周期列表(含构建进度、会话统计等原始数据)

监控工单

命令说明
monitor tickets list [--agent <id>] [--status <状态>] [--severity <级别>]列出监控工单
monitor tickets delete <ticket_id>删除监控工单

监控快照

命令说明
monitor snapshots hourly --agent <id> --start <ISO> --end <ISO>查询小时快照
monitor snapshots daily --agent <id> --start <日期> --end <日期>查询日快照
monitor snapshots daily-range --agent <id> --start <日期> --end <日期>查询日快照范围(含趋势)

Agent 运营统计

命令说明
monitor statistics [--start <ISO> --end <ISO>] [--page N] [--page-size N]Agent 运营统计(会话量、转人工率、响应时间等)

运营工作空间

命令说明
monitor workspaces [--has-agent] [--page N] [--page-size N]运营工作空间列表(含合同、客户信息)

模型 Token 成本(token-usage,需超级管理员(SYSTEM_ADMIN))

成本以 customer-observability-api 账本为准;cost_cny 是刊例价,payable_cost_cny / discount_rate 是实付。

命令说明
token-usage summary --start <时间> --end <时间> [--workspace-id <id>] [--agent <id>] [--engine sol|luna|classic] [--include-test]时间窗内的成本汇总

数据看板 (dashboard)

转人工率 / 接待量 / AI 回复量等运营指标。数据 T+1(--end 不能晚于昨天,否则后端返回 400);--start / --end 为闭区间。渠道枚举:qianniu(千牛/淘宝)/ jingdong / pinduoduo / douyin。CLI 只产结构化数据,运营报告由上层(如 LLM)按场景加工。

命令说明
dashboard summary [--config-id <id>] [--start <d>] [--end <d>] [--channel <c>]全局或单店 KPI 汇总 + 环比(不传 --config-id 为全店铺聚合)
dashboard trend [--config-id <id>] [--start <d>] [--end <d>] [--granularity day/week/month] [--channel <c>]趋势(每日/周/月接待客户数、转人工数、转人工率),--granularity 默认 day
dashboard shops [--start <d>] [--end <d>] [--channel <c>]全部店铺统计列表(默认按转人工客户数降序),用于横向对比
dashboard export --start <d> --end <d> [--config-id <id> ...] [--channel <c>] [--out <path>]店铺维度每日明细。默认解析为 JSON 行;--out 落盘原始 CSV

版本与发布记录

@bty/customer-service-cli 共发布 76 个版本,首次发布于 2026/03/22;过去 12 个月发布了 76 个版本。

版本发布日期距今
0.8.5latest2026/11/012 天前
0.8.42026/10/313 天前
0.8.32026/10/304 天前
0.8.22026/10/295 天前
0.8.12026/10/286 天前
0.8.02026/10/2410 天前

关于 @bty/customer-service-cli 的常见问题

@bty/customer-service-cli 是什么?

AI客户服务CLI -座席友好

如何安装 @bty/customer-service-cli?

在项目目录运行 npm install @bty/customer-service-cli,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 cs-cli,可以用 npx cs-cli 直接运行。

@bty/customer-service-cli 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/bty__customer-service-cli 是否存在。

@bty/customer-service-cli 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@bty/customer-service-cli 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@bty/customer-service-cli 可以商用吗?

@bty/customer-service-cli 使用 未声明 许可。package.json 没有声明许可证。没有许可证的代码默认保留全部权利,商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括,不构成法律意见,请以许可原文为准。

@bty/customer-service-cli 还在维护吗?

最新版本 0.8.5 发布于 2026/11/01(2 天前);至今共发布 76 个版本,其中过去 12 个月发布了 76 个;首次发布于 2026/03/22。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。