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

5.7 KiB
Raw Blame History

Provider replay / debug

当现象是 provider 返回错误、SSE 里只有 event: error、需要确认最终出站 provider body 是否能被独立复现时,优先读这份参考。

这套流程只用于还原“后端最终发给 provider 的请求形状”和“provider 对该请求的真实响应”。它不是语义 history,也不是客户端输入事实源。

证据边界

  • history/<conversationId>/debug/provider.jsonl
    • 最接近 provider 出站边界。
    • event=llm_requestpayload.body 是最终 provider request body。
    • 用它做 curl replay,判断问题是否已经出现在出站请求形状。
  • history/<conversationId>/state.json
    • 当前状态和最近 provider 摘要。
    • 重点看 latest_request_prefixlast_provider_call
  • history/<conversationId>/context.json
    • replayable 语义历史。
    • 用来解释为什么会形成这次 prompt,不用来直接重放 provider HTTP 请求。
  • history/<conversationId>/debug/bidi.raw.jsonl
    • 客户端原始上行字节证据。
  • history/<conversationId>/debug/bidi.decoded.jsonl
    • 当前 known-schema 解码后的客户端上行证据。
  • history/<conversationId>/debug/runtime.jsonl
    • 后端把哪些字段挂到 active request / stream 上。
  • history/<conversationId>/debug/runsse.jsonl
    • 后端尝试发回客户端的消息。

不要把这些证据混用:provider replay 只能证明最终 provider HTTP 请求与响应,不能单独证明客户端原始上传了什么,也不能替代 context.json 的语义历史。

前置条件

  • 请求发生时 config.yamllog: true,或已有 history/<conversationId>/debug/provider.jsonl
  • 已经通过 id 反查拿到:
    • conversationId
    • requestId
    • modelCallId
  • 已经确认要测的是 Anthropic-compatible /v1/messages 请求。

如果没有 debug 文件,先回到 state.jsoncontext.jsonusage.jsonlogs/app.log 做推断,并明确“没有直接 provider body 证据”。

最小流程

  1. 定位 provider debug 文件:
ROOT="$HOME/.cursor-local-assistant-v2"
CONV="<conversationId>"
REQ="<requestId>"
MODEL_CALL="<modelCallId>"
REQUEST_LOG="$ROOT/history/$CONV/debug/provider.jsonl"
  1. 确认 llm_request 存在:
jq -c --arg req "$REQ" --arg mc "$MODEL_CALL" '
  select(.event == "llm_request" and .request_id == $req and .model_call_id == $mc)
  | {at, conversation_id, request_id, model_call_id, provider: .payload.provider, model: .payload.body.model}
' "$REQUEST_LOG"
  1. 执行通用重放脚本:
REQUEST_LOG="$REQUEST_LOG" \
REQUEST_ID="$REQ" \
MODEL_CALL_ID="$MODEL_CALL" \
CHANNEL_NAME="GLM" \
OUT_DIR="/tmp/cursor-provider-replay-$REQ" \
.agents/skills/cursor-client-e2e-debugging/scripts/provider-replay.sh

也可以直接传入 provider 配置,避免读取 config.yaml

REQUEST_LOG="$REQUEST_LOG" \
REQUEST_ID="$REQ" \
MODEL_CALL_ID="$MODEL_CALL" \
BASE_URL="<provider-base-url>" \
API_KEY="<provider-api-key>" \
OUT_DIR="/tmp/cursor-provider-replay-$REQ" \
.agents/skills/cursor-client-e2e-debugging/scripts/provider-replay.sh
  1. 查看产物:
  • request.body.json:抽取出的最终 provider body。
  • response.headersHTTP 响应头。
  • response.sseSSE 响应体。
  • replay.meta.json:本次重放引用的 id 和 provider log 路径。

结果判断

  • curl_exit_code != 0
    • 网络、TLS、超时、连接或本机 curl 问题。
    • 先看 stderr、response.headers 是否存在,再判断是否真的到达 provider。
  • HTTP 非 2xx
    • provider 网关或鉴权层拒绝。
    • 优先看 response.headers 和 provider 错误体。
  • HTTP 2xx 但 SSE 中有 event: error
    • provider 已接受连接,但认为请求参数不合法或模型侧拒绝。
    • 这种情况下重点比对 request.body.json 的消息结构、tool schema、thinking/reasoning 参数、model 名称和 endpoint 兼容性。
  • SSE 正常流式输出
    • 原始 provider 请求形状基本可用。
    • 如果客户端仍失败,回到 runsse.jsonl、forwarder 状态机或客户端协议层继续查。

常见收敛方向

provider 参数错误时,优先检查:

  • model 是否是目标 endpoint 支持的名称。
  • messages 是否符合 Anthropic-compatible 形态。
  • system 是否被目标 provider 支持,或需要改成 message。
  • tools / tool_choice 是否符合目标 provider 方言。
  • thinking / reasoning 字段是否被目标 provider 支持。
  • 图片、文件、cache_control、metadata 等扩展字段是否超出 provider 兼容范围。
  • max_tokenstemperaturetop_pstop_sequences 是否落在 provider 允许范围内。

敏感信息规则

  • 不把 API key 写进 skill、reference、脚本默认值或提交内容。
  • 回复用户时不要粘贴完整 API key;最多说明“已使用用户提供的 key / config 中的 key”。
  • 不把完整 request.body.json 大段贴给用户;只摘和结论相关的字段形状。
  • 不把一次性 conversationId/requestId/modelCallId 写进 skill 文档。
  • 临时 replay 产物默认放 /tmp;如果需要保留,明确说明路径和原因。

脚本参数

scripts/provider-replay.sh 使用环境变量控制:

  • 必填:
    • REQUEST_LOG
    • REQUEST_ID
    • MODEL_CALL_ID
  • 可选:
    • BASE_URL
    • API_KEY
    • GLM_BASE_URL
    • GLM_API_KEY
    • ANTHROPIC_BASE_URL
    • ANTHROPIC_API_KEY
    • CONFIG_FILE,默认 ~/.cursor-local-assistant-v2/config.yaml
    • CHANNEL_NAME,默认 GLM
    • OUT_DIR,默认 /tmp/cursor-provider-replay-<requestId>
    • MAX_TIME,默认 240
    • ENDPOINT_PATH,默认 /v1/messages

脚本输出四个稳定产物:

  • request.body.json
  • response.headers
  • response.sse
  • replay.meta.json