Files
cursor-byok/.agents/skills/cursor-client-e2e-debugging/references/backend-store-log-tracing.md
T
2026-06-30 10:38:52 +08:00

7.5 KiB
Raw Blame History

backend/store 日志反查

当用户只给一个 id,或明确让你从本地记录里反查一次请求、会话、模型调用、工具调用或 provider 错误时,优先读这份参考。

当前固定路径

当前用户机器上的固定助手根目录:

  • ~/.cursor-local-assistant-v2

当前最关键的是三类内容:

  • history/<conversationId>/state.json
    • 会话元数据与当前状态。
    • 重点字段:request_id conversation_idroot_conversation_idparent_conversation_idparent_tool_call_idmodecurrent_loop_statuscurrent_request_idcurrent_turn_seqcontext_versionnext_turn_seqnext_entry_seqlatest_request_prefixlast_provider_callcurrent_todoscurrent_plans、token / compaction 字段。
  • history/<conversationId>/context.json
    • append-only 语义历史。
    • 重点字段:versionitems[]
    • items[] 中每个 entry 通常有 seqturn_seqrequest_idrolekindtool_call_idparent_tool_call_idpayloadcreated_at
  • history/usage.json
    • provider call 与 turn usage 聚合。
    • 重点字段:totalsdailyrecent_eventsevent_index

logs/app.log 是运行日志;它只用于补充运行时证据,不是会话事实源。

当前实现不再支持:

  • DB-backed store / searchable conversation memory
  • HTTP/protocol trace debug UI
  • data/data.sqlite / protocol_traces
  • history/<conversationId>/conversation.json
  • history/<conversationId>/turns/<n>/request.json|sse.jsonl|summary.json
  • 根目录或会话目录下的旧 latest.jsonsummary.jsonreplay.jsonruntime.jsonrequest.jsonrecovery.jsonentries.jsonl、数字 turn 目录

这些旧产物会被 internal/backend/forwarder/history_maintenance.go 清理。不要把它们当成当前事实源。

用户发来一个 id 时的固定步骤

1. 先判断 id 类型

不要先假设它是 requestId。按这个顺序缩小范围:

  1. 是否是 conversationId
    • 检查 history/<id>/state.jsonhistory/<id>/context.json 是否存在。
  2. 是否是 requestId
    • history/*/state.json 中查 current_request_idlatest_request_prefix.request_idlast_provider_call.request_id
    • history/*/context.jsonitems[].request_id 中查。
    • logs/app.log 中查。
  3. 是否是 modelCallId
    • state.json 中查 latest_request_prefix.model_call_idlast_provider_call.model_call_id
    • context.json.items[].payload 中查 model_call_id
    • logs/app.log 中查 model_call_id=<id>
  4. 是否是 toolCallId / exec_id
    • context.json.items[].tool_call_iditems[].payload 中查。
    • 在协议/工具相关日志中查。

可以用本地脚本或 rg 做只读反查。不要再用 SQLite 查询模板。

2. 拿到 conversationId 后看两份事实源

HISTORY_ROOT="$HOME/.cursor-local-assistant-v2/history"
CONV_ID="<conversation-id>"

ls -la "$HISTORY_ROOT/$CONV_ID"

重点检查:

  • state.json
    • current_loop_statusidlerunningwaiting_toolcompletedcanceledprovider_errorfailed
    • current_request_idcurrent_turn_seq
    • latest_request_prefix:最近一次 provider 请求的 provider/model/openai_endpoint/model_call_id/prompt token 摘要
    • last_provider_call:最近 provider 状态与错误文本
    • next_entry_seqnext_turn_seqcontext_version
    • current_todoscurrent_plans
  • context.json
    • version 是否与 state.context_version 对齐
    • items[] 是否按 seq 稳定递增
    • 同一 turn_seq 下是否有预期的 user/request_context/prompt_context/assistant/tool_result/metadata entries
    • 是否有重复、缺失或顺序异常
  • usage.json
    • 通过 event_indexrecent_events 查 request/model-call 相关 usage
    • totals.cache_read_tokens / (totals.cache_read_tokens + totals.input_tokens) 可粗略看 cache hit

3. Provider 调用证据现在在哪里

当前 provider artifact recorder 的行为:

  • RecordLLMRequest(...)
    • 只缓存当前 provider call 的请求摘要。
    • 如果 payload 可解析 provider/model/openai_endpoint,会更新 state.latest_request_prefix
    • 不再写 request.json
  • AppendLLMResponseChunk(...)
    • 当前是 no-op。
    • 不再写 sse.jsonl
  • RecordLLMSummary(...)
    • 只补齐当前 provider call summary,并更新 state.latest_request_prefix.prompt_tokens_total
    • usage 聚合写入 history/usage.json
    • 不再写 summary.json

所以 provider 错误排查应优先看:

  • state.last_provider_call
  • state.latest_request_prefix
  • context.json.items 里的 metadata/provider_error/turn_completed 等 payload
  • history/usage.json
  • logs/app.log
  • internal/backend/agent/model/openai.go / anthropic.go 的请求构造和错误解析

这些文件是怎么生成的

根路径

  • internal/appdata/paths.go
    • RootDir() 固定为 ~/.cursor-local-assistant-v2
    • HistoryRootPath()~/.cursor-local-assistant-v2/history
    • UsageFilePath()~/.cursor-local-assistant-v2/history/usage.json
    • LogsRootPath()~/.cursor-local-assistant-v2/logs

state.json + context.json

来源链路:

  • internal/backend/forwarder/file_store.go
    • CreateConversation
    • LoadConversation
    • AppendEntries
    • SaveConversationWithEntries
    • UpdateConversationMeta
    • ReplaceEntries
  • internal/backend/forwarder/service.go
    • handleRunIntent 开始新 loop / turn
    • appendConversationEntries 追加语义事件
  • internal/backend/forwarder/projector.go
    • ProjectPromptReplay()context.json.items 投影为 provider messages

稳定结论:

  • state.json 是当前状态和可变元数据。
  • context.json.items 是 replayable 语义历史。
  • 发给 LLM 的历史由 projector 从 context.json.items 投影,不是从 provider artifacts 重放。
  • state.json.entries 只是内存结构 ConversationFile 的字段;落盘时可投影历史在 context.json.items

usage.json

来源链路:

  • internal/backend/forwarder/usage_store.go
    • UsageFileStore.UpsertEvent
    • UsageFileStore.LookupEvent
  • internal/backend/forwarder/token_usage.go
  • internal/historymetrics/

稳定结论:

  • usage.json 是全局 usage 聚合,不属于单个 conversation 的语义历史。
  • recent_events 只保留最近有限数量事件;长期总量看 totals / daily

legacy 清理

来源链路:

  • internal/backend/forwarder/history_maintenance.go

稳定结论:

  • turns/conversation.jsonentries.jsonlrequest.jsonsummary.json 等都是 legacy artifact。
  • 启动后的 history maintenance 会清理这些旧产物。

快速判断规则

  • 用户只发一个 id 时,先查 history/<id>/state.json 是否存在;不存在再扫 state.json/context.json/logs
  • 请求失败时,先看 state.last_provider_callcontext.json.items 的错误 metadata、logs/app.log;不要找 turns/<n>/summary.json
  • pending / 工具不收口时,先看同一 turn_seq 的 tool call 和 tool result entries,再对照协议上行 exec_client_message / exec_client_control_message / interaction_response
  • prefix cache 异常时,先看 context.json.items 的稳定追加顺序和 usage.json 的 cache token 字段。
  • 如果 history 与日志冲突,优先相信当前仍在更新的 state.json/context.json,再用日志解释运行时经过了哪条路径。