| name | cursor-debug-log |
| description | 当需要调查 Cursor 本地模式 debug/log 证据时使用:config.yaml 的 log 热加载、history/<conversationId>/debug JSONL 文件、Bidi 原始/解码记录、RunSSE 记录、runtime/provider debug 记录、debug 文件缺失原因,或解释这些 debug 文件如何生成与如何查询。 |
Cursor Debug Log
使用这个技能来解释和检查本地 debug log 体系。目标是在不修改已安装 Cursor 客户端、不依赖旧版 legacy artifact 的前提下,还原一次请求附近发生了什么。
作用定位
debug log 是本地模式请求链路的可选证据层。它和模型可见历史是分开的:
- 用来回答“客户端到底发了什么”。
- 用来回答“后端解码后认为这是什么请求”。
- 用来回答“哪些字段被挂到了当前 active request 上”。
- 用来回答“最终 provider request body 是什么样”。
- 用来回答“RunSSE 实际给客户端发送了什么”。
- 不要把它当成 replay history、prompt 输入或状态事实源。
稳定事实源仍然是:
history/<conversationId>/state.json
history/<conversationId>/context.json
history/usage.json
logs/app.log
debug 文件是在这些事实源之外,补充原始或近原始链路证据。
固定路径
- 助手根目录:
~/.cursor-local-assistant-v2
- 配置文件:
~/.cursor-local-assistant-v2/config.yaml
- history 根目录:
~/.cursor-local-assistant-v2/history
- app 日志:
~/.cursor-local-assistant-v2/logs/app.log
- 会话 debug 目录:
history/<conversationId>/debug/
- 孤儿 debug 目录:
history/_debug/orphan/<requestId>/
通过配置开启 debug logging:
log: true
当前实现会用轻量文件快照检查热加载 config.yaml。改完 log 后,预留大约 500ms,再期待下一次请求事件使用新值。旧二进制可能仍然需要重启。
文件如何生成
debug 层随着请求穿过后端边界逐步落盘:
BidiAppend 收到客户端上行数据。
- 原始 hex 写入
bidi.raw.jsonl。
- 解码后的 known-schema protobuf 与后端提取出的 intent 写入
bidi.decoded.jsonl。
- forwarder 把解码结果转成 active runtime state。
- stream/request 状态决策写入
runtime.jsonl。
- provider pass 被准备并执行。
- adapter 前的请求摘要、
model_call_id、provider_pass 等写入 provider.jsonl。
- provider artifact callback 追加最终 request/summary payload 到
provider.jsonl。
RunSSE 把后端输出流式发送给客户端。
- 已发送消息、终态事件、发送错误、断连和 heartbeat 写入
runsse.jsonl。
如果某条消息到达时后端还不知道 conversationId,早期事件可能写到 _debug/orphan/<requestId>/。后续一旦知道 conversationId,新事件应进入 history/<conversationId>/debug/。还原早期或乱序请求时,两处都要查。
Debug 文件含义
bidi.raw.jsonl
- 方向:客户端到后端。
- 包含
request_id、可选 conversation_id、append_seqno、status、原始 data_hex。
- 当需要精确确认客户端上传字节时先看它。
bidi.decoded.jsonl
- 方向:客户端到后端,protobuf 解码后。
- 当前 schema v2 包含完整的 known-schema
AgentClientMessage protojson:message。
- 同时包含后端从上行包提取出的 intent:
intent,其中会展开相关 proto 子对象,例如 client_message、user_message、request_context、conversation_state、exec/interaction/kv 回包等。
- 还包含
message_case、requested_model、conversation_action 等检索索引;这些索引只方便搜索,不是完整证据本体。
- 当需要确认后端如何理解客户端请求时看它。若要证明客户端原始上传字节,仍以
bidi.raw.jsonl 为准。
- 旧二进制或旧日志可能只有 schema v1 摘要,未必展开
message 和 intent 里的完整字段。
runtime.jsonl
- 方向:后端内部 runtime。
- 包含状态流转,以及挂到 active stream/request 上的字段。
- 当需要把 decoded input 和后续 provider 行为串起来时看它。
provider.jsonl
- 方向:后端到 provider adapter/provider。
- 包含 provider pass 元数据、
model_call_id、request knobs、最终 provider request artifact、provider summary artifact。
- 当最终出站 provider body 或 provider summary 是关键证据时看它。
runsse.jsonl
- 方向:后端到客户端。
- 包含解码后的
AgentServerMessage 发送、终态事件、发送错误、断连和 heartbeat。
- 用来检查后端尝试返回给客户端的内容。它是解码后的消息证据,不是原始 HTTP/SSE framing。
查询流程
- 先判断 id 类型。
- 先查
history/<id>/state.json,确认它是不是 conversationId。
- 再在
history/*/{state.json,context.json}、history/usage.json、logs/app.log 里搜索 request/model-call/tool id。
- 拿到
conversationId 后,列出 debug 目录。
ls -la "$HOME/.cursor-local-assistant-v2/history/<conversationId>/debug"
- 如果 debug 目录不存在,确认请求发生时 debug 是否已开启。
- 读取
config.yaml。
- 对比
config.yaml、state.json、context.json 的 mtime。
- 搜索
logs/app.log 里的 config hot reload 或 provider start 记录。
- 按时间顺序读 JSONL,并用这些字段串联:
request_id
conversation_id
model_call_id
provider_pass
append_seqno
- event timestamp
- 最终回复只总结结论所需字段。不要粘贴 secret、API key、完整 provider body 或大段原始 payload。
常用命令:
ROOT="$HOME/.cursor-local-assistant-v2"
REQ="<requestId>"
CONV="<conversationId>"
rg -n "$REQ" "$ROOT/history" "$ROOT/logs/app.log"
find "$ROOT/history" -path "*/debug/*" -type f | sort
rg -n "$REQ|model_call_id|provider_request_prepared|llm_request" "$ROOT/history/$CONV/debug"
紧凑查看 JSONL:
jq -c 'select(.request_id == "<requestId>")' "$ROOT/history/$CONV/debug/provider.jsonl"
jq -c 'select(.request_id == "<requestId>") | {append_seqno, message_case, conversation_action, message, intent}' "$ROOT/history/$CONV/debug/bidi.decoded.jsonl"
证据怎么用
根据问题选择对应文件:
- 客户端原始上行问题:先看
bidi.raw.jsonl。这是精确原始包证据。
- 客户端 known-schema 字段问题:看
bidi.decoded.jsonl 的 message。例如 user_message.message_id、selected image、conversation state bytes 等字段是否在解码结果里。
- 后端如何理解请求:看
bidi.decoded.jsonl 的 intent,再接 runtime.jsonl。
- provider request 问题:看
provider.jsonl,尤其是 llm_request。
- UI/流式输出问题:看
runsse.jsonl。
- 请求状态问题:先看
state.json、context.json、usage.json,再用 debug 文件补证。
- debug 缺失问题:看
config.yaml、mtime、app log、orphan debug 目录。
runtime model parameters,例如 thinking strength,只是 provider request 证据的一类例子:
bidi.raw.jsonl 说明客户端原始上传了什么。
bidi.decoded.jsonl.message 说明上行包按当前 known schema 解码出了什么。
bidi.decoded.jsonl.intent 说明后端从 decoded input 里提取并准备使用了什么。
runtime.jsonl 说明后端把什么挂到了请求状态上。
provider.jsonl 说明最终为 provider 准备了什么。
只有普通 history 时不要过度断言。例如 context.json 里的 reasoning_content 能说明产生过 reasoning 文本,但不能单独证明是哪一个 runtime parameter value 导致的。
注意证据边界:
bidi.decoded.jsonl 使用当前已知 proto schema 做解码。未知字段或原始 framing 差异不能靠 decoded 证明,必须回到 bidi.raw.jsonl。
context.json 仍是持久化历史事实源;debug 文件只能证明某次请求链路附近发生过什么。
provider.jsonl 的 provider body 和 bidi.raw.jsonl / bidi.decoded.jsonl 都可能很大,回复用户时只摘必要字段,不粘贴完整图片、完整 body 或 secret。
Debug 文件缺失
如果某个 request 没有 debug 文件,要明确说明“没有直接 debug 证据”。常见原因:
- 请求发生时
log: false。
- 正在运行的二进制版本早于 debug logging 或 hot reload 实现。
- 事件发生时还没有解析到 conversation id,记录在
_debug/orphan/<requestId>/。
- 请求在开启
log 前已经完成。
- 写文件失败;如果该版本有相关记录,app log 里可能有 warning。
debug 证据缺失时,回退到 state.json、context.json、usage.json、logs/app.log,并把结论标成推断,而不是直接证明。