Skip to main content

19 posts tagged with "AI"

View All Tags

飞书 Playwright + Doc Parser 文档下载

· 3 min read
Bowen Zhang
本文作者

必需前置条件

本技能是 Playwright MCP + Doc Parser MCP 的组合实现,二者缺一不可:

  • Playwright MCP:复用已登录的飞书浏览器会话,读取 Wiki 目录树、节点层级和 Wiki token。
  • Doc Parser MCP:解析飞书文档正文、下载 Markdown 及图片。批量下载阶段必须调用其 submit_and_download_with_images 能力。

使用前必须先安装并配置 Doc Parser MCP。安装参考: https://li.feishu.cn/wiki/HoSbwwOt7iLGlZkPGKQcsTNin0f

如果 Doc Parser MCP 未安装、未配置或不可用,应先停止下载并提示用户完成安装;不要改用 lark-cli、飞书 OpenAPI、手工复制或其他解析方式替代。

适用范围

使用本技能把飞书 Wiki 下的全部或指定文档下载到本地,并保留知识库原有层级。目录读取必须通过 Playwright MCP 完成,文档解析和下载必须通过 Doc Parser MCP 完成。

工作流程

  1. 复用 Playwright MCP 中已经登录飞书的浏览器会话。不要随意新建未登录浏览器;如果页面跳到登录页,先重新连接已登录会话。
  2. 打开用户提供的 Wiki 地址,等待左侧目录树完成渲染。只处理用户指定 Wiki 子树,不要把其他空间或搜索结果混入任务。
  3. 从 DOM 收集目录节点的标题、层级位置和 Wiki token。优先使用以下选择器:
    • 节点:div.workspace-tree-view-node
    • 标题:.workspace-tree-view-node-content
    • 层级:data-node-pos
    • 标识:data-node-uid 中的 wikiToken
  4. 只展开目标节点的后代。记录每个节点的原始 pos、标题、token 和父子关系;不要只依赖当前可见文本,因为折叠节点可能尚未出现在 DOM 中。
  5. 根据 data-node-pos 生成本地目录。常见位置如 2,0,0,0 应从索引 3 开始映射,前面的 Wiki 根节点索引不应创建成本地目录。每篇文档使用独立目录,Markdown 和图片保存在该目录内。
  6. 先安全删除本次目标输出目录,再开始全量刷新。确认解析后的绝对路径位于用户指定根目录内,禁止删除其他路径。
  7. 对每个节点调用 Doc Parser 的 submit_and_download_with_images
    • resourceUrihttps://<飞书域名>/wiki/<wikiToken>
    • outputDir:该节点对应的本地目录
    • pollInterval:通常为 5 秒
    • timeout:按文档大小设置,至少覆盖正常解析和图片下载时间
  8. Doc Parser 通常会在 outputDir 下创建 docs-* 临时目录。任务成功后,将临时目录中的最终内容移动到节点目录的预期位置,并删除临时目录;失败时保留错误信息,不把临时目录当作最终结果。
  9. 所有节点完成后执行结果校验,汇总成功、失败、重复名称、缺少 Markdown、图片数量和残留临时目录。

目录映射规则

  • 使用 pos 的路径索引建立父子关系,而不是按遍历顺序猜测目录。
  • 同一父节点下出现同名文档时,按稳定顺序命名为 标题标题 (2)标题 (3);后缀只作用于真正同名的兄弟节点。
  • 不能因为递归遍历了很多子节点,就把父目录错误命名为 标题 (10)
  • 不能把不同节点合并到同一个目录,也不能静默覆盖同名文档。
  • Windows 文件夹名中的非法字符统一替换为 _,同时保留原始标题用于日志和校验。
  • 每个文档目录至少应包含一个 Markdown 文件;图片应保留为相对路径,避免 Markdown 中出现失效的临时绝对路径。

Playwright 读取示例

const nodes = await page.locator('div.workspace-tree-view-node').evaluateAll(items =>
items.map(node => ({
pos: node.dataset.nodePos || '',
uid: node.dataset.nodeUid || '',
title: node.querySelector('.workspace-tree-view-node-content')?.textContent.trim() || ''
}))
);

const tokenFromUid = uid => uid.match(/wikiToken=([^&]+)/)?.[1] || '';

实际执行时应先确认目录已展开、节点数量稳定,再保存 pos、标题和 token。若 token 不在 data-node-uid,点击对应文档后从当前地址提取 /wiki/<token>,仍然只通过 Playwright 完成。

失败处理

  • 登录失效:停止提交下载任务,重新连接已登录 Playwright 会话后再继续。
  • 单篇文档失败:记录 pos、标题、token、目标目录和错误,继续处理其他节点,最后集中重试失败项。
  • 目录数量异常:重新展开目标子树并重新采集,不要依据不完整列表执行全量删除或下载。
  • 出现重复目录或覆盖迹象:停止后续写入,检查同名兄弟的稳定后缀和 pos 映射,再从干净目标目录重跑。
  • Doc Parser 超时:提高该节点的 timeout 后重试;不要把未完成的 docs-* 目录标记为成功。

完成校验

至少检查以下项目:

  • Playwright 采集的文档节点数与成功下载的 Markdown 数量一致,或明确列出失败节点。
  • 每个预期节点都有正确的本地目录,目录层级与 pos 映射一致。
  • 同名文档均有稳定后缀,且没有误覆盖、误合并或父目录异常后缀。
  • Markdown 中的图片引用有效,统计图片总数并抽查相对路径。
  • 目标根目录下没有残留 docs-*、日志、临时下载目录或空的错误目录。

最终报告简要列出输出根目录、节点总数、成功/失败数、Markdown 数、图片数和需要人工处理的节点。

Vanna Fuxi SQL(伏羲数据问答)

· 2 min read
Bowen Zhang
本文作者

基于已部署的 Vanna AI SQL 问答服务(伏羲环境)接口:

  • POST https://vanna-ai-sql-api-ontest.inner.chj.cloud/ask

当用户询问“伏羲上的数据”时(例如“我想查伏羲上的张博文准驾等级”“帮我查伏羲里某人的驾驶证信息”),使用本 skill 调用该接口并整理结果后回复用户。

触发场景(给模型看的)

当满足以下任意条件时,优先考虑使用本 skill:

  • 用户明确提到“伏羲”“伏羲上的数据”“伏羲系统”“Vanna SQL 问答”等。
  • 用户用自然语言问与驾驶/准驾等级/人员车辆信息等相关的问题,并你知道这些数据在伏羲库里。

示例触发语句:

  • “我想查伏羲上的张博文准驾等级”
  • “帮我看看伏羲里某个驾驶人的违规记录”
  • “用 Vanna 那套 SQL 问答帮我看下这个人近期的驾驶情况”

调用方式

使用 exec 工具调用 Node.js 脚本:

python {baseDir}/scripts/ask.py "<自然语言问题>"

其中:

  • <自然语言问题> 直接使用用户的问题文本,例如:
    我想查伏羲上的张博文准驾等级

脚本会:

  1. https://vanna-ai-sql-api-ontest.inner.chj.cloud/ask 发送 POST 请求。

  2. 请求体 JSON 结构遵循后端 QuestionRequest 模型:

    {
    "question": "我想查伏羲上的张博文准驾等级",
    "visualize": false,
    "allow_llm_to_see_data": true,
    "model": null
    }
  3. 得到形如 QuestionResponse 的 JSON:

    • success: 是否成功
    • question: 实际问句
    • sql: 生成并执行的 SQL
    • data: 查询结果(列表,元素为对象)
    • explanation: 对 SQL / 结果的解释(如果有)
    • 其他辅助字段(visualization, data_markdown, error, execution_time 等)
  4. 将完整 JSON 输出到标准输出。

对话流程建议

  1. 检查用户问题是否属于伏羲数据范围:

    • 如果只是一般业务咨询,不需要查库,则按普通对话处理。
    • 如果需要真实数据(例如“准驾等级”“近半年违章次数”等),用本 skill。
  2. 调用脚本:

    python {baseDir}/scripts/ask.py "<用户原始问题>"
  3. 读取脚本输出的 JSON,按以下规则总结回答给用户(用中文):

    • 如果 success == false 或有 error 字段:
      • 告知用户“伏羲查询失败”,简要给出错误信息(避免泄露敏感内部栈信息)。
    • 如果 success == truedata 有内容:
      • 简要说明:你已经调用伏羲 SQL 问答接口并成功返回结果。
      • 若有 sql 字段且非空,请把生成的 SQL 展示给用户(可用代码块包裹)。
      • 结合 datasql/explanation,提炼用户最关心的信息:
        • 对于“准驾等级”类问题,只强调相关字段(例如某人的准驾等级、证件状态等)。
        • 如有多行数据,说明筛选条件(例如按最新记录、或者全部罗列)。
    • 尽量用自然语言解释,必要时可附上一小段表格或项目符号列表。
  4. 如有歧义(例如伏羲数据里有多个同名“张博文”):

    • 向用户说明存在同名记录。
    • 给出区分字段(如身份证号尾号、所属部门等),请用户补充信息后再调用一次接口。

注意事项

  • 本 skill 假定远端接口已经在伏羲环境正确配置并可访问。
  • 如遇网络故障 / 5xx 等错误,先向用户说明是“后端服务不可用或网络异常”,再视情况建议稍后重试。
  • 不要在对话中泄露完整内部 URL 日志,只说明是调用了“伏羲 SQL 问答接口”。

DeepSeek Harness 必装的 10 个插件

· 8 min read
Bowen Zhang
本文作者

截至2026年8月15日,Oh-My-DSH目录已收录精选插件 1117个,监测生态仓库 1521个,累计获得Star 301295 颗。

今天这篇文章,我就从众多插件里,挑出10个最值得装的,希望对你会有所帮助。

一、先搞懂Harness的插件怎么装

在聊具体插件之前,我们先花2分钟搞清楚怎么装插件。

Harness的插件安装只有一条命令:

dsh plugin --profile web add "github:owner/repo#ref"

比如装一个视觉插件:

dsh plugin --profile web add "github:liustack/modlens#main"

这条命令会从GitHub拉取插件代码,通过dsh.bundle声明自动启用它。安装完成后,重启dsh web服务并刷新页面,插件就生效了。

一个重要的坑:启动Web UI时必须加上--patch参数,否则很多插件和技能不会生效。完整命令:

npx @deepseek-ai/dsh web --patch

另外,官方建议插件仓库打上#dsh标签,这样社区目录才能自动收录。想找更多插件,可以直接在GitHub搜索dsh-plugin话题。

下面开始正式推荐。

二、插件1:ModLens

它给纯文本模型装上一双眼睛。

仓库:liustack/modlens | Star:905+

DeepSeek本身是纯文本模型,最大的短板就是看不了图。你贴一张报错截图、丢一个UI设计稿,它只能对着文字干瞪眼。

ModLens的README第一句就是"Give a text-only model sight"。

装上之后,图片可以直接粘贴进聊天框,它通过一个原生的modlens_read_image工具,把图转成结构化文本证据,再喂给DeepSeek作答。

核心思路是:DeepSeek还是那个纯文本模型,但凭空多了双眼睛。视觉模型把图像内容"翻译"成文字,纯文本模型再接着处理——就像请了个会看图的朋友在旁边给你念。

安装命令(注意必须锁版本号,别用@latest):

dsh plugin --profile web add "@liustack/modlens@3.17.2"

场景:贴报错截图让AI分析、丢UI设计稿让AI还原、识别流程图中的文字信息。

三、插件2:dsh-web-ui

它从毛坯到精装,一站式全家桶。

仓库:zhu1090093659/dsh-web-ui | Star:1013+

如果只让装一个插件,我会选dsh-web-ui。

默认的dsh web界面就是个纯聊天框,用久了你会觉得它"太素了"。

装上这个插件集之后直接变精装房——任务看板、Git图谱、右侧面板、移动端UI、宠物、实时Token统计、皮肤中心,一套全给齐

最让我惊喜的是任务看板(dsh-task-board):五列看板——待规划/待办/进行中/已完成/已失败。卡片能直接交给真实DSH会话去执行,跑完自动更新状态,还支持cron定时任务。

安装命令

dsh plugin --profile web add "github:zhu1090093659/dsh-web-ui#main"

装完之后,左侧边栏多了任务看板、Git图谱、Token统计等面板,整个界面从"毛坯"变成了"精装"。

场景:所有场景。这是Harness的"基础设施级"插件,装了不亏。

四、插件3:dsh-better-sidebar

它把WebUI变成Codex风格的工作台。

仓库:omdsh-dev/DSH-better-sidebar | Star:684+

如果你习惯用Codex或Claude Code的界面风格,dsh-better-sidebar就是给你准备的。

这个插件给Harness的WebUI加了一个侧边栏工作台,支持文件查看/编辑、终端、Git、子代理,还有可扩展的Tab。

装完之后,整个界面跟Codex几乎一模一样。

安装命令

dsh plugin --profile web add "github:omdsh-dev/DSH-better-sidebar#main"

dsh-better-sidebar vs dsh-web-ui:前者更像一个完整的工作台布局,侧重文件树、终端、Git这些开发工具;后者更像一个功能集合包,侧重任务看板、皮肤、宠物这些增强功能。

两个可以一起装,互不冲突——better-sidebar管布局,web-ui管功能。

场景:习惯IDE风格界面的开发者,想在浏览器里获得类似Codex的体验。

五、插件4:dsh-TUI

它把Harness搬回终端。

仓库:ccch1mneyyy/dsh-TUI | Star:793+

这是dsh中最火的插件之一。

官方没有推出任何CLI或TUI形式,所以TUI只能通过插件来扩展。

装上之后执行:

dsh --profile cc-tui

就可以进入DeepSeek Harness的全屏终端界面了。常用的命令基本都涵盖了。

dsh-TUI vs dsh-better-sidebar:better-sidebar是给WebUI补一个工作台,dsh-TUI则是直接把整个交互搬回终端

平时习惯在浏览器里看文件树、预览Markdown,就装better-sidebar;已经在日常离不开Claude Code、Codex CLI这种风格的,就装dsh-TUI。

安装命令

dsh plugin --profile web add "github:ccch1mneyyy/dsh-TUI#main"

场景:终端爱好者、习惯CLI工作流的开发者、想在远程服务器上跑Harness的场景。

六、插件5:deepseek-harness-desktop

它把Harness变成桌面App。

仓库:anywhere-labs/deepseek-harness-desktop | Star:4745+

这是最近最火的Harness插件之一。

官方没有提供桌面端,社区把这个缺口补上了。

核心功能:把DeepSeek Harness打包成Electron桌面应用,自动启动和管理本地Harness服务,集成系统托盘+桌面窗口。

最爽的一点是:无需装Node.js、无需敲命令。双击图标就能跑起来。

注意:这是社区项目,不是DeepSeek官方桌面端。目前主要支持macOS和Windows。插件市场、手机远程这些能力还在后续规划里。

安装方式:直接去GitHub Releases下载对应平台的安装包,双击安装即可。

场景:不想装Node.js、不想敲命令的开发者,或者想在系统托盘里随时启动Harness的用户。

七、插件6:dsh-at-file

它让引用文件,像Codex一样丝滑。

仓库:omdsh-dev/dsh-at-file

这是我在Codex中见过的功能——通过@的方式引用文件。

装上之后,在对话输入框中输入@,会自动弹出工作区文件列表供你选择,选中的文件内容会自动附加到提示词中。

不用再手动复制粘贴文件内容了。

安装命令

dsh plugin --profile web add "github:omdsh-dev/dsh-at-file#main"

场景:需要频繁引用项目文件进行对话的场景。

装了之后,Harness在文件引用这个体验上就追平了Codex。

八、插件7:dsh-agent-teams

它能让多智能体团队协作。

仓库:NanmiCoder/dsh-agent-teams

安装这个插件后,任何会话只需一句自然语言(例如"用AgentTeams调研一下XX"),即可驱动一个多智能体团队协作完成目标,并在Web GUI右上角实时看到团队活动面板。

工作流程:创建团队(队长=当前会话Agent)→拉成员(可续聊子代理)→拆任务并声明依赖→成员间直接收发消息(邮箱直达+唤醒,无队长中转)。

安装命令

dsh plugin --profile web add "github:dsh-external/dsh-agent-teams#main"

注意:本仓库不公开,github:安装依赖本机git对dsh-external/dsh-agent-teams的读取权限。

场景:需要多Agent协作的复杂任务,比如市场调研、技术选型分析、多维度报告生成。

九、插件8:dsh-plan-execute

它能让双模型路由,规划和执行分离。

仓库:dsh-external/dsh-plan-execute

这个插件的思路非常聪明:规划用推理模型,执行用经济模型

复杂任务先让推理模型做规划和拆解,生成的子任务再交给经济模型去执行。

规划阶段的思考质量高,执行阶段的成本低——脑子和手脚分开用

安装命令

dsh plugin --profile web add "github:dsh-external/dsh-plan-execute#main"

装完之后,Web设置页会多出"规划/执行模型"的配置行。

场景:复杂任务需要高质量规划,但不想让执行过程烧太多Token。

这是"降本增效"的典型插件。

十、插件9:dsh-context-doctor

它让你看清模型的"上下文账单"。

仓库:Zhenyu98/dsh-context-doctor

很多人不知道,大模型每次请求背着多少上下文——系统提示词、技能目录、工具schema全部累加在一起,每一轮都在烧Token。

dsh-context-doctor让你看清这笔账单。它逐项量化指令链/技能目录/工具schema的Token成本,自动检测重复与冲突,给出可执行裁剪建议。

Web端提供圆环面板可视化展示,同时提供context_audit工具供Agent调用。全程只读,不影响任何配置。

安装命令

dsh plugin --profile web add "github:Zhenyu98/dsh-context-doctor#main"

场景:Token消耗异常的排查、Agent上下文优化、成本敏感型项目的精细化管理。

十一、插件10:dsh-reverse-skill

它里面包含85个安全研究技能包。

仓库:dhicoc/dsh-reverse-skill

一个包含了85个SKILL.md的技能路由包,覆盖逆向工程、授权渗透测试与安全研究等领域。

如果你在做安全相关的工作,这个插件能让你快速获得一整套方法论和工具链。

安装命令

dsh plugin --profile web add "github:dhicoc/dsh-reverse-skill#main"

场景:安全研究、代码审计、逆向工程、渗透测试。

十二、优缺点

优点

  1. 极致可定制:从毛坯到精装,全部自己决定。不像其他工具那样"给你什么用什么"。
  2. 生态爆炸式增长:1117个插件,1521个生态仓库,301295颗Star。你要的功能大概率已经有了。
  3. 安装极其简单:一条dsh plugin --profile web add命令搞定一切。不需要手动下载、解压、配置。
  4. 开源协议友好:MIT协议,可自由使用、修改、商用。

缺点

  1. 版本波动大:目前还是developer preview,插件迭代很快,装之前记得看版本。
  2. 部分插件需要额外配置:比如ModLens需要锁版本号,dsh-agent-teams需要Git权限。
  3. 启动时记得加--patch:否则技能和部分插件不生效。

选装建议

用户类型推荐插件组合
只想用Harness干活dsh-web-ui + dsh-at-file
想要Codex风格界面dsh-better-sidebar + dsh-at-file
纯终端爱好者dsh-TUI
不想装Node.jsdeepseek-harness-desktop
需要看图加装ModLens
复杂任务/多Agent加装dsh-agent-teams和dsh-plan-execute
成本敏感加装dsh-context-doctor

十三、写在最后

回到最初的问题:DeepSeek Harness必装的10个插件是什么?

我给它们分了三个层次:

第一层(核心体验层):dsh-web-ui和dsh-better-sidebar。这两个是Harness的"精装修",装了之后界面体验直接从"毛坯"变"精装"。

第二层(交互方式层):dsh-TUI(终端)、deepseek-harness-desktop(桌面App)、dsh-at-file(@引用文件)。这三个决定了你用什么方式跟Harness交互。

第三层(能力扩展层):ModLens(看图)、dsh-agent-teams(多Agent)、dsh-plan-execute(双模型)、dsh-context-doctor(上下文审计)、dsh-reverse-skill(安全技能)。这些按需加载,需要什么能力就装什么插件。

DeepSeek给Harness的口号是"一切皆插件"。

从这一千多个插件来看,这真的不是口号——模型、工具、技能、会话、沙箱、存储、循环、调度、UI,全都可以拆下来换掉

我的建议是:先装dsh-web-ui和dsh-at-file这两个最基础的,把Harness从"毛坯"变成"能住"。然后根据你的使用习惯,选一个交互方式(TUI或桌面App)。最后遇到具体需求的时候(比如要看图、要多Agent协作),再去GitHub搜索dsh-plugin话题找对应的插件装上。

一千多个插件,总有一款适合你。

开源地址

DeepSeek Harness 接入 EPT 模型指南

· 3 min read
Bowen Zhang
本文作者

🛠️ 工具分享 | 2026-09-03

使用方式:把这篇文档丢给你电脑的 Agent(Codex、Claude 或其他),让 AI 帮你配置。

推荐 Skill

在 AI 市场安装 ept-dsh Skill:

https://ai-market.chehejia.com/?page=skills&skill=vfmxzgyvvqvtm5mmvf4j&creatorUid=18211132604_64538&rankType=hot&pageSize=20

⚠️ 注意:这个 Skill 不是接入融合云网关,而是调用你自己的 EPT LLM API(EPT Codex Responses API / EPT Claude Anthropic API)。每次对话都从你自己的 EPT 额度中扣除,占用的是个人 EPT 用量,与融合云 Token 额度无关。想用公司融合云额度,请参考《DeepSeek Harness 接入融合云模型指南》。

效果

  • 在 DSH 中使用 EPT 模型(如 baidu-deepseek-v4-flash)
  • 一键启动 / 停止 / 查看 DSH Web(端口 3080)
  • 一键启动 / 停止 / 测试 EPT Claude 本地代理(127.0.0.1:8787)
  • 一键把 EPT Codex Key 刷新进 DSH 凭据

前置条件

  • 已安装 DeepSeek Harness,~/.dsh 目录存在
  • 已登录 EPT,~/.config/ept/auth_session.json 存在且含 portal_token
  • 电脑已安装 Codex 或 Claude 客户端,可安装 Skill

第一步:安装 Skill

打开上面的 AI 市场链接安装 ept-dsh。安装后直接对你的 Agent 说「使用 ept-dsh 启动 DSH」即可。

第二步:配置 settings.yaml

编辑 ~/.dsh/settings.yaml,在末尾追加 provider 配置。

EPT Claude(需要本机代理):

llm-pi-ai:
providers:
ept-claude:
displayName: EPT Claude (Anthropic)
apiKeyEnv: EPT_CLAUDE_AUTH_TOKEN
api: anthropic-messages
baseURL: http://127.0.0.1:8787
models:
- id: baidu-deepseek-v4-flash
name: baidu-deepseek-v4-flash

EPT Codex(直连,无需代理):

llm-pi-ai:
providers:
ept-copilot:
displayName: EPT Codex
apiKeyEnv: EPT_CODEX_API_KEY
api: openai-responses
baseURL: https://portal-k8s-prod.ep.chehejia.com/api/copilot/codex/v1
models:
- id: baidu-deepseek-v4-flash
name: baidu-deepseek-v4-flash

模型 id 以 EPT 实际提供的为准;/models 接口 404 不代表 provider 不可用,直接用已知模型 id 即可。

第三步:启动 EPT Claude 代理(仅 ept-claude 需要)

EPT Claude 要求 Authorization: Bearer,而 Anthropic SDK 默认发 x-api-key,所以 Skill 内置了本机代理做转换。把 <skill-root> 换成 Skill 实际安装路径(如 ~/.agents/skills/ept-dsh):

python "<skill-root>\scripts\start_ept_claude_proxy.py"
python "<skill-root>\scripts\test_ept_claude_proxy.py"

代理只监听 127.0.0.1:8787;每次请求实时读取 EPT 登录态,登录态刷新后无需重启代理。

第四步:填入 / 刷新凭据

  • EPT Claude~/.dsh/.credentials.yaml 中添加 EPT_CLAUDE_AUTH_TOKEN。代理会忽略这个值,改用 EPT 当前 portal_token,所以填非空占位符即可。
  • EPT Codex:EPT 登录态刷新后,在同一 PowerShell 会话确认 EPT_CODEX_API_KEY 环境变量已存在,然后执行:
python "<skill-root>\scripts\refresh_ept_key.py"

该脚本只更新 refs.EPT_CODEX_API_KEY,保留其他凭据,并自动生成 .bak-时间戳 备份。更新后重启 DSH Web。

第五步:启动 DSH

# npx 方式(推荐)
python "<skill-root>\scripts\start_dsh.py" --npx

# 源码方式
python "<skill-root>\scripts\start_dsh.py" --source --source-path "<dsh源码目录>"

# 查看 / 停止
python "<skill-root>\scripts\start_dsh.py" --status
python "<skill-root>\scripts\start_dsh.py" --stop

必须使用 DSH 输出的完整 ?token=... 地址,不能只打开裸地址;同一时间只启动一个 3080 实例。

验证

python "<skill-root>\scripts\start_ept_claude_proxy.py" --status
python "<skill-root>\scripts\test_ept_claude_proxy.py"
python "<skill-root>\scripts\start_dsh.py" --status

代理测试通过会输出 EPT Claude proxy 通过:HTTP 200

关键参数说明

参数说明
baseURLhttp://127.0.0.1:8787EPT Claude 本地代理地址
apianthropic-messages / openai-responses分别对应 Anthropic / OpenAI 兼容协议
代理端口8787仅监听 127.0.0.1
DSH Web 端口3080同一时间单实例

回滚

# 恢复备份(refresh 脚本自动生成)
Copy-Item "$env:USERPROFILE\.dsh\.credentials.yaml.bak-时间戳" "$env:USERPROFILE\.dsh\.credentials.yaml" -Force

删除 settings.yaml 中的 ept-claude / ept-copilot provider 节即可回到原状。

常见问题

Q: 看不到 EPT 模型? 检查 settings.yaml 缩进、凭据 ref 是否匹配、代理是否已启动。

Q: Claude 401 / 403? 先运行 test_ept_claude_proxy.py;失败则重新执行 EPT 登录或 ept claude,不要改 DSH 源码。

Q: 代理或 DSH 端口冲突?--stop,再启动一个实例。

Q: 浏览器打开 401? 使用完整 ?token=... URL。

Q: 用这个 Skill 会扣费吗? 会。它调用的是你自己的 EPT LLM API,所有请求从个人 EPT 额度中扣除;如需使用公司融合云额度,请改用融合云网关方案。

EPT DSH

· 2 min read
Bowen Zhang
本文作者

使用公司 EPT 模型时,保留凭据在 $env:USERPROFILE\.dsh\.credentials.yaml,不得打印 key、token、凭据内容、请求体或 Authorization 头。

路线选择

  • ept-copilot:EPT Codex Responses API,直连 https://portal-k8s-prod.ep.chehejia.com/api/copilot/codex/v1api: openai-responses,凭据引用 EPT_CODEX_API_KEY
  • ept-claude:EPT Claude Anthropic API。必须经本 Skill 的本机代理,api: anthropic-messagesbaseURL: http://127.0.0.1:8787,凭据引用可保留为 EPT_CLAUDE_AUTH_TOKEN

不要修改 DeepSeek Harness 源码来适配 EPT Claude。Anthropic SDK 默认发 x-api-key,而 EPT Claude 要求 Authorization: Bearer;本机代理负责转换。

Claude 代理

先启动并确认代理,再启动 DSH:

python "<skill-root>\scripts\start_ept_claude_proxy.py"
python "<skill-root>\scripts\start_ept_claude_proxy.py" --status
python "<skill-root>\scripts\test_ept_claude_proxy.py"

代理只监听 127.0.0.1:8787。每次请求读取 %USERPROFILE%\.config\ept\auth_session.jsonportal_token,所以 EPT 登录态刷新后无需重启代理。代理不记录 prompt 或 token。

$env:USERPROFILE\.dsh\settings.yaml 中保留或添加:

llm-pi-ai:
providers:
ept-claude:
displayName: EPT Claude (Anthropic)
apiKeyEnv: EPT_CLAUDE_AUTH_TOKEN
api: anthropic-messages
baseURL: http://127.0.0.1:8787
models:
- id: baidu-deepseek-v4-flash
name: baidu-deepseek-v4-flash

EPT_CLAUDE_AUTH_TOKEN 只需是非空凭据;代理会丢弃 DSH 传来的 key,改用 EPT 当前 portal_token。缺少该 ref 时,把一个非敏感占位值保存为该 ref,或同步当前 EPT token。

启动 DSH

优先使用内置脚本;同一时间只启动一个 3080 Web 实例:

python "<skill-root>\scripts\start_dsh.py" --npx
python "<skill-root>\scripts\start_dsh.py" --source --source-path "<dsh-source>"
python "<skill-root>\scripts\start_dsh.py" --status
python "<skill-root>\scripts\start_dsh.py" --stop

npx 命令:

$env:DSH_HOME = Join-Path $env:USERPROFILE '.dsh'
npx --yes --package '@deepseek-ai/dsh@alpha' dsh web --no-open

源码命令必须在 DSH 仓库执行:

$env:DSH_HOME = Join-Path $env:USERPROFILE '.dsh'
pnpm dsh web --no-open

始终使用 DSH 输出的完整 ?token=... URL,不能只打开裸地址。

刷新 EPT Codex key

在 EPT 登录态已刷新、且当前 PowerShell 拿到 EPT_CODEX_API_KEY 后执行:

python "<skill-root>\scripts\refresh_ept_key.py"

代理认证会读取 %USERPROFILE%\.config\ept\auth_session.json;也可通过环境变量 EPT_AUTH_SESSION 指定该文件路径。刷新脚本读取环境变量 EPT_CODEX_API_KEY

该脚本只更新 refs.EPT_CODEX_API_KEY,保留 EPT_CLAUDE_AUTH_TOKENCHJ_GATEWAY_API_KEYrecords。更新后重启 DSH Web。

排查

  • Claude 401/403:先运行 python scripts/test_ept_claude_proxy.py。失败时让用户重新执行 EPT 登录或 ept claude;不要改 DSH 源码。
  • Claude 代理端口冲突:python scripts/start_ept_claude_proxy.py --stop 后重启。
  • DSH Web 端口冲突:python scripts/start_dsh.py --stop 后只启动一个实例。
  • 浏览器 401:使用包含 token 的完整 URL。
  • EPT /models 404:不是 provider 不可用的证据;使用已知模型 id。
  • Codex 401/403:刷新 EPT_CODEX_API_KEY,运行刷新脚本,然后重启 DSH。

SSP 车辆管理 - 从 prod 迁移车辆到 testtwo

· 2 min read
Bowen Zhang
本文作者

📖 不知道怎么获取 x-chj-gwtoken?看这里! 👉 飞书文档 - 获取 x-chj-gwtoken 操作指南(含截图步骤)

核心原则:优先通过接口操作。 流程:先查 prod 获取原车数据(需 x-chj-gwtoken)→ 再到 testtwo 还原创建(无需鉴权)。

环境信息

环境域名鉴权
prod(licar)https://api-hmi-default-private-front.chehejia.com需要 x-chj-gwtoken
testtwohttps://bcs-jedi-stub-service.testtwo.k8s.chehejia.com无需鉴权

域名可通过环境变量覆盖(默认使用上表中的值):

  • VEHICLE_SYNC_PROD_URL:prod 环境域名
  • VEHICLE_SYNC_TESTTWO_URL:testtwo 环境域名

快速开始

# 安装依赖
pip install -r requirements.txt

# 直接提供 x-chj-gwtoken 运行(推荐)
python scripts/sync.py <VIN> --token "your-x-chj-gwtoken"

# 不提供 x-chj-gwtoken 运行(会提示输入)
python scripts/sync.py <VIN>

获取 x-chj-gwtoken

不知道怎么获取 x-chj-gwtoken?查看飞书文档 👉 获取 x-chj-gwtoken 操作指南(含截图)

x-chj-gwtoken 有过期时间,如果迁移过程中报 401/403,重新获取一次即可。

工作流程

1. [prod] 查询车辆基础信息 → vehSeriesNo、vehVariableModelNo、purpose
2. [prod] 查询车辆配置字 → vehicleConfigCode(HU 功能配置字)
3. [prod] 查询车辆设备信息 → SN、ICCID
4. [testtwo] 同步车辆基础信息(mes/vehicle-info/licar/sync)
5. [testtwo] 同步拓扑信息(mes/topology-info/sync)
6. [testtwo] 创建 HU 功能配置字(config-code/create)
7. [testtwo] 绑定设备(devices/bind)
8. [testtwo] 更新车辆展示信息(update-veh-info)
9. 验证结果

执行步骤(供 Claude 使用)

1. 确认参数

先问用户以下信息,缺什么问什么:

如果用户提供了 VIN 和 x-chj-gwtoken,直接进入第 2 步。 如果用户只给了 VIN,先问 x-chj-gwtoken,并告知去飞书文档查看获取方式。

2. 检查 Python 环境

python --version

确认 Python 3.10+ 可用。

3. 安装依赖

cd "docs/skill/车云平台数据同步-prod-to-testtwo"
pip install requests

4. 运行同步脚本

python scripts/sync.py <VIN> --token "<token>"

如果用户没有提供 x-chj-gwtoken 参数,会交互式提示输入。

5. 向用户报告结果

  • 成功:显示迁移完成 + 车辆信息摘要
  • 失败:显示具体失败步骤 + 错误信息

参数说明

参数必填说明
VIN目标车辆 VIN(位置参数)
--tokenx-chj-gwtoken,不传则交互式输入

故障排查

问题原因解决
401 Unauthorizedx-chj-gwtoken 过期重新获取 x-chj-gwtoken
未找到车辆VIN 不存在于 prod确认 VIN 是否正确
同步失败网络或服务异常重试,或检查 testtwo 服务状态

DSH 接入公司 LLM —— 集成工程

· 3 min read
Bowen Zhang
本文作者

目标:把公司内部 LLM 接口接进 DeepSeek Harness 直接用。 结论:主路线(chj-gateway / deepseek-v4)已经在用;本目录补全模型清单,并新增 EPT Copilot(GPT-5.6,Responses API) 作为第二 provider(路线 C)。


一、现状盘点(已侦察确凿)

chj-gateway(已有,主力)ept-copilot(本次新增)
端点https://llm-gateway-proxy.inner.chj.cloud/llm-gateway/v1https://portal-k8s-prod.ep.chehejia.com/api/copilot/codex/v1
协议openai-completions(标准 Chat Completions)openai-responses(EPT/Codex 用的 Responses API)
鉴权CHJ_GATEWAY_API_KEY(已在 .credentials.yamlEPT_COPILOT_TOKEN(需获取,见下)
模型示例kivy-deepseek-v4-flash-0731 / kivy-deepseek-v4-pro / kivy-glm5 / kivy-kimi-k2_6azure-gpt-5_6-luna / sol / terra
现状✅ 已配好,本会话正在用它跑 kivy-deepseek-v4-flash-0731❌ 未接入

▲ 完整模型清单请在本机连 VPN 后用 verify.ps1 拉取(网关 /v1/models)。


二、一句话的 EPT 机制解析

ept codex 做的事:用 auth_session 登录态 → 从企业 copilot 拉取配置 → 通过环境变量注入 base_url + API keyEPT_CODEX_API_KEY)→ 启动 Codex,Codex 走 .../api/copilot/codex/v1/responses。 也就是说公司 LLM 的“钥匙”是 portal 域名的 Bearer 令牌auth_session.json 里的 access_token / portal_token 二选一,见 verify.ps1 探测结果)。


三、目录文件

dsh-ept-integration/
├── README.md # 本文件
├── provider-merge.yml # 两个 provider 的配置片段(合并目标)
├── verify.ps1 # ① VPN 终端先跑:拉 chj 模型 + 探测 ept 可用令牌
├── apply.ps1 # ② 备份+安全合并进 $DSH_HOME/settings.yaml
└── refresh-ept-key.ps1 # ③ (可选)刷新/写入 ept 令牌到 credentials

四、操作步骤

第 1 步(重要):先探测,别急着改

在你的正常终端(已连公司 VPN)里跑:

powershell -ExecutionPolicy Bypass -File D:\bowen\git-project\dsh-ept-integration\verify.ps1

它会(只读,绝不打印密钥值):

  1. CHJ_GATEWAY_API_KEYllm-gateway-proxy.../v1/models → 打印真实模型 id 列表;
  2. 依次用 auth_session.jsonaccess_tokenportal_token 作为 Bearer 探测 portal-k8s-prod.../api/copilot/codex/v1/models → 打印哪一个令牌被接受(HTTP 200 即为通过),并在通过时打印该端点可用的模型 id。

把这两份“模型 id 列表”和“通过的令牌名”回贴给我,我再据此定稿 provider-merge.yml 里的模型清单(不要凭我给的那几个猜测字段,要以网关真实返回为准)。

第 2 步:合并配置到 DSH

确认 provider-merge.yml 里的模型/令牌符合第 1 步结果后:

# 先看差量预览(不写盘)
D:\bowen\git-project\dsh-ept-integration\apply.ps1

# 确认无误再真正合并(会自动备份 settings.yaml)
D:\bowen\git-project\dsh-ept-integration\apply.ps1 -Apply

第 3 步:写入 ept 令牌(路线 B 用)

把第 1 步确认可用的令牌写进 DSH 凭据:

D:\bowen\git-project\dsh-ept-integration\refresh-ept-key.ps1 # 交互式从 auth_session 提取并写入 .credentials.yaml

(写入的是 EPT_COPILOT_TOKEN 键;注意 access_token 每天过期,需定期刷新——脚本会提示。)

第 4 步:让 DSH 生效并选模型

改完 settings.yaml重启 dsh web,然后在 Web 的模型选择里切换:

  • CHJ LLM Gatewaykivy-deepseek-v4-*(主力)
  • EPT Copilotazure-gpt-5_6-*(新增)

五、注意事项

  • 密钥安全:令牌属于敏感信息,脚本只在内存中使用、不回显;写入 .credentials.yaml 时保持该文件私密。
  • 凭据自动刷新access_token 短有效期(auth_session.jsonexpires_at),企业后台凭据说 refresh_token 可续。用 cron / 开机脚本定期跑 refresh-ept-key.ps1 即可维持。
  • 503 抖动:日志曾见 simulated no healthy upstream(deepseek-v4-pro 偶发 503)。属网关上游问题;pi-ai 有重试策略,若频繁可顺手把 CLI 里的重试调高。
  • 本沙箱无 VPN 且写盘受限,所以所有实连验证都必须在你的正常终端完成

dsh-hello-plugin

· 4 min read
Bowen Zhang
本文作者

一个 0 依赖DeepSeek Harness 插件, 用来演示 Cordis 插件系统的四个核心机制,并且能在任意目录直接安装

这个文件夹里的插件就是为 D:\bowen\git-project\dsh-hello-plugin\ 准备的, 不需要放进 DSH 仓库,也不需要联网装依赖。


目录结构与“每步作用在哪”

dsh-hello-plugin/
├── index.js # 插件本体(唯一源码,0 依赖)
├── package.json # 打包安装路线(dsh plugin add)用的 bundle 清单
├── cordis.yml # 开发期路线:--patch 覆盖层(引用上面的 index.js)
├── cordis.patch.yml # 打包路线:bundle 在被安装时应用的那一层
└── README.md # 本文件

index.js 里的插件扮演了这四种角色,各自作用在 DSH 的不同层:

#插件里的一段作用在哪个机制/层怎么观察
0export const nameCordis 插件的身份
1export const inject = ['tools']Cordis 依赖注入 + 生命周期 gating:框架等到 ctx.tools 就绪才把本插件从 PENDING 激活到 ACTIVE 并调用 apply()加载顺序不再是手排的,而是“等服务”
2apply(ctx) 第一行日志fiber 进入 ACTIVE(插件生命周期入口)启动终端打印 [dsh-hello-plugin] ACTIVE …
3ctx.effect(() => … setInterval …)可逆副作用:卸载/HMR 时自动 clearInterval改配置热替换后定时器不留残留
4ctx.on('session/created', …)钩住 Harness 应用生命周期:订阅会话子系统(packages/core/session)的真实 emit 事件新建聊天时终端打印 session/created
5ctx.tools.register({…})插入工具执行流水线packages/core/tools):注册 greet 工具,schema 自动流入系统提示词装配在 UI 里让模型调用 greet
6apply() 末尾 return () => …卸载清理最后一步(disposer,与各 effect 逆序执行)热替换/退出时打印 DISPOSED

前提

你的 DSH 是从源码跑起来的(界面上应该是 http://127.0.0.1:3080),且在 D:\bowen\github\deepseek-harness 有可执行的 checkout、pnpm 可用。 (如果不是从源码跑,见「路线 B」。)


路线 A · 开发期安装(最快,推荐)

这一步不“安装”到任何地方,而是让 DSH 在启动时叠加一层 patch 把插件挂进去。

  1. 停掉当前正在跑的 DSH Web(占用 3080 的那个进程)。

  2. 在 DSH 源码根目录执行:

    cd D:\bowen\github\deepseek-harness
    pnpm dsh web --patch D:/bowen/git-project/dsh-hello-plugin/cordis.yml
  3. 打开 http://127.0.0.1:3080

验证四件事:

  • 终端出现 [dsh-hello-plugin] ACTIVE — apply(ctx) 执行 …(插件装上了)。
  • 在 UI 开一个新对话 → 终端出现 [dsh-hello-plugin] 生命周期钩子触发 → session/created …(挂上生命周期的证据)。
  • 输入:用 greet 工具跟 Ada 打个招呼 → 模型调用 greet,得到 你好, Ada!(工具进流水线的证据)。
  • 改一下 cordis.yml 里的 greeting/heartbeatMs 再重启,观察配置生效、旧实例干净卸载。

为什么要用 file:///D:/... 而不是 D:/...D:\... 会被 Node 当成 URL 的 scheme d: 解析而报错;file:///D:/... 才是合法的模块标识符(见 vendor/loader/src/config/tree.tsimport() 解析)。

卸载路线 A:去掉启动命令里的 --patch … 参数即可,或者把 - insert 整段删掉。


路线 B · 打包安装(正式安装进 profile)

把插件变成一个可通过 dsh plugin 安装的组合包(bundle)。适合分发给别人 / 长期使用。

  1. 确认 dsh CLI 可用(源码 checkout 下用 pnpm dsh 代替 dsh)。

  2. 在本插件目录安装其 checkout:

    cd D:\bowen\git-project\dsh-hello-plugin
    dsh plugin --profile demo add .

    首次使用会初始化名为 demo 的 profile。因为我们声明了 dsh.bundle.patch (见下面),dsh 会把 dsh-hello-plugin 追加进该 profile 的 dsh.profile.bundles

  3. 先只看组合后配置、再启动:

    dsh --profile demo --dump-config # 会看到 “# == dsh-hello-plugin” 那一层
    dsh --profile demo
  4. 验证方式同路线 A(打开 Web UI 观察上面四件事)。

这里的 package.json 起了什么作用?

{
"main": "index.js", // 插件入口 = 同一个 0 依赖文件
"files": ["index.js", "cordis.patch.yml"], // 发布/打包只带这两个文件
"dsh": { "bundle": { "patch": "./cordis.patch.yml" } } // 声明“我是一个组合包,贡献这层 patch”
}

卸载路线 B

dsh plugin --profile demo remove dsh-hello-plugin # 同时移除依赖和它贡献的层

从 git / tarball 安装

dsh plugin --profile demo add ./dsh-hello-plugin-0.1.0.tgz # 或 github:you/dsh-hello-plugin

(你这份是纯 JS、main 就是构建产物,没有 prepare 构建脚本这道坎,git 安装也安全。)


配置文件一览

cordis.yml(路线 A 专用):

- insert:
- id: dsh-hello-plugin
name: 'file:///D:/bowen/git-project/dsh-hello-plugin/index.js'
config:
greeting: '你好'
heartbeatMs: 0 # 大于 0 时每秒打印心跳(演示 effect 清理)
verbose: true
  • insert = 往装配树里插入一行;插件加载时 config 会原样传给 apply(ctx, config)
  • 因为没导出 Config schema,这里配置是“透传 + 代码内默认值”的方式。

cordis.patch.yml(路线 B 专用): 唯一的差别是把 name 换成包名 dsh-hello-plugin, 这样库才在 profile 的 node_modules 里按模块名解析到已安装的代码。


怎么继续扩展

  • 加配置校验 / 默认值:在 index.js 导出 schemastery 的 Config

    // 需要联网先在本目录 pnpm add @deepseek-ai/schemastery(或复用 DSH 仓库里的)
    import Schema from '@deepseek-ai/schemastery'
    export const Config = Schema.object({
    greeting: Schema.string().default('Hello'),
    heartbeatMs: Schema.number().default(0),
    verbose: Schema.boolean().default(false),
    })

    一旦导出了 Config,Cordis 就会用它对 cordis.yml 的 config 做校验并填默认值。

  • 对外提供服务:把 apply(ctx) 改成 Service 子类并用 super(ctx, 'hiService') + ctx.provide(...),别的插件就能 inject: ['hiService'] 拿到它。

  • 参考user/develop/basicCordis primerCordis tutorial


LICENSE: MIT · 纯演示用途,无外部依赖。

AOSP APK 签名

· 2 min read
Bowen Zhang
本文作者

使用 scripts/sign.py 调用签名平台接口完成一次完整签名流程:上传 APK、创建后台任务、轮询任务状态,成功后返回签名文件地址。

使用 scripts/download.py 携带 Artifactory Basic Auth 下载 signed_url 返回的签名 APK。

快速开始

python scripts/sign.py path/to/app.apk \
--platform SS4 \
--signature-type platform \
--key-source releasekey \
--user-name fengyubiao

脚本成功时输出 JSON,重点字段为:

{
"status": "completed",
"task_id": "...",
"signed_url": "https://...apk.signed"
}

必填参数与环境变量

脚本读取以下环境变量:AOSP_SIGNATURE_BASE_URLAOSP_SIGNATURE_USER_NAMEARTIFACTORY_USERNAMEARTIFACTORY_PASSWORD

参数默认值说明
apk待签名 APK 本地路径
--user-nameAOSP_SIGNATURE_USER_NAME签名平台用户 LDAP 名称
--platformSS4SS3SS4
--signature-typeplatform签名类型,默认平台签名
--key-sourcereleasekey密钥来源
--base-urlAOSP_SIGNATURE_BASE_URL 或平台正式域名签名平台地址
--interval5轮询间隔,单位秒
--timeout1800最大等待时间,单位秒
--request-timeout300单次 HTTP 请求超时时间,单位秒

当前 Skill 不要求 Cookie,也不会主动发送 Cookie。签名平台需要在当前内网环境可直接访问。

$env:AOSP_SIGNATURE_USER_NAME = "fengyubiao"
python scripts/sign.py .\app-release.apk --platform SS4

下载签名 APK:

$env:ARTIFACTORY_USERNAME = "你的 Artifactory 用户名"
$env:ARTIFACTORY_PASSWORD = "你的密码或 Token"
python scripts/download.py `
"https://artifactory.example/artifactory/path/app.apk.signed" `
--output .\app-release.apk.signed

脚本使用流式写入,先保存为 .part 临时文件,下载完成后再替换目标文件;认证失败、网络失败或中断时会清理临时文件。

下载参数:

参数默认值说明
--usernameARTIFACTORY_USERNAMEArtifactory 用户名
--passwordARTIFACTORY_PASSWORDArtifactory 密码或 Token
--timeout600下载请求超时时间,单位秒
--chunk-size1048576流式下载块大小,单位字节

工作流

  1. 检查 APK 文件存在且扩展名为 .apk
  2. /api/apk/sign 发送 multipart form-data 请求,字段为 fileplatformsignature_typekey_sourceuser_name
  3. 从响应中读取 task_idstatus=accepted 表示任务已进入后台队列,不代表签名完成。
  4. 轮询 /api/tasks/stats/summary?user_name=... 获取总体 signing、completed、failed 状态,用于进度日志。
  5. 轮询 /api/tasks/list?user_name=...,按返回的 task_id 精确匹配当前任务。
  6. status=completedsigned_url 非空时立即返回 signed_url
  7. status=failed 或达到超时时抛出明确错误,并保留 task_id 方便人工排查。

不要按文件名或列表第一条任务匹配;同名 APK 可能存在多个历史任务,必须使用创建接口返回的 task_id

鉴权说明

HAR 只用于确认接口字段和响应结构,不要复制其中的 OAuth code、access token、refresh token 或 Cookie。当前实现不处理 Cookie;若接口返回 401/403,应确认服务端是否已开放内网匿名访问。

相关接口

详细请求/响应字段见 [references/api.md](#)。脚本仅使用 Python 标准库,无需安装第三方依赖;依赖说明见 [requirements.txt](#)

常见问题

  • accepted:任务已创建,继续轮询,不要立即当作成功。
  • signing:签名处理中,继续等待。
  • completedsigned_url 为空:视为异常,返回错误并提示检查平台任务详情。
  • failed:输出 error_message,不要重复自动提交同一个 APK,除非用户明确要求重试。
  • 列表接口没有当前 task_id:可能是任务尚未入库,等待后重试;超过超时后失败。

完整流程 - 从 prod 迁移车辆到 testtwo 并推送应用

· 4 min read
Bowen Zhang
本文作者

一站式编排:检测是否存在 → 添加车辆 → 添加白名单 → 切换云端环境 → 批量推送应用。 本 skill 是编排层:把各叶子能力按顺序串联,判断点必须询问用户;具体接口操作由各子 skill 完成。

流程概览

Step 1 [检测] testtwo 查询车辆是否存在 → 存在则跳过 Step 2
Step 2 [添加] 不存在时:prod 查询 → testtwo 添加车辆 + 绑定设备
Step 3 [白名单] 通过飞书机器人罗伯特添加 X01 白名单(线上 + 线下)
Step 4 [切环境] ⚠ 询问用户是否需要切换云端环境(prod → testtwo)
Step 5 [推送] ⚠ 询问用户是否需要批量推送(按车型选 OTA 测试分组)

前置条件

⚠ 本 skill 是编排层,依赖同市场发布的 3 个子 skill。需与本 skill 一起安装,否则 flow.py list 会显示「缺」,流程无法执行。

1. 安装依赖(插件市场)

本 skill 与子 skill 都发布在插件市场 lixiang-skills-marketplace,先添加并刷新市场,再按名称安装:

# 添加插件市场(首次执行)
/plugin marketplace add https://gitlab.chehejia.com/ai-market/lixiang-skills-marketplace.git

# 刷新市场,拉取最新插件列表
/plugin marketplace update lixiang-skills-marketplace

# 按名称安装(直接写插件名,不要带 lixiang-skills-marketplace@ 前缀)
/plugin install cheyun-vehicle-migrate-prod-to-testtwo-push
/plugin install cheyun-vehicle-sync-prod-to-testtwo
/plugin install cheyun-lark-robert-whitelist-env
/plugin install cheyun-amp-batch-push-app

# 安装完成后执行,使插件生效
/reload-plugins

以下 4 个插件在本流程中的作用与入口脚本:

市场中的名称在本流程中的作用入口脚本
cheyun-vehicle-migrate-prod-to-testtwo-push本编排 skill(主流程)flow.py
cheyun-vehicle-sync-prod-to-testtwoStep 1~2 检测/添加车辆sync.py
cheyun-lark-robert-whitelist-envStep 3~4 白名单/切换环境send.py
cheyun-amp-batch-push-appStep 5 批量推送push.py

2. 运行所需凭据

条件说明
x-chj-gwtokenStep 1~2 查询/同步需要(从 licar.chehejia.com F12 Network 复制)
lark-cli + 飞书群Step 3~4 需要(需先加入罗伯特所在飞书群并 lark-cli auth login
AMP CookieStep 5 需要(testtwo 登录 cookie,见子 skill 说明)

子 skill 一览

步骤子 skill入口脚本
1~2 检测/添加cheyun-vehicle-sync-prod-to-testtwosync.py --token …
3 白名单cheyun-lark-robert-whitelist-envsend.py whitelist <VIN>
4 切换/查询环境cheyun-lark-robert-whitelist-envsend.py switch-env / query-env
5 批量推送cheyun-amp-batch-push-apppush.py add <VIN…> --group …

每个子 skill 都是独立可安装的 skill,本 skill 只负责编排,不重复实现。

驱动命令

# 打印完整 5 步流程与命令(推荐先跑这个)
python scripts/flow.py plan <VIN...>

# 打印某一步的说明与命令
python scripts/flow.py step <1..5> <VIN...>

# 校验子 skill 是否就位
python scripts/flow.py list

执行步骤(供 Claude 使用)

汇总结论:把 flow.py 输出的命令复制执行;每步完成向用户汇报后再进下一步。

  1. 确认 VIN 列表(17 位,多台空格/逗号分隔)
  2. flow.py plan <VIN...> 拿到完整清单与命令
  3. Step 1~2 迁移:确认 x-chj-gwtoken(没有就引导用户从 licar F12 复制,见 cheyun-vehicle-sync-prod-to-testtwo 的飞书文档),运行 sync.py <VIN> --token <token>;若车辆已存在会提示,跳过添加
  4. Step 3 白名单:确认 lark-cli 可用且已进群,运行 send.py whitelist <VIN>(无论什么车型都按 X01;线上+线下都要)
  5. Step 4 切换环境必须询问用户是否需要切换(车辆可能不在线,切了无意义);需要则运行 send.py switch-env <VIN> prod testtwo
  6. Step 5 批量推送必须询问用户是否需要推送;需要则按车型选组(X04B=3000742,X04C=3000743,或 push.py groups --name <关键字> 查),运行 push.py add <VIN...> --group <名称或id>
  7. 收尾汇报:每台车的迁移/白名单/环境/推送结果汇总给用户

判断点(必须询问用户,不要自动执行)

判断点原因
Step 4 是否切换云端环境车辆可能不在线,切换了无意义,由用户判断车辆状态
Step 5 是否批量推送属额外操作,需用户确认

参考文档

内容位置
迁移/检测/添加车辆接口cheyun-vehicle-sync-prod-to-testtwo 技能说明
白名单/切换环境cheyun-lark-robert-whitelist-env 技能说明
测试分组查询接口docs/查询测试分组.md
AMP 登录 Cookie 获取飞书文档 获取AMP登录Cookie操作指南

故障排查

问题原因解决
flow.py list 显示「缺」子 skill 目录缺失按上文安装依赖,装完执行 /reload-plugins
/plugin install lixiang-skills-marketplace@xxx 报 Marketplace not found当前 CLI 不支持 市场名@插件名 写法去掉前缀直接 /plugin install xxx
迁移报 401/403x-chj-gwtoken 过期重新获取并传入;见 sync skill 飞书文档
白名单发送失败/找不到群未进群 / token 过期先通过邀请链接进群,再 lark-cli auth login
推送报 code 240420AMP Cookie 过期重新登录 testtwo AMP 复制最新 Cookie