Files
2026-06-30 10:38:52 +08:00

8.7 KiB
Raw Permalink Blame History

name, description
name description
cursor-debug-log 当需要调查 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 层随着请求穿过后端边界逐步落盘:

  1. BidiAppend 收到客户端上行数据。
    • 原始 hex 写入 bidi.raw.jsonl
    • 解码后的 known-schema protobuf 与后端提取出的 intent 写入 bidi.decoded.jsonl
  2. forwarder 把解码结果转成 active runtime state。
    • stream/request 状态决策写入 runtime.jsonl
  3. provider pass 被准备并执行。
    • adapter 前的请求摘要、model_call_idprovider_pass 等写入 provider.jsonl
    • provider artifact callback 追加最终 request/summary payload 到 provider.jsonl
  4. RunSSE 把后端输出流式发送给客户端。
    • 已发送消息、终态事件、发送错误、断连和 heartbeat 写入 runsse.jsonl

如果某条消息到达时后端还不知道 conversationId,早期事件可能写到 _debug/orphan/<requestId>/。后续一旦知道 conversationId,新事件应进入 history/<conversationId>/debug/。还原早期或乱序请求时,两处都要查。

Debug 文件含义

bidi.raw.jsonl

  • 方向:客户端到后端。
  • 包含 request_id、可选 conversation_idappend_seqnostatus、原始 data_hex
  • 当需要精确确认客户端上传字节时先看它。

bidi.decoded.jsonl

  • 方向:客户端到后端,protobuf 解码后。
  • 当前 schema v2 包含完整的 known-schema AgentClientMessage protojsonmessage
  • 同时包含后端从上行包提取出的 intent:intent,其中会展开相关 proto 子对象,例如 client_messageuser_messagerequest_contextconversation_state、exec/interaction/kv 回包等。
  • 还包含 message_caserequested_modelconversation_action 等检索索引;这些索引只方便搜索,不是完整证据本体。
  • 当需要确认后端如何理解客户端请求时看它。若要证明客户端原始上传字节,仍以 bidi.raw.jsonl 为准。
  • 旧二进制或旧日志可能只有 schema v1 摘要,未必展开 messageintent 里的完整字段。

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。

查询流程

  1. 先判断 id 类型。
    • 先查 history/<id>/state.json,确认它是不是 conversationId
    • 再在 history/*/{state.json,context.json}history/usage.jsonlogs/app.log 里搜索 request/model-call/tool id。
  2. 拿到 conversationId 后,列出 debug 目录。
    • ls -la "$HOME/.cursor-local-assistant-v2/history/<conversationId>/debug"
  3. 如果 debug 目录不存在,确认请求发生时 debug 是否已开启。
    • 读取 config.yaml
    • 对比 config.yamlstate.jsoncontext.json 的 mtime。
    • 搜索 logs/app.log 里的 config hot reload 或 provider start 记录。
  4. 按时间顺序读 JSONL,并用这些字段串联:
    • request_id
    • conversation_id
    • model_call_id
    • provider_pass
    • append_seqno
    • event timestamp
  5. 最终回复只总结结论所需字段。不要粘贴 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.jsonlmessage。例如 user_message.message_id、selected image、conversation state bytes 等字段是否在解码结果里。
  • 后端如何理解请求:看 bidi.decoded.jsonlintent,再接 runtime.jsonl
  • provider request 问题:看 provider.jsonl,尤其是 llm_request
  • UI/流式输出问题:看 runsse.jsonl
  • 请求状态问题:先看 state.jsoncontext.jsonusage.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.jsoncontext.jsonusage.jsonlogs/app.log,并把结论标成推断,而不是直接证明。