# AI 网关 > [!NOTE] > OCI Portal AI 网关将多个 OCI GenAI 渠道统一为 OpenAI、Anthropic 与 xAI > 兼容接口,并集中处理鉴权、模型访问控制、渠道调度和协议适配。 > > 路径、参数与响应结构以 [Swagger YAML](swagger.yaml) 或运行时 Swagger UI > 为准;协议差异、兼容改写和实测边界以本文为准。 **兼容快照:2026-07-15** ## 快速导航 - [快速接入](#quick-start) - [端点一览](#endpoints) - [路由与全局行为](#routing) - [Codex 接入](#codex) - [已知限制](#limitations) - [字段兼容矩阵](#compatibility) - [实现索引](#implementation) ## 快速接入 ### 基础地址与鉴权 ```text Base URL: https://<网关地址>/ai/v1 ``` 网关密钥在管理面板中创建,支持以下任一请求头: ```http Authorization: Bearer sk-... ``` ```http x-api-key: sk-... ``` 密钥可绑定渠道分组和模型白名单。全局模型黑名单会同时作用于模型列表、 请求路由和探测候选;开启「过滤弃用模型」后,OCI 已宣布弃用的模型也会从 列表与路由中移除。 可先用模型列表验证地址与密钥: ```bash curl "https://<网关地址>/ai/v1/models" \ -H "Authorization: Bearer $OCI_PORTAL_KEY" ``` ## 端点一览 | 协议域 | 端点 | 角色 | 流式 | | --- | --- | --- | :---: | | 对话 | `POST /ai/v1/responses` | OpenAI Responses,无状态主接口 | SSE | | 对话 | `POST /ai/v1/chat/completions` | OpenAI Chat Completions 兼容层 | SSE | | 对话 | `POST /ai/v1/messages` | Anthropic Messages 转换层 | SSE | | 向量 | `POST /ai/v1/embeddings` | OpenAI Embeddings | — | | 语音 | `POST /ai/v1/audio/speech` | OpenAI Audio Speech 外壳 | — | | 语音 | `POST /ai/v1/tts` | xAI TTS 格式转换层 | — | | 检索 | `POST /ai/v1/rerank` | Cohere / Jina 风格文档重排 | — | | 安全 | `POST /ai/v1/moderations` | OpenAI 外壳映射 OCI Guardrails | — | | 发现 | `GET /ai/v1/models` | 当前密钥可见模型列表 | — | 选择建议: - 新客户端优先使用 **Responses** - Anthropic SDK 或 Claude 生态客户端使用 **Messages** - 仅支持旧 OpenAI 对话协议的客户端使用 **Chat Completions** - Embeddings、TTS、Rerank 与 Moderations 使用各自专用端点 ## 路由与全局行为 ### 请求链路 ```mermaid flowchart LR A[客户端] --> B[网关密钥鉴权] B --> C[分组、白名单与全局过滤] C --> D[模型与能力匹配] D --> E[选择最小 Priority] E --> F[同优先级按 Weight 加权] F --> G[OCI GenAI] G -. 可重试且流未建立 .-> D ``` 单次请求最多尝试三个渠道。模型不可用、限流、上游服务错误或网络错误可触发 换渠道;流式连接建立后不会切换渠道重试。 ### 全局兼容边界 | 主题 | 当前行为 | | --- | --- | | 会话状态 | 网关不保存会话历史,客户端必须在每次请求中携带完整上下文 | | 上游存储 | Responses 请求始终强制 `store:false` | | 有状态字段 | Responses 拒绝非空 `previous_response_id`、非 `null` 的 `conversation` 和 `background:true` | | 对话上游 | 对话请求统一进入 OCI OpenAI 兼容面,当前供给以 `xai.`、`meta.`、`openai.` 前缀模型为主 | | 推理强度 | Responses `reasoning.effort`、Messages `output_config.effort`、Chat `reasoning_effort` 会传给上游;可用档位由模型决定 | | 服务端工具 | Responses 支持 `web_search`、`x_search`、`code_interpreter` 和远程 `mcp`;命名容器管理与 File Search 不提供 | | 文件输入 | `input_file` 会被 OCI ZDR 形态拒绝,详见[已知限制](#limitations) | | Chat 定位 | Chat Completions 只承担协议转换与兼容修复;新能力优先落在 Responses 与 Messages | ## Codex 接入 ### 主配置 自定义模型提供方必须写在用户级 `~/.codex/config.toml`。Codex 的项目级 `.codex/config.toml` 不允许改写 `model_provider` 与 `model_providers`。 ```toml model = "xai.grok-4.3" model_provider = "oci" [model_providers.oci] name = "oci-portal" base_url = "https://<网关地址>/ai/v1" env_key = "OCI_PORTAL_KEY" wire_api = "responses" ``` ### 自定义子代理 新版 Codex 可在 `~/.codex/agents/` 或项目级 `.codex/agents/` 放置独立 TOML 文件,并为子代理覆盖模型。每个文件都需要 `name`、`description` 和 `developer_instructions`: ```toml # .codex/agents/oci-worker.toml name = "oci-worker" description = "通过 OCI Portal 网关执行通用开发任务。" developer_instructions = """ 完成被分配的开发任务,保持改动聚焦,并返回验证结果。 """ model = "xai.grok-4.3" ``` > [!IMPORTANT] > `codex-cli 0.144.1` 已实测主会话和 multi-agent 子代理全链路可用。 > 内置 worker 可能先尝试 `gpt-5.6-luna` 或 `gpt-5.4`;网关没有对应渠道时 > 会出现少量 404,随后由 Codex 回落到可用模型。自定义 agent 的模型覆盖是否 > 直接生效取决于 Codex 版本;0.144.1 的实测主要依赖自动回落。 Codex 工具兼容现状: | 工具形态 | 网关处理 | 验证状态 | | --- | --- | --- | | `function` | 原样透传 | 可用 | | `namespace` | 子工具拍平为限定名 `function`,响应时还原 | multi-agent 已端到端实测;MCP 同路径有单测 | | `custom` | 顶层普通工具转换为 `function`,调用与历史记录双向回转 | 可用,但存在降级边界 | | `custom:apply_patch` | 直接剥离,让模型回落到其他编辑方式 | 有意限制 | | `tool_search` | namespace 已完整展开,目录搜索语义冗余,直接剥离 | 有意降级 | 配置语法参考 [Codex Subagents](https://learn.chatgpt.com/docs/agent-configuration/subagents) 与 [Codex Advanced Configuration](https://learn.chatgpt.com/docs/config-file/config-advanced)。 ## 已知限制 ### 超大流式请求 上游流式断流有两个独立触发维度,状态不同: > [!WARNING] > **instructions + tools 合计超过约 64.5 KB** 的流式请求,上游会在推理阶段 > 静默断连(纯 EOF,无 error / 终态事件);同请求非流式总是成功,`input` > 正文完全不计入。2026-07-13 定位(字节级二分),**2026-07-16 复测仍存在** > (70.4 KB 断 / 59.7 KB 过,Chicago,API Key 与签名行为一致)。 > [!NOTE] > **完整请求体超过约 82 KB**(含 input)的纯体积断流(2026-07-15 定位) > **已被上游修复**:2026-07-16 复核 83 KB、真实 codex 形态 104.5 KB、200 KB、 > 400 KB 流式均正常完成(Chicago 与 Phoenix 两区、签名与 API Key 两路径对照)。 网关当前行为: - **Chat Completions / Messages**:若上游在客户端收到任何内容前断流,自动用 非流式重做,并合成对应 chunk / event 序列(可兜住 64.5 KB 断流) - **Responses**:直通协议中途无法透明重试(客户端已收到事件)。流式保险丝按 `instructions + tools` 字节和判定:超过阈值时预防性改非流式上游 + 合成最小 SSE 事件序列(`response.created` → `response.output_item.done` → `response.completed`),语义保留但无增量输出。默认开、60 KB,可在 **设置 → AI → 流式保险丝** 调整或关闭 - **已开始输出的流**:不能透明重试;调用日志会记录提前终止,客户端可能只拿到 部分事件 ### grok 服务端搜索工具默认注入 对 `xai.` 前缀模型的 Responses 请求,网关按开关默认注入 `web_search` / `x_search` 工具;请求 tools 已包含同名工具时保持原样,不覆盖参数。默认双开, 可在 **设置 → AI → grok 服务端搜索工具** 关闭。 ### ZDR 与文件输入 Responses 的 `input_file` 内容块(`file_url` / `file_data`)实测会被上游拒绝: ```text File content is currently unsupported for ZDR customers ``` 网关强制 `store:false`,属于 ZDR 请求形态,因此当前不能通过该端点上传或引用文件。 ### 规格与实测边界 本项目提供的是兼容接口,而不是 OpenAI、Anthropic 或 xAI 协议的完整实现。 部分 OCI OpenAI 兼容行为来自实测,未见 Oracle 文档合同,可能随上游调整。 ## 字段兼容矩阵 矩阵基线: - [OpenAI Responses](https://developers.openai.com/api/reference/resources/responses/methods/create) - [OpenAI Chat Completions](https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create) - [OpenAI Embeddings](https://developers.openai.com/api/reference/resources/embeddings/methods/create) - [OpenAI Audio Speech](https://developers.openai.com/api/reference/resources/audio/methods/speech) - [OpenAI Moderations](https://developers.openai.com/api/reference/resources/moderations/methods/create) - [Anthropic Messages](https://platform.claude.com/docs/en/api/messages/create) - [Cohere Rerank](https://docs.cohere.com/reference/rerank) | 标记 | 含义 | | :---: | --- | | ✅ | 网关直接支持 | | ➡️ | 原样保留或透传;是否生效由 OCI 上游决定 | | 🔄 | 网关执行字段或协议转换后支持 | | ◐ | 部分支持、存在前置条件或语义降级 | ### OpenAI Responses **`POST /ai/v1/responses` · 无状态主接口** 网关以原始 JSON 为基底保留未知字段,但会强制关闭上游存储,并执行下表列出的 Codex 工具兼容改写。请求会重新编码,不承诺字节级原样转发。
核心字段 | 标准字段 | 状态 | 网关行为 | | --- | :---: | --- | | `model` | ◐ | 必填;通过密钥白名单并匹配可用渠道后送往上游 | | `input` | ➡️ | 支持字符串或 item 数组;普通内容保留,Codex 工具历史项可能改写 | | `instructions`、`max_output_tokens` | ➡️ | 类型可解析后保留,不做范围或模型能力校验 | | `temperature`、`top_p` | ➡️ | 保留,不做取值范围校验 | | `parallel_tool_calls` | ◐ | 通常保留;若全部工具被剥离,则与 `tool_choice` 一并删除 | | `text` / `text.format` / `text.verbosity` | ➡️ | 整个对象保留;是否生效由 OCI 模型决定 | | `reasoning` | ➡️ | 整个对象保留;`effort` 不校验档位 | | `tool_choice` | ◐ | 普通形态保留;namespace 对象会重限定,全部工具被剥离时删除 | | `store` | 🔄 | 无论客户端传什么,上游请求都强制改写为 `false` | | `stream` | ◐ | 支持 SSE;网关按 instructions+tools 字节和触发预防性非流式回退(保险丝,默认开 60 KB,见[已知限制](#limitations)) | | 其余标准与未知顶层字段 | ➡️ | `context_management`、`include`、`metadata`、`prompt`、`prompt_cache_key`、`service_tier`、`truncation`、`user` 等均保留,由 OCI 决定是否接受 |
工具兼容 | 工具或参数 | 状态 | 网关行为 | | --- | :---: | --- | | `tools[].type=function` | ➡️ | 非流式与流式均可,工具对象保留 | | `web_search` / `x_search` / `code_interpreter` | ◐ | Oracle 文档化的 xAI 服务端工具;参数与限制遵循 [xAI 规格](https://docs.oracle.com/en-us/iaas/Content/generative-ai/get-started-agents.htm#xai-compatible-tools) | | `tools[].type=mcp` | ➡️ | 远程 MCP 由上游直连,`server_url`、`require_approval`、`authorization` 等保留 | | `tools[].type=namespace` | 🔄 | 子 `function` 上提并限定命名;响应、历史调用和 `tool_choice` 会反向还原;组内非 `function` 子工具被剥离 | | `tools[].type=custom` | ◐ | 顶层非 `apply_patch` 工具转为带 `input` schema 的 `function`;响应与多轮历史双向回转;`format` 会删除 | | `custom:apply_patch` | ◐ | 整体剥离;grok 系未针对 Codex 补丁格式训练,模型应回落其他编辑方式 | | `tools[].type=tool_search` | ◐ | 请求可被接受,但工具本身直接剥离 | | `web_search.external_web_access=true` | 🔄 | 删除上游不识别的字段,保留 `web_search` | | `web_search.external_web_access=false` | ◐ | 上游没有“仅缓存检索”对应能力,按不越权原则剥离整个工具 |
本地拒绝(返回 400): - 非空 `previous_response_id` - 非 `null` 的 `conversation` - `background:true` - 未列入白名单的工具类型,例如 `web_search_preview`、`file_search`、 `computer`、`image_generation`、`shell` 响应边界: - 无工具还原且未触发流式升级时,普通响应保持直通语义 - namespace / custom 调用会在非流式响应与命中的 SSE `data` 事件中定向还原 - 普通 SSE 不补 `data: [DONE]`,reasoning 增量不会被过滤 - 未知模型返回 404,无可用渠道返回 503 - 上游错误使用 OpenAI 风格错误外壳,但不保证字段与标准 OpenAI 完全一致 ### OpenAI Chat Completions **`POST /ai/v1/chat/completions` · 存量客户端兼容层** 请求先转换为 Responses,再将 OCI Responses 响应桥接回 Chat Completions。 只有下表字段会进入上游请求。
展开字段矩阵 | 标准字段 | 状态 | 网关行为 | | --- | :---: | --- | | `model` | ◐ | 必填,受密钥白名单和可用渠道限制 | | `messages` | 🔄 | 必填,转换为 Responses `input` / `instructions` | | `system` / `developer` 消息 | ◐ | 文本按顺序合并为 `instructions`;块数组中的非文本内容忽略 | | `user` / `assistant` 文本 | 🔄 | 字符串和 `text` 块分别转为 `input_text` / `output_text` | | `image_url` | ◐ | URL 或 data URI 转为 `input_image`;`detail` 忽略 | | assistant `tool_calls` / `role=tool` | 🔄 | 转为 `function_call` / `function_call_output` | | `max_completion_tokens` | 🔄 | 转为 `max_output_tokens`,优先于 `max_tokens` | | `max_tokens` | 🔄 | 未提供 `max_completion_tokens` 时转为 `max_output_tokens` | | `temperature`、`top_p`、`parallel_tool_calls` | ◐ | 写入 Responses,不校验范围或模型能力 | | `stream` | 🔄 | Responses SSE 转为 `chat.completion.chunk`,末尾补 `data: [DONE]` | | `stream_options.include_usage` | 🔄 | 控制终块后的独立 usage 块 | | `tools[].type=function` | ◐ | 支持 `name`、`description`、`parameters`;`strict` 忽略 | | `tool_choice` | ◐ | 支持 `auto` / `none` / `required` 和具名 function | | `response_format` | ◐ | `json_object`、`json_schema` 转为 Responses `text.format` | | `reasoning_effort` | ◐ | 转小写后映射为 `reasoning.effort` | | `store` | 🔄 | 客户端取值忽略,上游始终使用 `store:false` |
不支持(返回 400):`input_audio`、`file`、`refusal` 等消息内容块,以及 `function` 之外的工具类型。
静默忽略字段 消息级 `name` / `refusal` / `audio` / 旧式 `function_call`;`stop`、`seed`、 `n`、`frequency_penalty`、`presence_penalty`、`logprobs`、`top_logprobs`、 `logit_bias`;`user`、`audio`、`modalities`、`prediction`、`metadata`、 `moderation`、`prompt_cache_key`、`safety_identifier`、`service_tier`、 `verbosity`、`web_search_options`、`stream_options.include_obfuscation` 及其他未知字段。
响应边界: - 非流式固定生成一个 `choices[0]`;文本合并,函数调用转为 `tool_calls` - `finish_reason` 只生成 `stop`、`tool_calls`、`length` - reasoning、logprobs、refusal、annotations、audio、service tier 和 system fingerprint 不返回 - usage 保留 `prompt_tokens`、`completion_tokens`、`total_tokens` 与 `prompt_tokens_details.cached_tokens` - 已开始输出的流中断不会转换成标准 SSE 错误事件 ### Anthropic Messages **`POST /ai/v1/messages` · Anthropic 协议转换层** 支持 `Authorization: Bearer` 与 `x-api-key`,但不校验或使用 `anthropic-version`、`anthropic-beta` 请求头。
展开顶层字段矩阵 | 标准字段 | 状态 | 网关行为 | | --- | :---: | --- | | `model` | ◐ | 用于模型与渠道选择;空字符串通常最终返回模型不存在 | | `max_tokens` | 🔄 | 缺省或 ≤0 时使用 8192,再转为 `max_output_tokens` | | `messages` | ◐ | 必须非空;角色、交替顺序和空内容不做完整校验 | | `system` | ◐ | 支持字符串或 text 块数组;文本块拼接,附加字段忽略 | | `temperature`、`top_p` | ◐ | 写入 Responses,不校验范围或模型能力 | | `stream` | 🔄 | Responses SSE 桥接为 Anthropic 标准事件序列 | | `tools` | ◐ | 每个工具转为 Responses `function`;服务端工具类型不保留原语义 | | `tool_choice` | ◐ | 支持 `auto`、`any`、`none`、具名 `tool` | | `output_config.effort` | 🔄 | 转小写后映射为 `reasoning.effort` |
内容块兼容: | `messages[].content` | 状态 | 网关行为 | | --- | :---: | --- | | 字符串 / `text` | 🔄 | user 转 `input_text`,assistant 历史转 `output_text` | | `image` | ◐ | 仅支持 `base64` 与 `url` source | | `tool_use` | 🔄 | 转为 `function_call`,保留 ID、名称与输入 | | `tool_result` | ◐ | 转为 `function_call_output`;块数组只拼接 text,`is_error` 与非文本结果丢失 | | `null` / 空块数组 | ◐ | 消息可能从上游 input 中消失,不返回参数错误 | 不支持(返回 400):`document`、服务端工具结果及未知内容块。历史 `thinking` / `redacted_thinking` 会删除。
静默忽略字段 `top_k`、`stop_sequences`、`metadata`、`thinking`、`output_config` 其余子字段、 `cache_control`、`container`、`inference_geo`、`service_tier` 及其他未知顶层字段。
响应边界: - 仅将 Responses `output_text` 转为 `text`,`function_call` 转为 `tool_use` - `stop_reason` 只生成 `end_turn`、`tool_use`、`max_tokens` - 不生成 Anthropic thinking / signature 内容块 - usage 只保留 `input_tokens`、`output_tokens` 与 `cache_read_input_tokens` - 流式上游错误与无终态断流会转成 Anthropic `error` 事件 ### OpenAI Embeddings **`POST /ai/v1/embeddings` · 向量化专用端点** | 标准字段 | 状态 | 网关行为 | | --- | :---: | --- | | `model` | ◐ | 必填,受白名单限制,且需要 `EMBEDDING` 能力渠道 | | 字符串 `input` | ✅ | 包装为单个输入后调用 OCI | | 字符串数组 `input` | ✅ | 按原顺序调用 OCI | | `dimensions` | ◐ | 映射为 OCI 输出维度,不校验范围或模型能力 | | `encoding_format=float` | ✅ | 返回 float 数组;省略时相同 | 不支持(返回 400):token ID 数组、空数组、`null` 和 `encoding_format=base64`。`user` 与其他未知字段静默忽略。 响应使用标准 `object:"list"` 外壳,向量为 `float32` 数组,不支持流式。 ### 语音生成 两个端点最终使用同一 OCI xAI TTS 上游与渠道调度: #### OpenAI Audio Speech **`POST /ai/v1/audio/speech`** | 标准字段 | 状态 | 网关行为 | | --- | :---: | --- | | `model` | ◐ | 必填,受白名单限制,需要 `TTS` 能力渠道;当前为 `xai.grok-tts` | | `input` | ◐ | 必填非空,随后保留 | | `voice` | ➡️ | 使用 xAI 音色 `ara` / `eve` / `leo` / `rex` / `sal` | | `response_format` | ➡️ | 实测 `mp3` 可用,其余格式由上游决定 | | `language`(扩展) | 🔄 | 上游必填;缺省时注入 `"auto"` | | `speed`、`instructions` 与未知字段 | ➡️ | 保留,是否生效由上游决定 | #### xAI TTS **`POST /ai/v1/tts`** 接受 [xAI 官方 TTS 格式](https://docs.x.ai/developers/model-capabilities/audio/text-to-speech), 转换为 OpenAI 兼容形态后进入同一上游。 | 字段 | 状态 | 网关行为 | | --- | :---: | --- | | `text` | 🔄 | 必填非空,转换为 `input` | | `language` | ◐ | 必填,接受 BCP-47 或 `auto` | | `voice_id` | 🔄 | 转为 `voice`;缺省交给上游默认值 `eve` | | `output_format` | ➡️ | `{codec, sample_rate, bit_rate}` 对象保留,实测生效 | | `speed` | ➡️ | 保留,实测可用 | | `model`(网关扩展) | ◐ | 缺省注入 `xai.grok-tts`,可覆盖,受白名单限制 | | 其余未知字段 | ➡️ | 保留,是否生效由上游决定 | 共同响应边界: - 成功响应为一次性完整音频,`Content-Type` 透传上游,缺省 `audio/mpeg` - 不提供 HTTP 流式音频或 WebSocket 代理 - 无 token 用量口径,调用日志只记时延与渠道 ### Rerank **`POST /ai/v1/rerank` · Cohere / Jina 风格协议** 上游走 OCI typed 面,模型为 `cohere.rerank-v4.0-pro` 或 `-fast`。 | 字段 | 状态 | 网关行为 | | --- | :---: | --- | | `model` | ◐ | 必填,受白名单限制,需要 `RERANK` 能力渠道 | | `query` | ✅ | 必填非空 | | `documents` | ◐ | 仅接受字符串数组;旧版 `{"text": ...}` 对象数组返回 400 | | `top_n` | ✅ | 可选,限制返回条数 | | `return_documents` | ✅ | 为 `true` 时回带原文 | `max_tokens_per_doc` 与未知字段静默忽略。响应按相关度降序, `results[].index` 指向输入下标,`relevance_score` 为 0~1 浮点;无 token 用量口径。 ### Moderations **`POST /ai/v1/moderations` · OpenAI 外壳映射 OCI Guardrails** | 标准字段 | 状态 | 网关行为 | | --- | :---: | --- | | 字符串 `input` | ✅ | 单条审核 | | 字符串数组 `input` | ✅ | 逐条审核,单次 1~8 条 | 不支持(返回 400):多模态 input、空字符串条目、空数组或超过 8 条。 `model` 接受但忽略,不参与白名单判断。 响应边界: - categories 使用 OCI 原生维度 `overall` / `blocklist` / `prompt_injection` - 任一维度得分 ≥ 0.5 时 `flagged=true` - PII 命中放在扩展字段 `results[].pii`,包含 `text`、`label`、`score`、 `offset` 与 `length`,不参与 `flagged` - 实测中文人名与手机号识别较弱,英文 PII 识别正常 - 响应 `model` 恒为 `oci-guardrails` ### Models **`GET /ai/v1/models` · 当前密钥可见模型列表** 响应使用 OpenAI Models 列表外壳,只返回同时通过以下条件的模型: 1. 存在于当前渠道目录 2. 匹配密钥绑定的渠道分组 3. 不在全局模型黑名单 4. 命中密钥模型白名单(配置时) 5. 未被「过滤弃用模型」开关排除 网关不提供标准的单模型检索端点。 ## 实现索引 | 端点 / 能力 | 主要实现 | | --- | --- | | Responses 直通与 Codex 工具兼容 | [`airesponses.go`](../internal/service/airesponses.go) · [`responses.go`](../internal/aiwire/responses.go) | | Chat Completions 转换 | [`chatresponses.go`](../internal/service/chatresponses.go) · [`openai.go`](../internal/aiwire/openai.go) | | Anthropic Messages 转换 | [`anthresponses.go`](../internal/service/anthresponses.go) · [`anthropic.go`](../internal/aiwire/anthropic.go) | | 渠道路由与 Embeddings | [`aigateway_chat.go`](../internal/service/aigateway_chat.go) | | TTS 上游 | [`genai_speech.go`](../internal/oci/genai_speech.go) · [`aigateway_extras.go`](../internal/service/aigateway_extras.go) | | Rerank / Moderations 上游 | [`genai_guard.go`](../internal/oci/genai_guard.go) · [`rerank.go`](../internal/aiwire/rerank.go) · [`moderations.go`](../internal/aiwire/moderations.go) | | HTTP Handler 与流式桥接 | [`aigateway.go`](../internal/api/aigateway.go) · [`aigateway_extras.go`](../internal/api/aigateway_extras.go) | 本文是兼容性快照,不替代 Swagger。标准接口、Codex 客户端与 OCI 上游均可能 变化,最终行为以当前版本代码、运行时 Swagger 和实测结果为准。