本文定义 AIStudio2API 使用的 Google AI Studio 私有协议、认证状态、WAA 运行时、JSON+protobuf 数组、增量事件、工具与媒体链。模型方法、限制和能力由账户的实时 ListModels 返回,公开 API 将原始结构投影为规范事件和兼容响应。
| 用途 | 入口 | 格式 |
|---|---|---|
| 页面 origin | https://aistudio.google.com |
HTTPS |
| MakerSuite RPC | https://alkalimakersuite-pa.clients6.google.com/$rpc/google.internal.alkali.applications.makersuite.v1.MakerSuiteService/<METHOD> |
application/json+protobuf |
| WAA RPC | https://waa-pa.clients6.google.com/$rpc/google.internal.waa.v1.Waa/<METHOD> |
application/json+protobuf |
| BotGuard interpreter | https://www.google.com/js/bg/<INTERPRETER_HASH>.js |
JavaScript |
| Drive 上传 | https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id |
multipart/related |
| Drive 下载 | https://www.googleapis.com/drive/v3/files/<FILE_ID>?alt=media |
HTTPS body |
MakerSuite 请求使用以下公共头:
| Header | 来源 |
|---|---|
content-type |
固定为 application/json+protobuf |
user-agent |
当前账户 Camoufox 官网请求 |
x-user-agent |
官网 gRPC-Web 标识 |
x-goog-api-key |
AI Studio 首页或当前官网请求动态值 |
x-goog-authuser |
当前账户官网请求 |
x-aistudio-visit-id |
首页初始化或当前官网请求 |
x-aistudio-g1-tier、x-goog-ext-519733851-bin |
官网请求存在时透传 |
authorization |
三段 SAPISID 签名 |
cookie |
当前账户对目标 RPC 可见的 Cookie |
origin、referer |
https://aistudio.google.com |
accept-language |
账户 locale |
请求头 x-goog-api-key 是 AI Studio 页面使用的动态公共值,与用户创建的 Google Cloud API key 不同;免费网页链仍依赖 Cookie、SAPISID 签名和 WAA proof。
MakerSuite 与 Drive 业务请求使用和 Camoufox 对齐的 Firefox TLS、HTTP/2 与请求头顺序;WAA VM、fresh proof 和隔离登录由同一账户的 Camoufox 环境完成。
JSON+protobuf 使用数组表示 protobuf message。数组索引从 0 开始,protobuf field 从 1 开始,因此 field N 对应索引 N-1。Google 响应允许省略空槽并形成 [,value];解码器先把省略槽规范化为 null,再从完整 JSON 根值中提取 repeated message。HTTPS chunk 仅提供字节序列,业务事件边界由数组结构确定。
协议核心使用以下 MakerSuite RPC:
| RPC | 用途 |
|---|---|
ListModels |
读取模型、方法、限制、默认参数与能力选项 |
CountTokens |
权威输入 token 计数 |
GenerateContent |
文本、思考、函数、Google 工具、图片、语音与音乐 |
GenerateAccessToken |
获取 Drive bearer token |
GenerateVideo |
创建 Veo 长任务 |
GetGenerateVideoOperation |
轮询 Veo 长任务 |
AI Studio 页面初始化还包含以下控制面 RPC:
| RPC | 用途 |
|---|---|
GetLoggingContext |
页面日志上下文 |
GetUserPreferences |
用户偏好与欢迎状态 |
UpdateUserPreferences |
更新欢迎状态等用户偏好 |
ListPromos |
页面活动信息 |
GetAiStudioBenefitTier |
账户层级枚举 |
ListRecentApplets |
最近 Applet |
ListPrompts |
提示词目录 |
GetUserRestrictions |
账户限制 |
服务启动加载账户、公共头和实时模型目录,业务能力按需调用对应数据面 RPC。
authorization 由三个 Cookie 分别签名:
| 令牌标签 | Cookie |
|---|---|
SAPISIDHASH |
SAPISID |
SAPISID1PHASH |
__Secure-1PAPISID |
SAPISID3PHASH |
__Secure-3PAPISID |
三段使用相同的 Unix 秒级时间戳:
source = "<TIMESTAMP> <COOKIE_VALUE> https://aistudio.google.com"
digest = lowercase_hex(SHA1(source))
token = "<LABEL> <TIMESTAMP>_<DIGEST>"
authorization = token_1 + " " + token_2 + " " + token_3
MakerSuite 响应的 Set-Cookie 在响应头到达时基于账户最新 storage-state.json 单写合并并原子写回。签名、Cookie 选择和过期判断均以请求时重新读取的账户状态为准。
Windows Chrome 导入从 Profile 恢复 OAuth 与 Device Bound Session Credentials:
Chrome Local State + Profile Preferences + Web Data/token_service
-> Gaia ID、v20 refresh token 密文、wrapped binding key
-> 解开 App-Bound v20 主密钥
-> AES-256-GCM 解密 refresh token
-> OAuthMultilogin sentinel 请求取得 DBSC challenge
-> NCrypt 设备密钥签发 ES256 assertion
-> X25519/HPKE 解密服务端 Cookie
-> 保存 Playwright storage state 结构与续签材料
Local State.os_crypt.app_bound_encrypted_key 使用 Base64 编码并带 APPB 前缀。程序把内嵌 ABE helper 加载到独立、隐藏的 Chrome 进程中,取得 32 字节主密钥;临时进程树由 Windows Job Object 管理。token_service.encrypted_token 使用 v20 || nonce[12] || ciphertext+tag,以该主密钥执行 AES-GCM 解密。
OAuthMultilogin 使用 MultiOAuth 头。第一次 assertion 为 DBSC_CHALLENGE_IF_REQUIRED,响应提供 challenge;第二次 assertion 的 JWT header 使用 ES256 与 DEVICE_BOUND_SESSION_CREDENTIALS_ASSERTION。payload 绑定 Google OAuth client、challenge、设备公钥 issuer 和临时 HPKE 公钥。Cookie 密文使用 X25519、HKDF-SHA256 与 AES-128-GCM 解密。
Chrome 导入状态在 storage-state.json 的 aistudio2api 扩展中保存来源、Gaia ID、refresh token 与 wrapped binding key。普通或受保护 RPC 首次返回 401/403 时,服务在同一账户出口续签 Cookie、使动态头失效、关闭该账户 WAA runtime,并只重放一次。隔离 Camoufox 登录和外部 storage state 不携带 Chrome OAuth 扩展,因此遇到 401/403 时跳过 Cookie 续签,仅使动态头失效、重建 WAA runtime 并只重放一次。
| 文件 | 内容 |
|---|---|
account.json |
label、enabled、proxy、locale、timezone |
storage-state.json |
Cookie、localStorage 和可选 Chrome 续签材料 |
camoufox-fingerprint.json |
账户固定的 navigator、屏幕、字体、语言、地区和时区配置 |
runtime-state.json |
模型/全局冷却与 Drive/Veo 资源到账户的绑定 |
初始化、WAA、MakerSuite、OAuth 续签和 Drive 使用账户固定代理。locale 同时设置 navigator language、Accept-Language 与地区,timezone 设置浏览器时区;重新登录和 WAA runtime 复用同一账户指纹。调度器先按模型与方法筛选,再轮询获取账号并发槽位。同账号 WAA proof 串行生成,已准备的 MakerSuite HTTP 请求并发执行;首个活动请求获取跨进程文件租约,最后一个释放。未绑定账户和资源的请求遇到可重试的 401、403、404、429、5xx 或单账户初始化超时时,可以在首个客户端可见事件前切换到另一个同能力账户。Drive file、Veo operation 与产物 file 始终使用创建账户。
受保护请求使用以下链路:
Waa/Create
-> decode challenge
-> load interpreter by current hash
-> initialize official VM lifecycle
-> expose official snapshot service
-> SHA-256(binding prompt) as lowercase hex
-> snapshot({TYb:{content:<DIGEST>}})
-> write fresh proof into request
-> Go HTTP transport sends MakerSuite RPC
Waa/Create 响应第二槽经 Base64 解码后,对每个字节加 97 得到 challenge:
{
"messageId": "<MESSAGE_ID>",
"globalName": "<GLOBAL_NAME>",
"interpreterHash": "<INTERPRETER_HASH>",
"interpreterUrl": "https://www.google.com/js/bg/<INTERPRETER_HASH>.js",
"program": "<DYNAMIC_PROGRAM>"
}program 与 challenge 属于当前 Create 生命周期,interpreter 按 hash 缓存。proof 绑定当前 prompt 摘要与 VM 内部状态,每个请求生成新的 proof。
生成服务启动时按配置的常驻数与启动并发数预热账户 WAA runtime:
- Go 启动隔离、无头 Camoufox,并通过原生 WebDriver BiDi 建立 session
- 写入账户 Cookie 与 localStorage,使用实时目录中的
gemini-flash-latest进入新对话;TEMPORARY_CHAT=true时 URL 携带temporary=true - 定位页面 bundle 中调用
.snapshot({且包含content的官方高层函数 - 填入唯一 bootstrap prompt 并执行一次官网 Run
- 保存官网
GenerateContent的必要动态头与官方 WAA service - 后续业务请求串行调用同一 service 获取 fresh proof
GenerateContent写入 field 5,GenerateVideo写入 field 8,正文由 Go HTTP transport 发送
Camoufox 负责官方 VM 初始化与 WAA proof;Go 负责业务请求、增量解码和公开 API。运行期依赖 Go 与 Camoufox。官方 VM 初始化形状为:
initialize(program, ready, true, environment, signalLists, persistentState, false, loggers)VM 生命周期参数为 43,200,000ms,检查间隔为 300,000ms。页面生命周期中断、snapshot 错误、计时器到期、认证续签或进程关闭会使 runtime 失效,下一次请求重新 bootstrap。Waa/Ping 维护官方生命周期,业务请求 proof 由 snapshot 生成。
WAA 预热页在普通模式下会执行官网 GenerateTitle 与 CreatePrompt;临时对话关闭该页的自动保存,GenerateContent 请求结构保持一致。
同一账户的 snapshot 必须串行。GenerateContent 的 binding prompt 按 contents 和 parts 的原顺序展开,再以单个空格连接:
| Part | 写入 binding prompt 的值 |
|---|---|
| text | 原始文本 |
| inline data | 原始二进制的标准 Base64 |
| external media | URL |
| Drive file | file ID |
| function、function result、code、thought signature | 空字符串 |
binding prompt 的输入域为 contents parts;Veo 使用视频提示词。prompt 的 SHA-256 小写十六进制摘要交给官方 snapshot,返回值是 ! 开头的字符串;编码器随后把 proof 写入目标 protobuf field,原请求的其他槽位保持不变。worker 状态为 starting、bootstrapping、ready、busy、closing、closed 和 failed。
请求正文:
[]响应根形状为 [[<MODEL_ROW>, ...]]。模型行字段:
| JSON 索引 | protobuf field | 内容 |
|---|---|---|
| 0 | 1 | models/<MODEL_ID> |
| 2 | 3 | 版本 |
| 3 | 4 | 显示名称 |
| 4 | 5 | 描述 |
| 5 | 6 | 输入 token 上限 |
| 6 | 7 | 输出 token 上限 |
| 7 | 8 | 支持的方法 |
| 8 | 9 | 默认 temperature |
| 9 | 10 | 默认 topP |
| 10 | 11 | 默认 topK |
| 56 | 57 | 模型别名 |
| 64 | 65 | 主能力码 |
| 66 | 67 | TTS voice 列表 |
| 70 | 71 | Veo 配置 |
| 71 | 72 | thinking 默认配置 |
| 74 | 75 | 次能力码 |
| 75 | 76 | 图片宽高比码 |
| 76 | 77 | 图片输出分辨率码 |
能力码映射:
| 码 | 能力 | 码 | 能力 |
|---|---|---|---|
| 1 | chat model | 9 | code execution |
| 10 | function declarations | 12 | Google Search |
| 13 | URL Context | 20 | Veo route |
| 21 | image route | 25 | thinking |
| 26 | live route | 35 | thinking budget |
| 37 | speech route | 43 | media resolution |
| 47 | aspect ratio | 49 | output resolution |
| 52 | thinking level | 53 | music route |
| 54 | image search | 58 | Google Maps |
| 59 | private Interaction route |
未知能力码按原值保留为 capability_code_<N> 或 secondary_capability_code_<N>。
图片与视频选项使用枚举码:
| 类型 | 码值映射 |
|---|---|
| 图片/视频宽高比 | 1=1:1、2=9:16、3=16:9、4=3:4、5=4:3、6=3:2、7=2:3、8=5:4、9=4:5、10=21:9、11=9:21、12=1:4、13=4:1、14=1:8、15=8:1 |
| 图片分辨率 | 1=1K、2=2K、3=4K、4=512 |
| 视频时长 | 1=5s、2=6s、3=7s、4=8s、5=4s |
| 视频分辨率 | 1=720p、2=1080p、3=4k、4=368p、5=360p |
Veo field 71 的宽高比、时长和分辨率分别位于子索引 4、5、9。TTS field 67 是 repeated voice row,每行索引 0 为 voice name。thinking field 72 的默认 level 位于子索引 5。
纯文本且无 system:
["models/<MODEL_ID>", [<CONTENT>, ...]]含 system、inline data、外部媒体或 Drive file:
["models/<MODEL_ID>", null, ["models/<MODEL_ID>", [<CONTENT>, ...], null, null, null, <SYSTEM>]]请求形状选择:
| 条件 | 根结构 | GenerateContent 子消息位置 |
|---|---|---|
| 纯文本 contents | [model, contents] |
— |
| system instruction | [model, null, generate] |
$[2][5] |
| function / Google tools | [model, null, generate] |
$[2][6] |
| inline data、external media、Drive、function call/result、code result | [model, null, generate] |
$[2][1] |
包含 system 与函数声明的完整计数请求:
[
"models/gemini-3.6-flash",
null,
[
"models/gemini-3.6-flash",
[
[
[[null, "调用 ping 检查服务"]],
"user"
]
],
null,
null,
null,
[
[[null, "你是诊断助手"]],
"user"
],
[
[null, [["ping", "检查服务"]]]
]
]
]响应为单元素数组:
[<INPUT_TOKEN_COUNT>]
索引 0 是权威输入 token 数。其他槽按不透明协议字段保留。
Content 形状:
[[<PART>, ...], "user|model"]客户端 tool result 使用 user role。Part 字段:
| JSON 索引 | protobuf field | 内容 |
|---|---|---|
| 1 | 2 | 文本 |
| 2 | 3 | inline data [mime, base64] |
| 5 | 6 | Drive file [fileId] |
| 6 | 7 | 外部媒体 [mime, url] |
| 7 | 8 | executable code [languageCode, code] |
| 8 | 9 | code execution result [outcomeCode, output] |
| 10 | 11 | function call [name, Struct, callId?] |
| 11 | 12 | function result [name, Struct, callId?] |
| 12 | 13 | thought boolean |
| 14 | 15 | thought signature |
system instruction:
[[[null, "<SYSTEM_TEXT>"]], "user"]根消息字段:
| JSON 索引 | protobuf field | 内容 |
|---|---|---|
| 0 | 1 | models/<MODEL_ID> |
| 1 | 2 | contents |
| 2 | 3 | safety settings |
| 3 | 4 | generation config |
| 4 | 5 | fresh WAA proof |
| 5 | 6 | system instruction |
| 6 | 7 | tools |
| 10 | 11 | 固定值 1 |
| 13 | 14 | [[null,null,<TIMEZONE>]] |
| 14 | 15 | 用户 Cloud API key,免费网页链保持 null |
safety settings:
[
[null, null, 7, 5],
[null, null, 8, 5],
[null, null, 9, 5],
[null, null, 10, 5]
]generation config 字段:
| JSON 索引 | protobuf field | 内容 |
|---|---|---|
| 1 | 2 | stop sequences |
| 3 | 4 | max output tokens |
| 4 | 5 | temperature |
| 5 | 6 | topP |
| 6 | 7 | topK |
| 7 | 8 | response MIME type |
| 8 | 9 | response schema |
| 13 | 14 | 固定值 1 |
| 14 | 15 | response modalities:TEXT=1、IMAGE=2、AUDIO=3 |
| 15 | 16 | speech config |
| 16 | 17 | thinking config [1, budget?, null, level] |
| 18 | 19 | seed |
| 26 | 27 | image config [aspectRatio?, imageSize?] |
生成参数校验:
| 参数 | 默认来源 | 有效值 |
|---|---|---|
| max output | ListModels field 7 | 1..model.outputTokenLimit |
| temperature | ListModels field 9 | 0..2 |
| topP | ListModels field 10 | 0..1 |
| topK | ListModels field 11 | 非负整数 |
| thinking level | ListModels field 72 | Low=1、Medium=2、High=3、Minimal=4 |
| thinking budget | 请求值 | 模型能力码包含 thinking budget |
response modalities:
| 输出 | wire | 默认路由 |
|---|---|---|
| text | [1] |
chat |
| image | [2] |
image route |
| image + text | [2,1] |
显式组合请求 |
| audio | [3] |
speech / music route |
AUDIO 采用独立输出模态。JSON Schema type code 为 string=1、number=2、integer=3、boolean=4、array=5、object=6;schema 支持 format、description、nullable、enum、items、properties、required 和 field 23 propertyOrdering。
以下最小组合请求包含 system、文本、函数声明、generation config、WAA proof 与账户时区。连续空槽保持在同行,字段含义查上表:
[
"models/gemini-3.6-flash",
[
[
[[null, "调用 ping 检查服务"]],
"user"
]
],
[
[null, null, 7, 5],
[null, null, 8, 5],
[null, null, 9, 5],
[null, null, 10, 5]
],
[null, null, null, 512, 0.2, 0.95, 40, null, null, null, null, null, null, 1],
"!WAA_PROOF",
[
[[null, "你是诊断助手"]],
"user"
],
[
[null, [["ping", "检查服务"]]]
],
null,
null,
null,
1,
null,
null,
[[null, null, "Asia/Taipei"]]
]GenerateContent 返回持续增长的 JSON+protobuf 根数组,根索引 0 是 repeated frames。帧结构:
| 路径 | 内容 |
|---|---|
$[0][frame][0] |
candidates |
$[0][frame][0][0][0] |
candidate content |
$[0][frame][0][0][1] |
finish reason code |
$[0][frame][0][0][6] |
citations |
$[0][frame][0][0][7] |
grounding metadata |
$[0][frame][2] |
usage |
$[0][frame][7] |
response ID |
$[0][frame][3] 且 frame 0 为空 |
interaction metadata |
传输正文是一个 JSON 根值,网络 chunk 提供字节;解码器在 $[0] 中每出现一个完整 repeated frame 时立即消费该 frame。每个内容帧包含一个 candidate,candidate content 为 [[parts...], "model"]。完成帧可以同时携带最后一组 Part、usage、response ID 和 finish reason,根数组解析完成后结束读取。
从 $[0] 提取出的文本帧:
[
[
[
[
[[null, "42"]],
"model"
]
]
]
]随后到达的完成帧包含 finish=1、usage 和 response ID:
[
[[null, 1]],
null,
[27, 1, 28, null, null, null, null, 0, null, 0],
null,
null,
null,
null,
"response_01"
]高频路径速查:
| 结构 | JSONPath | 内容 |
|---|---|---|
| GenerateContent | $[0] |
model |
| GenerateContent | $[1] |
contents |
| GenerateContent | $[3] |
generation config |
| GenerateContent | $[4] |
WAA proof |
| GenerateContent | $[5] |
system instruction |
| GenerateContent | $[6] |
tools |
| GenerateContent | $[13][0][2] |
timezone |
| response root | $[0][frame] |
repeated frame |
| candidate content | $[0][frame][0][0][0] |
[[parts], "model"] |
| candidate finish | $[0][frame][0][0][1] |
finish reason code |
| Part text | ...parts[part][1] |
text |
| Part inline data | ...parts[part][2] |
[mime, base64] |
| Part function call | ...parts[part][10] |
[name, Struct, callId?] |
| Part thought | ...parts[part][12] |
boolean |
| Part signature | ...parts[part][14] |
signature |
| frame usage | $[0][frame][2] |
usage array |
| frame response ID | $[0][frame][7] |
response ID |
Part 文本带 part[12]=true 时属于 reasoning summary,普通文本属于可见正文;part[14] 是 thought signature。签名可以附在文本、函数调用或独立空 Part 上,下一轮必须原样回传:
| 公开协议 | 签名输入 | 签名输出 |
|---|---|---|
| OpenAI Chat | assistant tool call 的 extra_content.google.thought_signature |
tool call 的同名扩展字段 |
| OpenAI Responses | reasoning.encrypted_content 紧邻后续 function_call |
reasoning item 的 encrypted_content |
| Anthropic | thinking 或 redacted_thinking block 的 signature |
thinking block 的 signature |
| Gemini | 数据 Part 或独立 Part 的 thoughtSignature |
Part 的 thoughtSignature |
reasoning summary 是服务端返回的摘要文本。thought signature 作为下一轮请求的协议状态字段原样回传。
协议核心按网络顺序输出 text、reasoning、tool_call、executable_code、code_execution_result、grounding、citation、media、thought_signature、usage、finish 和 error。
grounding metadata 字段:
| JSON 索引 | 内容 |
|---|---|
| 0 | search entry point [renderedContent?, sdkBlob?] |
| 1 | grounding chunks |
| 2 | grounding supports |
| 3 | retrieval metadata,动态分数位于子索引 1 |
| 4 | web search queries |
| 6 | Maps widget context token |
grounding chunk 的 oneof 索引 0/1/2 分别为 web、retrieved context、maps;内部字段依次为 URI、title、text、place ID。support 为 [segment, chunkIndices, confidenceScores],segment 为 [partIndex,startIndex,endIndex,text]。candidate citations 的 entries 位于 metadata 索引 0,每项 URL 在索引 2、title 在索引 3。
包含 web chunk、maps chunk、正文 support、检索分数和查询词的 raw metadata:
[
["<div>Search results</div>", "SDK_BLOB"],
[
[["https://example.com/gemini", "Gemini Guide", "Protocol overview"]],
[null, null, ["https://maps.google.com/?cid=1", "Google Taipei", "", "ChIJ_demo"]]
],
[
[[0, 0, 12, "Gemini Guide"], [0], [0.98]]
],
[null, 0.91],
["Gemini AI Studio protocol"],
null,
"MAPS_WIDGET_CONTEXT_TOKEN"
]Code Execution 的 language code 为 0=LANGUAGE_UNSPECIFIED、1=PYTHON。执行结果 outcome code 为 0=OUTCOME_UNSPECIFIED、1=OUTCOME_OK、2=OUTCOME_FAILED、3=OUTCOME_DEADLINE_EXCEEDED。
完成帧 usage:
| 数组索引 | 语义 | 规范字段 |
|---|---|---|
| 0 | input tokens | input_tokens |
| 1 | visible output tokens | output_tokens |
| 2 | total tokens | total_tokens |
| 7 | tool tokens | tool_tokens |
| 9 | thought tokens | reasoning_tokens |
完整 usage 直接按上游原值返回。完成帧省略 visible output tokens 时,服务按上游 total 与其余分类字段恢复该值。完整 usage 缺失时,内置 Gemini SentencePiece tokenizer 在本地统计可观测输入、工具声明、reasoning summary 和实际输出。
OpenAI 与 Anthropic 的输入统计为 input + tool,输出统计为 visible output + reasoning。Gemini 分别投影 promptTokenCount、candidatesTokenCount、thoughtsTokenCount 与 totalTokenCount。隐藏思考用量来自上游 usage field 9;本地 fallback 统计服务端返回的 reasoning summary。
| code | reason | code | reason |
|---|---|---|---|
| 0 | unspecified | 1 | stop |
| 2 | max_tokens | 3 | safety |
| 4 | recitation | 5 | other |
| 6 | language | 7 | blocklist |
| 8 | prohibited_content | 9 | spii |
| 10 | malformed_function_call | 11 | image_safety |
| 12 | unexpected_tool_call | 13 | too_many_tool_calls |
| 14 | image_prohibited_content | 15 | image_other |
| 16 | no_image | 17 | image_recitation |
错误响应根形状为 [null,[code,message,...]]。协议核心保留 HTTP 状态、协议 code 与 message;公开适配器映射为 OpenAI、Anthropic 或 Gemini 错误对象。Chat、Responses、Anthropic Messages 与 Gemini GenerateContent 将媒体模型的普通文本作为文本结果输出;专用图片端点要求图片结果。HTTP/协议错误或缺失完成帧形成失败;上游 finish reason 作为正常终态保留并映射到各公开协议。
根 field 7 是 repeated Tool:
| 工具 | Tool 数组形状 |
|---|---|
| Function declarations | [null, [[name, description?, schema?], ...]] |
| Code Execution | [[]] |
| Google Search | [null,null,null,[null,[searchTypes]]],searchTypes 索引 0 为 [] |
| Image Search | 同一 Search tool,searchTypes 索引 1 为 [] |
| URL Context | 8 槽数组,索引 7 为 [] |
| Google Maps | 11 槽数组,索引 10 为 [] |
公开工具名称归一化后再生成上述 Tool 数组:
| AI Studio 工具 | OpenAI Chat / Responses | Anthropic | Gemini |
|---|---|---|---|
| function declarations | function |
空 type 或 custom |
functionDeclarations |
| Google Search | web_search、web_search_preview |
web_search* |
googleSearch、googleSearchRetrieval |
| Image Search | image_search |
— | imageSearch |
| URL Context | url_context |
web_fetch*、url_context* |
urlContext |
| Code Execution | code_interpreter |
code_execution* |
codeExecution |
| Google Maps | google_maps |
google_maps* |
googleMaps |
根 field 7 按请求声明逐项编码,函数声明和各类 Google 工具分别占用独立 Tool entry。模型的工具范围取自实时能力码。
函数 JSON Struct 使用 protobuf Struct/Value 数组:map 为 [[[key,value],...]];Value oneof 索引 0..5 分别表示 null、number、string、bool、Struct、ListValue。对象键排序后编码。
例如以下函数参数:
{
"city": "Taipei",
"days": 2,
"metric": true,
"note": null,
"units": ["C", "F"]
}编码后的 Struct 为:
[
[
["city", [null, null, "Taipei"]],
["days", [null, 2]],
["metric", [null, null, null, true]],
["note", [0]],
[
"units",
[
null,
null,
null,
null,
null,
[[[null, null, "C"], [null, null, "F"]]]
]
]
]
]完整 function call Part 的关键槽位为:
[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
["multiply", [[["a", [null, 21]], ["b", [null, 2]]]], "call_01"],
null,
null,
null,
"!THOUGHT_SIGNATURE"
]其中 Part 索引 10 保存 function call,索引 14 保存 thought signature。
函数参数和结构化输出 Schema 使用以下 protobuf fields:
| JSON Schema | Field | JSON Schema | Field |
|---|---|---|---|
type |
1 | format |
2 |
description |
3 | nullable |
4 |
enum |
5 | items |
6 |
properties |
7 | required |
8 |
minProperties |
9 | maxProperties |
10 |
minimum |
11 | maximum |
12 |
minLength |
13 | maxLength |
14 |
pattern |
15 | example |
16 |
oneOf |
17 | anyOf |
18 |
allOf |
19 | not |
20 |
maxItems |
21 | minItems |
22 |
propertyOrdering |
23 |
Schema 归一化规则:
| 输入结构 | 编码结果 |
|---|---|
$schema、default、additionalProperties、exclusiveMinimum |
从 wire schema 中省略 |
type: [T, "null"] |
根类型 T 与 nullable=true |
anyOf / oneOf 的 null 分支 |
移除 null 分支并设置 nullable=true |
多个非 null type |
首项作为根类型,完整类型集合写入 anyOf |
组合 Schema 缺少根 type |
首个带类型的分支作为根类型 |
| 其他 Schema 字段 | 返回 400 invalid_request / INVALID_ARGUMENT |
AI Studio 网页协议使用自动函数调用:auto 请求只携带根 field 7 的函数声明,由模型决定是否调用;none 省略 tools。客户端工具选择映射如下:
| 公开协议 | 接受 | 返回 400 |
|---|---|---|
| OpenAI Chat / Responses | 默认、auto、none |
required、named function |
| Anthropic | 默认、auto、none |
any、named tool |
| Gemini | 默认、AUTO、NONE |
ANY、allowedFunctionNames |
函数调用响应 Part 为 [name, Struct, callId?];下一轮 function result 使用同一形状并原样带回 thought signature。公开协议的 tool result 只有 call ID 时,实现从同一 contents 链的先前 function call 恢复函数名,查找失败返回参数错误。函数参数和结果使用 JSON object,标量或数组结果封装为 {"result":<VALUE>}。
GenerateAccessToken ["users/me"]
-> response ["<BEARER_TOKEN>"]
-> POST Drive multipart/related
part 1: {"mimeType":"<MIME>","name":"<NAME>"}
part 2: raw bytes
-> {"id":"<FILE_ID>"}
-> GenerateContent Part field 6 ["<FILE_ID>"]
Drive token、上传、提示引用和下载使用创建账户固定出口。文件 ID 与账户绑定写入 runtime-state.json;同一请求内的多个 Drive file 必须属于同一账户。
三类媒体复用 GenerateContent:
| 路由 | generation config | 响应 |
|---|---|---|
| Nano image | modalities [2],image config [aspectRatio?, imageSize?] |
Part field 3 [mime, base64] |
| TTS | modalities [3],speech config |
Part field 3 音频 chunk |
| Lyria | modalities [3] |
Part field 3 音频 chunk |
单声音 speech config 为 [[[voiceName]]]。多说话人 speech config 为 [null,null,[null,[[speaker,[[voiceName]]],...]]]。相邻且 MIME 相同的音频 Part 按到达顺序拼接。图片宽高比、图片分辨率与 TTS voice 必须来自当前模型能力选项。
GenerateVideo 使用 8 槽数组,WAA proof 位于 field 8:
[
"models/<MODEL_ID>",
"<PROMPT>",
[1, "<ASPECT_RATIO>", ["<SECONDS>"], "<RESOLUTION>"],
["<IMAGE_MIME>", "<BASE64>"] | null,
["<DRIVE_FILE_ID>"] | null,
null,
null,
"<WAA_PROOF>"
]起始帧只能选择 inline image 或 Drive file。创建响应 field 1 是 operation ID。轮询请求为 ["<OPERATION_ID>"];轮询响应 field 1 是 done,产物 Drive file ID 位于 $[1][0][0][0]。operation 与结果 file 均绑定创建账户,再通过 Drive bearer 下载媒体。count、宽高比、秒数和分辨率按实时模型 field 71 校验。
| 协议 | 端点 |
|---|---|
| OpenAI Chat | GET /v1/models、POST /v1/chat/completions |
| OpenAI Responses | POST /v1/responses |
| OpenAI 媒体 | POST /v1/images/generations、POST /v1/audio/speech、POST /v1/videos、GET /v1/videos/{id}、GET /v1/videos/{id}/content |
| Anthropic | POST /v1/messages、POST /v1/messages/count_tokens |
| Gemini | GET /v1beta/models、GET /v1beta/models/{model}、POST /v1beta/models/{model}:generateContent、:streamGenerateContent、:countTokens、:predictLongRunning、GET /v1beta/operations/{id} |
公开 /v1 与 /v1beta 接受 Authorization: Bearer、X-API-Key、X-Goog-API-Key 或 ?key=。配置为空时关闭本地 API key 校验。/api 控制面仅允许 loopback;GET /health 返回管理进程健康状态。
| 控制能力 | 端点 |
|---|---|
| 状态与模型 | GET /api/status、GET /api/models |
| 生成服务 | POST /api/control/start、POST /api/control/stop |
| 账户 | GET /api/accounts、POST /api/accounts、PUT /api/accounts/{id}、DELETE /api/accounts/{id} |
| 账户认证 | POST /api/accounts/{id}/login、POST /api/accounts/{id}/verify |
| 配置 | GET /api/config、PUT /api/config |
| 冷却与请求 | GET /api/cooldowns、DELETE /api/cooldowns?account_id={id}、GET /api/requests、POST /api/requests/{id}/cancel |
| 日志与事件 | DELETE /api/logs、GET /api/events |
运行状态机:
process start
-> control plane ready
-> data plane stopped
POST /api/control/start
-> refresh account model catalogs
-> prewarm up to WARM_WORKER_LIMIT workers
with WARM_STARTUP_CONCURRENCY bootstraps
-> first worker ready
-> data plane ready
request
-> match model + method
-> acquire one PER_ACCOUNT_CONCURRENCY slot
-> prepare WAA proof
-> send MakerSuite RPC
-> stream frames
-> release slot
POST /api/control/stop
-> cancel active requests
-> close WAA workers
-> data plane stopped
stopped 状态下生成与计数端点返回 503 service_stopped。模型路由从支持目标模型与方法的 ready 账户中轮询,冷却时加载合格备用账户,无可用账户时返回 400 account_required。
模型目录投影:
| 规则 | 结果 |
|---|---|
| OpenAI | GET /v1/models 返回 OpenAI model list |
| Anthropic | GET /v1/models 携带 Anthropic-Version 时返回 Anthropic model list |
| Gemini | 模型名称使用 models/<ID> |
| 多账户同模型 | generation methods 与能力选项取并集 |
| 多账户 token limit | 输入和输出上限分别取正数最小值 |
| 模型别名 | 来自 ListModels field 57 |
| 请求匹配 | model ID/alias 与 method 同时命中目录后进入账户调度 |
主要请求合同:
| 端点 | 必需字段 | 主要结果 |
|---|---|---|
/v1/chat/completions |
model、非空 messages |
Chat completion 或增量 chunk |
/v1/responses |
model、input |
Response object 或 response.* 事件 |
/v1/messages |
model、非空 messages、max_tokens |
Anthropic message 或 message 事件 |
:generateContent / :streamGenerateContent |
非空 contents |
Gemini candidates、usage 与 grounding metadata |
/v1/images/generations |
model、prompt,n 只能为 1 |
b64_json 或 data URL |
/v1/audio/speech |
model、input |
WAV、PCM 或 MP3 body |
/v1/videos |
model、prompt |
长任务对象,随后轮询并下载内容 |
四套生成入口共享同一规范请求,输入映射如下:
| 能力 | OpenAI Chat | OpenAI Responses | Anthropic | Gemini |
|---|---|---|---|---|
| system | system / developer messages |
instructions 和 system/developer message items |
system 字符串或 text blocks |
systemInstruction text parts |
| text | 字符串或 text content part | 字符串、message item | 字符串或 text block | Part text |
| image/document | Base64 data URL、file_id |
input_image、input_file |
base64 source 或 URL source | inlineData、fileData |
| audio input | input_audio Base64 |
message content 中的 input_audio |
base64 document source | inlineData |
| YouTube | video_url / input_video |
input_video |
URL source | fileData.fileUri |
| function call | assistant tool_calls |
function_call item |
tool_use block |
functionCall Part |
| function result | tool message | function_call_output item |
tool_result block |
functionResponse Part |
| structured output | response_format |
text.format |
— | responseMimeType 与 response schema |
| thinking | reasoning_effort 或 reasoning.effort |
reasoning.effort |
thinking.budget_tokens、output_config.effort |
thinkingConfig |
生成参数映射:
| 参数 | 规则 |
|---|---|
| OpenAI max tokens | max_completion_tokens 优先于 max_tokens |
| Anthropic max tokens | max_tokens 映射 generation config field 4 |
| Gemini max tokens | maxOutputTokens 映射 generation config field 4 |
| temperature / topP / topK / seed | 映射 generation config fields 5 / 6 / 7 / 19 |
| stop sequence | 映射 generation config field 2 |
| structured output | MIME type 映射 field 8,Schema 映射 field 9 |
| frequency / presence penalty | 0 采用 AI Studio 默认值,非零值返回 400 invalid_request |
Responses parallel_tool_calls |
写入响应合同元数据,函数调用仍采用 AI Studio auto 模式 |
流式端点统一使用 text/event-stream,每个 SSE frame 以空行结束:
| 协议 | 首事件 | 内容序列 | usage | 终止事件 |
|---|---|---|---|---|
| OpenAI Chat | assistant role chunk | chat completion delta | include_usage=true 时位于 finish chunk 之后 |
data: [DONE] |
| OpenAI Responses | response.created、response.in_progress |
output item / content part / delta / done | 完成 response 的 usage |
response.completed 或 response.incomplete |
| Anthropic | message_start |
content_block_start、delta、content_block_stop |
message_delta.usage |
message_stop |
| Gemini | candidate Part | GenerateContentResponse 增量 |
最后一帧 usageMetadata |
最后一帧 finish reason |
公开适配规则:
| 规范事件 | OpenAI Chat | Responses | Anthropic | Gemini |
|---|---|---|---|---|
| text | message/content delta | output_text | text block | candidate text Part |
| reasoning | reasoning_content |
reasoning summary | thinking block | thought Part |
| function | tool_calls |
function_call item | tool_use block | functionCall Part |
| function result | tool message | function_call_output | tool_result | functionResponse Part |
| code execution | 可读 Markdown | code_interpreter item | text block | executableCode/result Part |
| grounding/citation | annotations | output annotations | text sources | groundingMetadata |
| media | data URL/媒体端点 | output content | content block | inlineData Part |
| usage | prompt/completion/total | input/output/total | input/output | prompt/candidates/thoughts/total |
OpenAI Chat 使用 Markdown data URL 承载生成图片;客户端把 assistant message.content 回传下一轮时,适配器将其中的图片恢复为 inline data Part,保留图片多轮上下文。
用户文本中的 youtu.be/<ID>、youtube.com/watch?v=<ID>、/shorts/<ID>、/live/<ID> 和 /embed/<ID> 会转换为 video/* 外部媒体 part,并从用户 text part 中移除;重复 URL 合并为一个附件。OpenAI video_url/input_video、Anthropic URL source 与 Gemini fileData.fileUri 使用相同的外部媒体编码。
OpenAI Responses 的 previous_response_id 在进程内保存最多 256 个响应节点并重建完整 contents;重启后客户端重新提交完整上下文。Drive 与 Veo 资源绑定持久化到磁盘。
模型、参数、账户与上游错误按下方状态表投影。客户端取消会关闭上游 reader并释放账户租约。
错误对象与状态语义:
| 情况 | HTTP | OpenAI | Anthropic | Gemini |
|---|---|---|---|---|
| 参数、Schema、tool choice 无效 | 400 | invalid_request |
invalid_request_error |
INVALID_ARGUMENT |
| 本地 API key 无效 | 401 | invalid_api_key |
authentication_error |
UNAUTHENTICATED |
| 模型或方法不存在 | 404 | model_not_found |
not_found_error |
NOT_FOUND |
| 上游拒绝权限 | 403 | upstream_error |
permission_error |
PERMISSION_DENIED |
| 上游配额或限流 | 429 | upstream_error |
rate_limit_error |
RESOURCE_EXHAUSTED |
| 生成服务已停止 | 503 | service_stopped |
api_error |
UNAVAILABLE |
| 请求期限到期 | 504 | upstream_error |
api_error |
DEADLINE_EXCEEDED |
| 传输、Content-Type、解码或缺失终态 | 502 | upstream_error |
api_error |
INTERNAL |
错误对象 raw body:
OpenAI Chat / Responses
{
"error": {
"message": "upstream response ended before finish frame",
"type": "api_error",
"code": "upstream_error"
}
}Anthropic
{
"type": "error",
"error": {
"type": "api_error",
"message": "upstream response ended before finish frame"
}
}Gemini
{
"error": {
"code": 502,
"message": "upstream response ended before finish frame",
"status": "INTERNAL"
}
}已开始流式响应后的终止原文:
# OpenAI Chat
data: {"error":{"message":"...","type":"api_error","code":"upstream_error"}}
# OpenAI Responses
event: response.failed
data: {"response":{"id":"resp_...","object":"response","status":"failed","error":{"code":"upstream_error","message":"..."}}}
# Anthropic
event: error
data: {"type":"error","error":{"type":"api_error","message":"..."}}
# Gemini
data: {"error":{"code":502,"message":"...","status":"INTERNAL"}}
MakerSuite 错误解析:
| 来源 | 路径 | 公开结果 |
|---|---|---|
| HTTP status | response status | 保留原状态码 |
| protocol code | $[1][0] |
映射到协议 error code/type/status |
| protocol message | $[1][1] |
写入公开错误的 message |
| 原始形状 | [null,[code,message,...]] |
解析后进入统一错误事件 |
请求生命周期:
| 阶段 | HTTP / SSE 行为 | 资源状态 |
|---|---|---|
| response headers 前失败 | 返回对应 HTTP status 与协议 JSON error | 释放账户槽位 |
| SSE 已开始后失败 | 发送 OpenAI error、response.failed、Anthropic error 或 Gemini error frame |
关闭上游 reader并释放账户槽位 |
| 完成帧 | 输出 finish reason、usage 与协议终止事件 | 合并 Set-Cookie并释放账户槽位 |
| 客户端取消 | 结束上游读取 | 取消请求上下文并释放账户槽位 |
欢迎二次开发,如果对你有帮助,考虑给仓库点一个Star~