Come usare
- Copia il comando e controlla il pacchetto prima di installarlo nel tuo ambiente agente.
- Controlla strumenti, credenziali e ambienti richiesti nel documento originale.
- Descrivi input e risultato desiderato; confronta l’output con le fonti.
npx skills add https://github.com/happyplum/workskills --skill opencode-subagent-log-triagePrima di iniziare
- L’installazione non include abbonamenti, quote API o accesso ai file.
- Stelle e installazioni indicano attività, non un test indipendente di qualità o sicurezza.
Contenuto dal repository con titoli, esempi, codice, tabelle, link e immagini preservati.
OpenCode 子代理日志排查
概述
本 skill 覆盖两类取证,共用同一套本地数据源(SQLite DB / 日志 / 进程树):
- 卡住排查:把模糊的「子代理卡住」报告转化为证据,判断工具是否仍在运行还是仅存储陈旧,推荐最小安全干预。
- 执行审计:把「这次开发费时费钱」的感受转化为总账——按会话树汇总成本/token/时长,找出烧钱贡献最大的会话,支撑 prompt 与流程改进讨论。
核心原则:在从独立证据关联起卡住的 session、工具调用、进程树和用户可见结果之前,绝不杀进程或编辑任何东西。
存储事实(先读)
- SQLite DB 是唯一权威:
%USERPROFILE%\.local\share\opencode\opencode.db。会话表含成本与 token 列(见下)。 - session JSON 已陈旧:
storage\session\下的 JSON 文件自存储迁移后不再更新,只用于考古,发现其 mtime 陈旧时直接转向 DB,不要在 JSON 里反复 grep。 - DB 可能数十 GB:一律 readOnly 打开(脚本已内置),禁止 VACUUM/写入;WAL(
opencode.db-wal)随主库一并可读,无需单独处理。 - cost 列语义:仅按量计费模型有值;订阅/免费模型
cost=0但 token 计数真实。审计时$0 ≠ 零消耗,tokens_cache_read才是体量主力(常比 input 大 10 倍量级)。 - 日志:
%USERPROFILE%\.local\share\opencode\log;工具输出:%USERPROFILE%\.local\share\opencode\tool-output。
收集输入
接受以下任一作为起点:
- Session ID:
ses_... - 后台任务 ID:
bg_... - 消息或 part ID:
msg_...、prt_... - 工具描述/标题,如
Checks browser settings redirect - Worktree 或项目路径
- 端口、进程名、URL 或浏览器 session 名
若用户只给文字描述,先用特征子串搜索。工具描述常存储在 part JSON 内,可能不出现在常规 session 搜索结果中。
证据工作流
- 优先用高层 session API:
- 已知 ID 时用
session_info(session_id) - 用
session_search(query)搜索特征标题、工具描述、worktree 名、URL 或端口 - 已知项目/worktree 路径时用
session_list(project_path)
- 若高层 API 未命中或不一致,转向本地存储(路径与语义见上节「存储事实」)。
- 用 SQLite 识别真正的父/子 session 和工具 part(完整列清单见「SQLite 查询模式」):
session(id, parent_id, title, directory, agent, model, cost, tokens_*, time_created, time_updated)message(id, session_id, data)part(id, message_id, session_id, time_created, time_updated, data)
- 对每个可疑工具 part,提取:
status、exit、tool、description、command、workdir、timeout- 捕获的输出、stdout/stderr 和最后更新时间
- 同一消息周围匹配的
step-start/step-finishpart
- 推荐操作前先关联进程状态:
- 找到精确的工具进程 PID、父 PID、子 PID、命令行和创建时间
- 用拥有者 PID 检查相关端口
- 确认哪个进程拥有应用服务器 vs 卡住的工具
- 区分 OpenCode tool 进程 vs 应用 server(后者若由 long-running-process 启动,查
%TEMP%\opencode-long-running\*.json)
- 产出 writer 三态(供 recovery 消费;本 skill 不调用
task()续派):
- ACTIVE:已关联到仍存活且有进展(或合理 CPU/IO)的 writer/tool 进程
- INACTIVE:session/tool 已结束,或 running 状态无对应活进程(陈旧存储)
- UNKNOWN:DB/日志/进程树冲突,或无法关联 PID
- 仅在进程关联后,附加一种处置建议(仍不派发子代理):
- 无需操作:命令已完成且 session 状态已关闭
- 等待/重试:writer=ACTIVE 且在产生输出
- 精确清理:仅终止已证实的 OpenCode tool 孤儿进程树;应用 server 用
long-running-process的stop-background/cleanup-port - 提级:writer=UNKNOWN 且有数据丢失风险
脚本(优先于手写 SQL)
两个只读脚本覆盖最常见的取证场景,参数见各自文件头注释。PowerShell 调用:
会话检索 / 成本汇总 / 父子树重建(审计主工具):
node "<skill-dir>/scripts/query-sessions.mjs" --match webpath --since 2026-08-19 # 关键词+时间窗
node "<skill-dir>/scripts/query-sessions.mjs" --root ses_fe4fbef3 # 整棵会话树+成本总账(支持前缀)输出每行含 agent / cost / in / out / cacheR / 时长 / 开始时间 / 标题,末尾 TOTAL 行给出总成本与 token 体量。审计时先跑 --root 拿总账,再按 cost、dur、cacheR 排序找烧钱贡献者。
工具 part 时间线(卡住取证核心):
node "<skill-dir>/scripts/dump-session-parts.mjs" ses_fe2dd74 --last 10 # 支持会话 ID 前缀
node "<skill-dir>/scripts/dump-session-parts.mjs" ses_fe2dd74 --stuck # 只看未闭合工具 part每行含 状态 / exit / idle 分钟数 / 命令或描述摘要。--stuck 列出 status 非 completed/error 的工具 part——疑似卡住清单。
SQLite 查询模式
脚本不覆盖时用手写查询。session 表关键列:id, parent_id, title, directory, agent, model, cost, tokens_input/output/reasoning/cache_read/cache_write, time_created, time_updated。
查找 session:
select id, parent_id, title, directory, agent, model, time_created, time_updated
from session
where id = 'ses_TARGET'
or title like '%distinctive text%'
or directory like '%worktree-or-project%';列出子 session:
select id, title, agent, time_created, time_updated
from session
where parent_id = 'ses_PARENT'
order by time_created;检查目标 session 的工具 part:
select id, message_id, time_created, time_updated,
json_extract(data, '$.type') as type,
json_extract(data, '$.tool') as tool,
json_extract(data, '$.state.status') as status,
json_extract(data, '$.state.exit') as exit_code,
json_extract(data, '$.state.title') as state_title,
json_extract(data, '$.state.input.description') as description
from part
where session_id = 'ses_TARGET' and json_extract(data, '$.type') = 'tool'
order by time_created;按工具描述搜索 part JSON:
select session_id, message_id, id, time_created, time_updated, substr(data, 1, 1000)
from part
where data like '%distinctive tool description%'
order by time_updated desc;Windows 进程检查
用精确 PID 和命令行。不要按宽泛进程名终止。
$targets = @(60132,26560,35088)
Get-CimInstance Win32_Process |
Where-Object { $targets -contains $_.ProcessId } |
Select-Object ProcessId,ParentProcessId,Name,CreationDate,CommandLine |
Format-List
Get-NetTCPConnection -LocalPort 3104 -ErrorAction SilentlyContinue |
Select-Object LocalAddress,LocalPort,State,OwningProcess若清理有据,仅终止精确的孤儿工具 PID 树:
taskkill /PID <exact-tool-pid> /T /F立即验证工具 PID 消失且应用服务器 PID/端口仍存活。
报告格式
返回简洁报告,结构如下:
理由:一句话说明核心依据。
定位:
- 子会话:ses_...
- 父会话:ses_...
- 卡住 part:prt_...
- 工具/描述:...
证据:
- SQLite 状态:status=..., exit=..., updated=...
- 工具输出摘要:...
- 进程/端口:...
判断:
- 根因假设:...
- 不是哪些问题:...
建议:
- 最小安全动作:...
- 不要动:...常见错误
- 把工具描述当 session 标题。
session_search未命中时搜part.data。 - 只信 `session_read`。它可能失败,即使
session_info和 SQLite 有该 session。 - 在 `storage\session\` 的 JSON 里找近期会话。存储已迁移到 SQLite,JSON 停止更新;发现 mtime 陈旧即转向 DB。
- 在 PowerShell 里写 `node -e "..."` 内联查询。双引号与
$转义在 PowerShell 下层层嵌套必然出错;改写临时.mjs文件再node执行,或直接用本 skill 的 scripts。 - 把 `cost=$0` 当作零消耗。订阅/免费模型不计价但 token 真实;体量看
tokens_cache_read。 - 杀掉所有 `chrome.exe` 或所有 Playwright/浏览器自动化进程。始终先关联父/子 PID 和命令行。
- 杀掉卡住浏览器检查正在测试的应用服务器。清理前确认端口归属。
- 仅因捕获的输出看起来完整就认为 session 已解决。验证工具 part 有
statusclosed 和 exit code。


