Repository navigation
docs(#1445): Exa MCP 失败信号实读 —— 票面那一种响应没有可消费的结构化信号 - #1452
Merged
Merged
Conversation
修「额度提示被当成搜索结果」之前只有一个问题要答:怎么判别「这是一段错误提示」 而不手写 Exa 的文法。实读端点本体(请求与生产 call() 逐字同形),量到四种形状: - 正常结果:200 + content[0]._meta.searchTime,27/27; - Exa 自己的 in-band 错误:200 + isError:true 且 content[0] 没有 _meta,4/4; - 免费额度用尽(今天):429 + JSON-RPC error + retry-after/x-ratelimit-*,43/43, 含五种 accept 头变体 —— 这一种生产已经响亮失败; - 票面那一种(2xx + result + 未置 isError):本轮 0 次。 对票面那一种,可消费的结构化信号逐个点名后都不成立:isError 可由生产代码反推为非真、 JSON-RPC 是 result 不是 error、HTTP 2xx、两个工具在 tools/list 里都没声明 outputSchema。 唯一还站着的候选 content[0]._meta 有两处站不住:它的失败臂从没被观测过(拿它当闸就得先 假设票面负载不带 _meta,再用这个假设去判它,期望值与被测对象同源),以及它会把一个 无契约的 vendor 字段变成致命前提(不成立时闸门拒载的是真实结果)。 所以本次不落闸,只落勘破,判据交裁决。 顺带量到、不属于本轮:packages/core 那份 V2 副本缺整层 E7 收口(McpResult 不含 isError、 读不出就返回 undefined 再换成 NO_RESULTS 伪成功串、filterStatusOk 压掉全部非 2xx)—— 把今天抓到的真实 isError:true 负载喂进去,opencode 判失败而 core 判成功。 Refs #1445 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #1445
这个 PR 不修 bug。 它落的是修之前必须先答的那一问的答案,以及一个要裁决的判据缺口。
#1445票面自己写着:「有结构化信号 ⇒ 消费它;没有 ⇒ 明说没有,把可选方案与代价摆出来交裁决,不要退回关键字匹配当默认解」。实读之后落在第二条,所以这里用
Refs不用Fixes。先答那一问
「这是一段错误提示」有没有结构化信号可消费?对票面那一种响应,没有。
实读
https://mcp.exa.ai/mcp本体(请求与packages/opencode/src/tool/mcp-websearch.ts的
call()逐字同形),2026-09-24 11:34–11:46Z:isErrorcontent[0]._metaresult{searchTime}resulttrueprovider_error,响亮(对)error-32000unexpected_status,响亮(对)result对 D 逐个点名:
isError可由生产代码反推为非真;JSON-RPC 是result不是error;HTTP 2xx(所以
#489/E7「非 2xx 一律 LOUD」那条管不到它);tools/list实读两个工具都没声明
outputSchema⇒structuredContent不构成成功判据。唯一还站着的候选是
content[0]._meta—— 但 D 那一格从没被观测过。bytes校验:票面记录bytes: 246,head被截到 240 字;补回尾部 6 字得YOUR_EXA_API_KEY,长度逐字等于 246,前 240 字与记录逐字相同。负载与反推过程都在
docs/verification/2026-09-24-1445-exa-mcp-response-shapes/results/ticket-payload.json。要裁决的
选项 1 —— 不落闸,只落勘破(本 PR)。 代码零改动。代价:D 若再出现,仍会以结果的形状到达模型;
今天它到不了(Exa 走 429),但那是 Exa 的当前版本决定的,不是我们的闸决定的。可逆,随时能在勘破之上加闸。
选项 2 —— 消费
content[0]._meta(「没有 provider 元数据的块不算搜索结果」)。两份副本各写一份 + 一条钉住不漂的判据。只有 D 确实不带
_meta时它才解决#1445,而那一格没人量过。两处站不住:① AC2 做不到 —— 我得先拼一个不带
_meta的 envelope,再用「没有_meta即失败」判它,期望值与被测对象同源;② 它把一个无契约的 vendor 字段变成致命前提,Exa 哪天不发
_meta,闸门拒载的就是真实结果,本地搜网整条断掉(响亮,但不可用)。
REQ-127为同一形态付过账。选项 3 —— 关键字匹配。 票面与
CLAUDE.md明令禁止(#123/#36一夜十四轮)。列在这里只为说明它被评估过并拒绝,不是漏了。
选项 4 —— 先把 D 的 envelope 取到再设计。 在传输层加一条只记录、不判决的诊断:
2xx +
result时记一行「isError在不在 /structuredContent在不在 /content[i]._meta有哪些键 /限流类响应头」(不含正文)。下一次 D 出现,缺的那一格就有了。不解决 bug,只把「未知」变成「下次可知」。
我的推荐:选项 1,并把「拿到 D 的 envelope」列为
#1445的前置。 理由:今天 D 在用户面上到不了;唯一能修它的判据缺的正是 D 的那一格;在缺那一格时落闸,要么空转(D 带
_meta),要么把致命前提押在vendor 字段上。拖着的代价:Exa 若改回去,这个 bug 会静默回来 —— 选项 4 的那一行日志正是为这个代价买的保险。
顺带量到、没有顺手改的
packages/core/src/tool/websearch.ts那份 V2 副本完全没有 E7 的那层收口。McpResult(:148)不含isError;parseResponse(:171)读不出返回undefined;调用方(
:312)把它换成NO_RESULTS(:68,一句编造的「没有结果」);出网用
HttpClient.filterStatusOk(:229)把全部非 2xx 压成不可辨的错误。实测(
results/parsers-before.txt):把今天抓到的 B 臂真实负载(isError: true的 401)喂进去,packages/opencode判失败,packages/core判成功,并把那句 401 原文当搜索结果交给模型。这是同一个「伪成功」类的另一个实例,触发条件与
#1445不同 ⇒ 按边界不顺手改,开不开票是主 session 的事。web_search_exainputSchema必填objective且additionalProperties: false,而两份生产副本都不发它(发的是
type/livecrawl/contextMaxCharacters)。今天服务端仍宽松接受;哪天不接受,两条腿同时坏。我没有旧 schema 快照,所以「Exa 改过」是推测不是实读。
alpha分支 tip 本身是红的,与本 PR 无关。 见下。本地门
bash scripts/alpha-check.sh,worktree.worktrees/1445-exa-fake-success(已 bootstrap,electron/dist与alpha_fence.node两个未追踪产物均已补齐)。57646831b,零改动)fail-set = 1:packages/ui-mac/src/main/mcp-server-derivation.test.ts :: #1381 端到端…,期望
X-Token: "t"实得"***"。根因是本次上游 sync 带进来的82d4c8903 fix(opencode): redact credentials in debug config (#50956)——git merge-base --is-ancestor 82d4c8903 d287d7471答 NO ⇒ 它随57646831b进入 alpha。整条 alpha 现在 push 不了,不只是这条 lane。
docs/(9 个文件,+599/-0;git diff --name-only origin/alpha HEAD对
^packages/零命中,其中两个是探针脚本,不进构建、不被 typecheck 覆盖),与 base fail-set 逐条相同,零新增红。
完整输出在 PR 讨论区的下一条评论里。
文档影响
docs/architecture/2026-09-24-exa-mcp-failure-signal-recon.md—— 勘破结论(CLAUDE.md《勘破先于闸门设计》第 1 条要求的对照物);
docs/verification/2026-09-24-1445-exa-mcp-response-shapes/—— 探针 + 原始输出 + 票面负载夹具;docs/README.md—— 两行索引。🤖 Generated with Claude Code