Uh oh!
There was an error while loading. Please reload this page.
fix(plugin-chatbot): parseAiQuotaError 先学会嵌套声明信封(三方言全部可读)(#3491) - #3802
Conversation
…r envelope (#3491) The two cloud AI 429 producers fill the same `error` key in opposite ways (the token guardrail puts the code there, service-ai puts the message there and the code in a `code` sibling), while ADR-0112 declares a third shape both converge on: `{ success: false, error: { code, message } }`. The consumer has to learn the declared shape first, or the producers' convergence silently turns every quota refusal back into a generic "Response failed" banner (cloud#944; same consumer-first sequencing as objectui#2992). Code lookup is a total order — declared envelope, flat guardrail code, `code` sibling — so a transitional producer double-emitting the new envelope next to the legacy top-level keys has one defined outcome. Only the code's location widens: the recognized code set is unchanged and any unrecognized shape still degrades to null. Companion fields keep their top-level read; their position in the declared envelope is not presumed (cloud#1168 fixes the real shape). Tests: three dialects x hit/miss, unknown-shape degradation, companion-field backward compatibility, and the parse-priority order. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
The latest updates on your projects. Learn more about Vercel for GitHub. |
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
yinlianghui
commented
Aug 8, 2026
✅ 验收通过(objectui 分片 PM,session_01GTRjn8xBqp75dk7kFupVRt)—— undraft + auto-merge。 git 实物核验( 验收要害采纳并转录:#3804(finding)记录的词汇缺口 —— 三个 AI 配额 code 在 ADR-0112 封闭值域外,合规嵌套信封今天装不下它们;本单只接住「新形态+旧词汇」的过渡期生产者。 Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#3491
Part of objectstack-ai/cloud#944 —— 消费端先行;本单落地后 cloud#1168(生产者按 ADR-0112 收敛)才可动。⛔ 本 PR 不改任何生产者、不动 cloud 仓。
为什么消费端必须先行
两个 AI 配额 429 生产者用相反的方式填同一个
error键(guardrail 塞 code,service-ai 塞 message、code 放在code兄弟键),而 ADR-0112 声明的是第三种:{ success:false, error:{ code, message } }。parseAiQuotaError今天只认「平铺error就是 code」这一种,生产者一旦按声明收敛,配额拒绝会静默失配、退回通用的「Response failed」红条 —— 与 objectui#2992(useAgents 先学信封、服务端再转)同一套路。改动(
packages/plugin-chatbot/src/tool-display.ts)parseAiQuotaError现在在三个位置找 code:嵌套声明形error.code、平铺error、兄弟键code。ai_design_quota_exhausted/ai_data_chat_trial_exhausted/ai_allowance_exhausted)一字未动,任何未知形状仍降级为现状行为(null),因此不会有非配额错误被新捕进配额 CTA。error.message→ 平铺message→ (仅当error不是 code 槽时)error里的散文。service-ai 方言的 message 就在error里,而平铺方言的error是 code —— 后者绝不能当 message 显示给用户,这个 gate 由测试钉住。upgrade/topUp/messageEn)保持既有的顶层读取,嵌套位置不预设(是error.details.upgrade?还是error.code的兄弟?)—— 那是 cloud#1168 决定的形状,现在编一个嵌套键出来等于把没人同意过的契约固化下来(AGENTS.md #0.1)。asAiQuotaCode(值域判定)、asText(空串不算 message,因为{ error:'', code:… }方言正好发空串)。三方言 × 命中/不命中矩阵(实跑)
pnpm vitest run packages/plugin-chatbot/src/tool-display.test.ts→ Test Files 1 passed / Tests 30 passed;整包pnpm vitest run packages/plugin-chatbot→ 17 files / 272 tests passed;pnpm --filter @object-ui/plugin-chatbot type-check干净通过。error是 code)error:'ai_quota_exhausted'→ nullcode兄弟键)error散文当 messagecode:'ai_quota_exhausted'→ nullcode:'QUOTA_EXCEEDED'→ null;error无 code → null另有:未知形状降级(
error:null/error:[]/code:42/ 非 JSON)、伴随字段向后兼容(嵌套 code + 顶层 upgrade/topUp/messageEn 双发)、嵌套-only 时 CTA flag 落 false、以及嵌套在外层文本/数组里的 body 仍能被定位(既有 substring 抽取行为,顺手钉住)。解析优先级依据
嵌套声明形 > 平铺 code > 兄弟 code,是一条全序,不是「先试哪个都行」:过渡期生产者新信封与旧顶层键双发是很现实的一步,同时命中两形态时必须只有一个确定结果,所以最「声明」的位置优先;而嵌套 code 缺失或不在值域时,旧 limb 仍然可达(测试里QUOTA_EXCEEDED嵌套 + 顶层旧 code 就落到旧 limb)。反向验证(方向先判后跑,两次都对上)
一个必须记下的剩余缺口(本单不动手,交 PM/维护者定)
ADR-0112 的
error.code值域是封闭z.enum(ErrorCode=StandardErrorCode∪ERROR_CODE_LEDGER,SCREAMING_SNAKE,由error-code-ledger.test.ts机械强制),而这三个配额 code 在 ledger 里零登记(git grepoverorigin/mainpackages/spec/src零命中)。也就是说:一个真正合规的嵌套信封今天装不下ai_allowance_exhausted——ApiErrorSchema.parse会拒。所以本 PR 的嵌套分支只对「嵌套形 + 旧小写词汇」的生产者生效;cloud#1168 若把词汇一并收敛(登记AI_*,或按 ledger 自己的建议直接用标准的QUOTA_EXCEEDED把三态与 CTA flag 挪进details),objectui 这边还需要一次词汇对齐的后续小 PR。那是契约决策,不该由我猜 —— 已写进 JSDoc 与 dev 报告的 open_questions。顺带更正 issue 描述里的一处:
parseAiQuotaError并非「今天无仓内生产调用方」——ChatbotEnhanced.tsx有两处活调用(:2781的红条抑制、:3790的配额 CTA)。核心前提(只认平铺error-as-code)经origin/main实读成立,tool-display.ts:197一带确如描述。Generated by Claude Code