Repository navigation
RFC-0039: ops、FFI 与八种绑定契约 - #209
Conversation
There was a problem hiding this comment.
注:文中“V4 层”的代码位置,以及未注明 master 的 aimux 路径和行号,均以 #256 的提交 65ca6be 为准(#249–#256 按顺序叠放,这个提交包含全部各层):https://github.com/arcships/aimux/tree/65ca6be74515374ea89eb4f25717b4ac42ca2911
| "kind": "aimux", | ||
| "code": 11, | ||
| "message": "API call failed", | ||
| "error": {"type": "api-call", "message": "rate limited", "statusCode": 429}, |
There was a problem hiding this comment.
§6.1 有三处想先和你确认(错误 JSON 形状的统一我们决定暂缓,放到新 ABI 那几层一起做):
- 判别字段:示例用 "error": {"type": "api-call", ...}(第 290 行),上游 AI SDK 的错误以 name 区分,例如 "AI_APICallError"(@ai-sdk/provider@4.0.19 src/errors/api-call-error.ts:3;ai@7.0.122 src/util/retry-error.ts:3),master 上的错误 JSON 还是 0.5 的形状({"ApiCall": {...}},aimux-core/tests/error_value_golden_test.rs:35),V4 的公共 JSON 那一层([8/8] refactor!: public JSON equals the AI SDK JSON #256)改成了按上游的 name 区分(https://github.com/arcships/aimux/blob/65ca6be74515374ea89eb4f25717b4ac42ca2911/aimux-core/tests/error_value_golden_test.rs#L36)。信封里的 error 最终用 name 还是 type?第 296 行说完整联合归 RFC-0042,但 RFC-0042: V4 类型边界与统一生成 #212 没有错误联合这一节,也想确认由哪份 RFC 定义。
- “HTTP 状态只在实际观察到响应时提供”(第 301 行):上游对 200 响应中的流内 error 帧会推断状态码,OpenAI 把 rate_limit 推成 429、authentication 推成 401,其余默认 500(@ai-sdk/openai@4.0.80 src/openai-stream-error.ts:192、:235-260);ai 的 StreamProviderError.statusCode 也注明是可推断的“HTTP-equivalent”(ai@7.0.122 src/error/stream-provider-error.ts:23-27,overloaded → 503)。我们按上游移植了 OpenAI 这段(aimux-providers/src/openai/mod.rs 的 openai_stream_error)。建议区分“观察到的状态”和“由错误帧推断的状态”,并确认 TokenExpired 可以带它来源的 401(aimux-core/src/error.rs 的 status_code)。
- 码值:第 299 行写“保留 AiMux 1–17,新增由 manifest 分配”,但 manifest 还没有,V4 层里已在 17 之后加了 18 NoOutputGenerated、19 LoadApiKey、20 LoadSetting(aimux-ffi/src/lib.rs:452、:457-458)。能否把这三个登记进来,或说明由 manifest 接管?
|
|
||
| ### 5.3 有界背压 | ||
|
|
||
| 当前切换默认预算:音频输入最多 64 项且最多 8 MiB;输出 data 队列最多 256 项且最多 8 MiB;单个事件/音频块最大 1 MiB;先达到任何限制即背压。Node/Python 可保留更小的 64 项桥接队列,但总字节上限与终结规则一致。允许显式降低限额,不允许“无限”配置。 |
There was a problem hiding this comment.
§5.3 的“单个事件/音频块最大 1 MiB”和“超大单项在分配前返回 ResourceLimit”(第 273、275 行)会把一个已经修掉的缺陷带回 FFI 层。#200 的影响面地图把旧 SSE 单事件 1 MiB 上限列为 as:STREAM-1:Gemini 流式图片、Responses 的 response.completed 等合法事件超过 1 MiB,本应成功的请求因此失败(docs/aisdk-architecture-impact-map.md:558);master 上的 #213 已按上游去掉了 SSE 上限(aimux-stream/src/sse.rs:19;上游 parseJsonEventStream 不设 maxBufferSize,@ai-sdk/provider-utils@5.0.51 src/parse-json-event-stream.ts:20)。这类数据在 FFI 流里是单个 data 事件:file part 的内容内联在事件里(aimux-core/src/result.rs 的 GeneratedFile),includeRawChunks 下的 raw 事件也是整块原始事件,按 1 MiB 上限会以 ResourceLimit 失败。
建议:单事件不设固定 1 MiB 上限,改为按字节计的队列背压(总字节上限可以保留);如果一定要有单事件上限,至少高于录制 fixture 中最大的事件并留出余量,数值仍交给 RFC-0038 核定。
| | `auth.codexRefresh` | G | 既有 refresh 输入;不记录 token、不自动重试 | call → token 结果;不得进入通用日志 | | ||
| | `handle.drop` | 所有非零 kind;0/未知值也可 | 无 | 幂等;先移除 registry,再取消/回收 | | ||
|
|
||
| 这里的 provider/transport/devtools 生命周期 op 是 #200 对现有行为的显式对象化,不授权本期实现 descriptor 中尚未具备的 skills、Evaluation、Batch、SpeechTranslation 等能力。方法列在 descriptor 中但不属于 current capability 集时,返回 `UnsupportedFunctionality`,不能返回伪造的成功空值。 |
There was a problem hiding this comment.
§3.1 的句柄种类(第 115 行)、§3.2 的合法矩阵(第 126-178 行)和 §1.2 的能力保留清单(第 72 行)都没有 Decision,第 180 行还把 Evaluation 列为“不授权本期实现”的能力。你起草时的基线 72a37b5 还没有它;之后 master 合入了 #221、#226(RFC-0037、RFC-0038 decision),C ABI 已有 Decision 句柄和 aimux_provider_decision_model、aimux_decision_capabilities、aimux_decide、aimux_decide_with_abort(master aimux-ffi/src/lib.rs:107、:2849、:2911、:2928、:2938),七个绑定都有对应封装(例如 bindings/go/decision.go)。
它就是上游的实验性 evaluate:@ai-sdk/provider 4.0.19 里叫 EvaluationModelV4(src/evaluation-model/v4/),4.0.22 改名为 DecisionModelV4 / doDecide(src/decision-model/v4/decision-model-v4.ts:6-17),NoSuchModelError 的 modelType 也改为 decisionModel(4.0.22 src/errors/no-such-model-error.ts:19-21)。按 §0.1 第 9 条和 §11.2,新 ABI 删除旧导出时,如果没有对应的新 op,这项能力会丢失。
建议:§3.1 加 Decision 句柄(由 provider.model 的 decisionModel 方法产生;与上游一样是 Provider 上的扩展,不进入稳定的 ProviderV4 接口);§3.2 加 decision.decide(Decision;Abort 可选;call → decision 结果)和 decision.capabilities(Decision;无参数;call → 能力摘要,不联网);§1.2 加 decision;第 180 行删去 Evaluation,或写成“Evaluation 已以 Decision 的名义由 RFC-0037/0038 实现”;第 56、72 行的“八模态”届时是九种模型句柄。
覆盖 C1–C4、D1–D8、op/handle、错误、流生命周期、版本、stdio 和冻结条件。
状态与依赖
以 #200 已记录的一次性切换/全语言宿主回调后置为目标;类型和 provider 合同分别依赖 RFC-0042/0040,stdio 作为后续独立能力。
本 PR 属于完整 roadmap RFC 批次。整批已完成节点覆盖与跨文档契约复核,再按主题分别提交 Draft。各 PR 均独立基于 master,不叠加其他未合并文档。设计齐备不表示运行时实现或验收已完成。
验证
同批设计(均独立基于 master)