SKILL.md 18 KB


name: smartbadge-ops

description: 智能工牌录音管道全功能运维技能。当用户提到录音归档、录音下载、管道巡检、转录重试、每日录音任务、smartbadge 运维、归档失败、转录失败、录音清洗、讯飞转录、OSS 同步、分析任务状态、线上部署核验、健康检查、列表数据、故障自诊断、月报、年报、周报、日报汇总、报告解读、历史数据对比、区间数据聚合时使用。提供对服务器定时管道(归档→清洗→讯飞转录→DeepSeek 报告)的巡检、手动触发、补跑、重试、故障诊断、列表排查、月报/年报按需聚合分析、线上部署核验与浏览器走查。交互特色:先复述问题与方案,回问用户确认后再执行。

智能工牌录音管道运维(smartbadge-ops)

服务器(server/index.js)常驻运行每日定时管道,无需人工值守;本技能是控制面:巡检、诊断、补跑、重试、部署核验、区间(月报/年报)按需聚合分析。所有作业逻辑在服务器端,技能只调用其 REST API 与直连 OSS。

本技能为独立仓库,脚本全部在 ./scripts/(零依赖,Node >=18;verify-online.py 需本机 playwright)。


§1 交互协议:确认门(第一优先,不可跳过)

无论用户请求什么,先走确认门:

重档(默认,适用于一切「有生产影响」或「参数不明确」的请求)

  • 写操作永远重档:archive/runanalysis/runretryretry-transcriberepair-ossconfig PUT、任何 DELETE。
  • 步骤:
    1. 复述:用 1-3 句话复述我理解的问题、时间窗、对象(哪些设备/日期)、期望产物(如「月报 Markdown」)。
    2. 方案:列出将执行的脚本与命令序列,并一句话说明是否会写数据
    3. 回问:"是这个意思吗?" 等待用户确认(或纠正)。
  • 用户纠正后:只用一句更新复述,再确认一次即执行,不重复长篇。
  • 已确认动作链中的后续复查步骤(如补跑后复跑 report-aggregate/reconcile 归零验证)视为同一确认,无需再问。

轻档(预授权:纯只读且参数齐全)

以下场景视为用户已授权,可一句话备案后直接执行(备案格式:我将执行:…(若与预期不符请中断),不强制等待回答):

  • get/list 查询、check-online.mjs 巡检、oss.mjs 列举、reconcile 对账、report-aggregate 聚合、fetch-report-text 正文拉取、verify-online.py 走查。
  • 用户说「巡检」「跑 check-online」等明确指令,直接执行。

确认门例外

  • 用户明确说「直接跑」「不用问」或已确认过相同模式请求 → 跳过回问,执行并在首句说明。

§2 连接与凭据

export MSYS_NO_PATHCONV=1     # 仅 Windows Git Bash 需要(防 / 开头参数被转成 Windows 路径);Linux/Docker 无此问题
  • 接口地址:默认线上 https://recording.sh-lami.com;本地开发:环境变量 SMARTBADGE_API_BASE=http://localhost:3002(或各脚本 --base)。
  • 登录:node scripts/api.mjs login <密码>,token 缓存到 scripts/.token(各脚本自动共享)。
  • 用户名/密码无内置默认值(1.2.0 起零密钥原则):必须经环境变量或 .env 提供,缺省脚本报错提示;Docker 容器用 -e SMARTBADGE_USERNAME=/PASSWORD=--env-file 注入。
  • 凭据回退链(OSS 等):--env 参数 > SMARTBADGE_ENV_FILE > 技能仓库根 .env(npx 安装后复制 .env.example 填值) > 自动发现(向上扫本仓库同级/兄弟目录含 server/.env 的项目,如服务端项目与技能放在同一父目录) > 已存在的 OSS_* 进程环境变量。
  • 敏感凭据只存在于服务端项目 server/.env(OSS/讯飞/DeepSeek/masterKey),本技能仓库不含任何密钥;node scripts/oss.mjs --find-env 可查看实际采用的 server/.env 路径。
  • 平台:技能本体零依赖 Node ≥18 跨平台(Windows/Linux/Docker 一致);verify-online.py 浏览器走查需要 playwright+chromium,容器/无浏览器环境跳过(用 check-online.mjs 替代);日期口径固定 Asia/Shanghai,容器 UTC 时区无需配置。

§3 能力矩阵与编排表

脚本 能力 典型参数
scripts/api.mjs 任意接口调用 login / get <路径> / post <路径> '<JSON>' / env / --raw / --base
scripts/check-online.mjs 12 项断言一键核查 [密码]SMARTBADGE_PASSWORD
scripts/verify-online.py 浏览器 5 页走查 + 0 错误断言 环境变量 PLAYWRIGHT_BASE_URL/SMARTBADGE_*
scripts/oss.mjs OSS 直连列举统计 [prefix] --json --env <path> --find-env
scripts/report-aggregate.mjs 区间聚合(月报/年报/任意窗口) --start --end [--type day\|week\|all] [--json] [--no-reconcile]
scripts/fetch-report-text.mjs 报告正文拉取(HTML→文本) --id <reportId> | --url <直链> [--preview] [--json]

用户需求 → 命令序列(编排参考)

  • 「今天(这几天)管道有问题吗」→ check-online.mjs → 有 FAIL 走 §7 → 按 category 处置 → 汇总。
  • 「昨天报告没有/转录失败」→ api.mjs get /api/analysis/health + errors?pageSize=20 看 category(§7 处置表)。
  • 「昨天的数据/录音列表不对」→ §8 列表诊断。
  • 「给我上月月报」(月报/年报 == 同流程换窗口) → 确认门(窗口+产物形态)→ report-aggregate --start 月初 --end 月末 --json → 必要时补跑缺失日(§10)→ fetch-report-text 选 3-5 篇读正文 → 按 templates/monthly-report.md 八段模板产出 → 产物形态加工(Markdown/HTML/PPT)。
  • 「上线后核验一下」→ §12(check-online + verify-online.py + nginx -t + pm2 logs)。
  • 「OSS 里有哪些东西」→ oss.mjs(顶层)或 oss.mjs recordings/ 等按前缀。

§4 架构与每日流程

每天 archive_time(默认 02:00 Asia/Shanghai, 可配 SbSystemConfig)
 ├─ 归档: 上游 /audio/list → 下载本地 → OSS(ETag 校验) → SbAudioRecording 落库(含音源字段镜像)
 ├─ 分析: process.py 三级过滤(静默/模糊/短音频) → 讯飞多说话人 → SbTranscriptSegment
 ├─ 报告: DeepSeek → HTML → reports/ + OSS → SbReport(day/week)
 ├─ 合并: 按设备×天拼接 MP3(OSS merges/,仅存档收听,不参与转录)
 ├─ 24h 清理: 已 OSS 同步文件 → canPurge → 删除本地(DB 记录保留)
 └─ 保留期兜底清理: 录音 15 天 / 合并 7 天 / 报告 HTML 7 天(删前补同步一次;报告 OSS 补传失败时安全闸保留本地)
每周一(archive_time+30min): 周报(近 7 天聚合, 转录增量跳过不重复计费)
失败任何环节 → 自动入队重试(3 次, 5/15/30 分钟指数退避) → 耗尽才进入错误展示;重试零残留

边界事实(设计依据):

  • 归档窗口 ≤7 天(上游自动删除录音)→ 错过即丢;>6 天前的缺失不可补
  • POST /api/analysis/run 窗口上限 MAX_WINDOW_DAYS=7、start 晚于今天报错、全局互斥 1 个任务(冲突 429)→ 区间聚合/补跑严格遵守:一次最多 7 天,或逐日。
  • 录音列表默认本地库(截至昨日);endDate >= 今天 走上游实时分流。
  • 转录消耗讯飞额度(每文件一次;清洗已滤约 90% 无效音频;周报/聚合复用已转录段落不重复计费)。

§5 接口命令速查(经 api.mjs)

命令 用途
get /api/archive/status?date=&deviceNo= 当日归档状态(expected/downloaded/ossSynced/failed)
get /api/archive/missing 归档失败待重试列表(含 retryCount/lastError)
post /api/archive/run '{"dates":[...]}' \| '{"dateRange":{"start","end"}}' \| '{"devices":[...]}' 手动触发归档(默认全部×昨天)
post /api/archive/retry '{"ids":[...]}' 重试失败归档(也支持 {date}/{deviceNo})
post /api/archive/retry-transcribe '{"date":"YYYY-MM-DD"}' 仅重跑转录(不重复清洗;互斥 429)
post /api/analysis/run '{"period":"yesterday"\|"last7days"\|{"start","end"},"type":"day"\|"week"}' 手动分析(窗口≤7 天,互斥)
get /api/analysis/jobs?status=&page=&pageSize= 任务列表(status/progress/summary/reportId/transcriptCount/nextRetryAt/failStage)
get /api/analysis/reconcile?date= 三方对账(total/localHit/ossHit/transcribeDone/missingCleansed/missingTranscript)
post /api/analysis/repair-oss '{"date":"YYYY-MM-DD"}' 补传缺失 OSS 对象(互斥 429;支持 {ids})
get /api/analysis/health 健康快照(retryingCount/warnings/categoryCounts/ossMissingCount)
get "/api/analysis/errors?pageSize=20" 错误汇总(四来源,含 advice;重试中默认隐藏,includeRetrying=true 查)
post /api/smartbadge/recordings/list '{"page":1,"pageSize":20}' 录音列表(本地库;支持 deviceNo/startDate/endDate/keyword;endDate>=今天走实时)
post /api/smartbadge/logs/heartbeat '{"page":1,"pageSize":20}' 心跳列表(startTime/endTime 代替日期)
get /api/devices?page=&pageSize=&keyword= 设备分页(DB 级)
get /api/config / put /api/config '{"key":"value"}' 系统配置(archive_time 等;PUT 前必过确认门)
get /api/reports?type=day\|week&start=&end=&pageSize= 报告列表(分页;无正文)
get /api/reports/:id 报告详情(同样无正文;正文经 ossUrl/downloadUrl)

写请求必须带 X-Requested-With 头——api.mjs 已自动带上;手动 curl 时须加。

§6 每日巡检 SOP(营业前一次)

  1. node scripts/check-online.mjs12 项全 PASS 即健康;0 FAIL 跳第 5 步汇报。
  2. 有 FAIL:进 §7 定位——先 api.mjs get /api/analysis/healthretryingCount(>0=引擎自动重试中,别急)。
  3. api.mjs get /api/analysis/reconcile?date=<昨天> 核对缺项;oss.mjs 核对四类目录数量(recordings/ cleansed/ transcripts/ reports/)。
  4. <昨天>missingCleansed/missingTranscriptrepair-oss '{"date":"<昨天>"}' 补传,复跑验证归零。
  5. 三行简报:正常项 / 异常项(及原因分类)/ 采取的动作。
  6. 周一额外:jobs?pageSize=5 见 week 任务 + get /api/reports?type=week 有周报。

§7 故障自诊断 SOP

node scripts/api.mjs get /api/analysis/health               # retryingCount=自动重试中数;categoryCounts=分类计数
node scripts/api.mjs get "/api/analysis/errors?pageSize=20" # 重试中项默认隐藏(耗尽才出现)
node scripts/api.mjs get "/api/analysis/errors?includeRetrying=true&pageSize=20"

重试语义:失败先自动重试 3 次(5/15/30min,~50 分钟),耗尽才可见。retryingCount>0 → 等引擎;0 且有 warnings → 真错误。 无害告警:health warnings 中「最近任务无待转录文件(属正常)」是无害告警(当日无录音或全部被三级过滤),不影响健康判定;check-online 已按此语义断言。

按返回 category 行动(每条自带 advice):

category 含义与动作
quota(额度/并发) 讯飞/DeepSeek 额度受限或并发超限(10407/10901/402/429/rate limit):非接口故障,等恢复或联系开通;可稍后 retry-transcribe/analysis/run(增量跳过,成本低)
network/timeout 网络抖动/超时(ETIMEDOUT/ECONNREFUSED/socket):重试即可;当日重试 archive/retry/retry-transcribe
auth(鉴权) 密钥/令牌错误(401/403/accessKeyId/signature):报修——检查服务器 server/.env 的 OSS*/IFLYTEK*/DEEPSEEK_API_KEY 是否过期,修复后重试
server(5xx) 上游 5xx 或内部错误:报修——查 pm2 logs smartbadge-api 或宝塔日志
other 未知格式:人工看 message;可复现则升级分类器关键词

口径示例:「今天的报告为什么没有?」→ errors?source=report → quota:「不是接口问题,额度受限,已自动重试,等待恢复」;auth:「鉴权失败,需检查密钥(报修项)」。先跑命令看 category,不要凭猜回复。

§8 列表问题诊断 SOP

  1. 本地列表(默认窗)recordings/list → total>0 且无 failed/capped?缺失日 = 归档失败日:查 archive/status?date=archive/missing
  2. 「包含今日」开关走实时——failed/capped 非空 = 上游个别设备失败/超 2000 条截断;等 60s 缓存或缩小筛选。
  3. startTime 全为 -:上游 /audio/list 最后一条元数据未结算(数据源属性);旧行缺字段可跑回填脚本 server/scripts/maintenance/backfill-recording-meta.js
  4. 上游误返全量:服务端已有近 7 天缺省窗,移除。

§9 补跑与重试 SOP

  • 昨天断电/失败 → post /api/archive/run '{"dates":["<昨天>"]}'(仅收 今天-6 ~ 今天)。
  • 部分文件下载失败 → post /api/archive/retry '{}'(按日期/设备过滤更精准)。
  • 转录失败 → post /api/archive/retry-transcribe '{"date":"<日期>"}'
  • 报告失败(任务 error 含「报告生成失败」)→ post /api/analysis/run '{"period":"yesterday","type":"day"}'(已转录增量跳过,只补报告)。
  • 互斥 429 → 已有任务运行中:先 get /api/analysis/jobs 看进度;分析有超时兜底(20 分钟),等待即可。
  • 跨 >6 天窗口的缺失:上游已删,不可补,在汇报中披露。

§10 月报/年报 SOP(按需聚合,不建永久管道)

系统仅自动产生 day/week 报告;月报/年报 = 运行时拉取窗口数据自动聚合分析。执行步骤:

  1. 确认门(重档无关,但必须问):
    • 窗口:如「2026 年 8 月」= --start 2026-08-01 --end 2026-08-31;年报同理 01-01 ~ 12-31;或自定义区间。
    • 内容范围:仅数据(录音/转录/报告清单)还是含智能分析(读报告正文提炼)?默认含。
    • 产物形态由用户选择:① Markdown(默认,回复正文+可存文件)② HTML(模板 templates/report-html.html + markdown 最小转换)③ PPT(使用全局 weekly-report-pptx 技能承接)。
  2. 拉数据:node scripts/report-aggregate.mjs --start <起> --end <止> --json(可 --type week 只看周报;--deviceNo 单设备;--no-reconcile 跳过逐日对账)。得到:报告清单、逐日明细、缺失三类清单(无报告日/转录=0 日/对账异常日)、补跑建议命令。
  3. 补缺失(过确认门):对 daysAgo<=6 的无报告日,执行聚合输出里的建议命令(逐日 analysis/run,{"period":{"start":D,"end":D},"type":"day"});复跑聚合验证归零。
  4. 读正文(需要智能分析时):node scripts/fetch-report-text.mjs --id <reportId> --preview 选 3-5 篇代表性报告(readme 说选择标准:设备覆盖广、转录量高、异常日),必要时 --json 定位 id(或 api.mjs get "/api/reports?type=day&start=<起>&end=<止>&pageSize=10")。
  5. 产出:按 templates/monthly-report.md 八段(总体概览/设备活跃/录音量与转录效率/趋势/异常与缺失/报告要点摘录/结论与建议)成稿;形态按第 1 步选择。
  6. 披露:超 6 天的缺失日标注「上游已清理,不可补」;summary=「无待转录文件」 的任务属正常(三级过滤)。

注意:report-aggregate 是只读(轻档权限);「补缺失」是写操作,必须重档确认。

§11 报告解读

  • 列表/详情无正文:正文经 ossUrl(OSS 公开直链)或 downloadUrl(302 OSS / 本地回源)获取 → 推荐 fetch-report-text.mjs
  • 阅读视角(KPI 指标卡、客户画像表、关键事件时间线、销售策略、VOC 原话、风险提示);报告只含转录文本与指标,不内嵌录音 URL。
  • 报告 HTML 是 DeepSeek 提炼物(含 VOC 引用 6-9 条),非全文转录;需要全文 → §13。

§12 上线/部署核验 SOP

node scripts/check-online.mjs        # 12 项断言: 登录/health/归档/列表/实时分流/心跳/设备/互斥
python scripts/verify-online.py      # 浏览器: 5 页走查 + 0 pageerror 断言
nginx -t                             # 宝塔保存自动校验;配置见 deploy/nginx-recording.sh-lami.com.conf
pm2 logs smartbadge-api --lines 50   # 服务器错误日志
  • 前端打包:项目内 pnpm build → zip 上传解压到线上 dist;后端 .env.env.production 模板(PORT=3007)+ CDN 自动拉取。
  • 双进程提醒:共享 Parse 只允许一个后端常驻跑 cron——本地(3002)与线上(3007)不要同时在线。

§13 转录原文获取(边界)

  • 转录原文无 HTTP 接口,数据在 Parse SbTranscriptSegment(CLP 仅 masterKey,技能侧不可直读)。
  • OSS 有转录文本对象:transcripts/{deviceNo}/{Y}/{M}/{D}/*.txtnode scripts/oss.mjs transcripts/ 列举,经 publicDomain 拼直链可下载。
  • 需逐条查原文时,在企业内用服务器 masterKey 侧(如维护脚本),不在本技能承诺。

§14 注意事项

  1. 归档窗口 ≤7 天:错过即丢,巡检每天执行。
  2. 写操作(归档/分析/重试/补传/配置)一律先确认门,并提示互斥 429 可能性。
  3. 凭据只存 server/.env(讯飞/DeepSeek/OSS/masterKey),本仓库零密钥;git 提交需用户明确同意。
  4. 禁止直接在 server/recordings/ 下手动跑 process.py:对输入文件是移动/删除语义;排查过滤请用工作区副本或 repair-oss
  5. Python 仅服务器端管道需要;技能本体不调 Python(Docker/Linux 容器零 Python 依赖可跑全部 Node 脚本)。唯一例外 verify-online.py(浏览器走查)需在宿主机执行 pip install playwright && playwright install chromium
  6. .token/out//__pycache__ 已 gitignore,不提交。

§15 结束协议(每任务收尾)

输出三行:① 做了什么(命令序列)② 结果(数据或 PASS/FAIL + 异常项)③ 遗留与建议下一步。有「未验证项/已知限制」要显式披露。

相关技能

  • 报告人工解读模板细节见项目内 smartbadge-report(执行报告解读时可调用)。
  • PPT 产物:全局 weekly-report-pptx 技能。