Copilot Premium Requests 优化指南:一个 Session 只花一次钱
众所周知,GitHub Copilot Plus 订阅的计费方式不是按 token 用量计费的,而是按一个叫做 premium requests 的次数来计费。而且这个次数还会根据不同模型乘以不同的权重倍率——比如 Claude Opus 4.5 每次请求乘以 3x,用起来刷刷地掉。
那到底什么请求才算一次 premium request?
X-Initiator:计费的关键
根据 opencode#8721 这个 PR 的发现,Copilot 的计费逻辑取决于 HTTP 请求头中的 X-Initiator 字段:
X-Initiator: user → 计费
X-Initiator: agent → 不计费只有 user 的请求会被计入 premium requests,agent 的请求不计费。
VSCode 官方的做法
看一下 VSCode 官方 Copilot 插件(microsoft/vscode-copilot-chat)的实现:
// toolCallingLoop.ts:469
userInitiatedRequest: iterationNumber === 0
&& !isContinuation
&& !this.options.request.subAgentInvocationId简单说:
| 场景 | X-Initiator | 计费? |
|---|---|---|
| 你发的第一条消息 | user | 是 |
| 工具调用循环 | agent | 否 |
| Continuation | agent | 否 |
| 子代理调用 | agent | 否 |
在 VSCode 的实现里,每次发送新的 prompt 算一次 premium request,之后的 tool call、子代理、continuation 都不计费。
OpenCode 的问题
OpenCode 内置的 CopilotAuthPlugin 判断 isAgent 的逻辑有问题:
// 只检查最后一条消息的 role
isAgent: last?.role !== "user"问题在于 OpenCode 内部会创建很多 synthetic user messages(合成消息),比如消息压缩后的 "What did we do so far?"、工具返回结果、子任务消息等。这些合成消息的 role 都是 user,导致大量本不该计费的请求被标成了 user,白白烧掉 premium requests。
相关讨论:opencode#8030
激进方案:全标 agent(别这么干)
最直接的想法是把所有请求都标成 X-Initiator: agent,理论上全部免费。
但这风险很大。GitHub 检测到你 100% 都是 agent 请求、没有任何 user 请求,和正常使用行为完全不一样,封号概率不低。
我们的方案:Session 级别标记
思路是在 session 级别追踪:每个 session 第一次请求标 user,后续全部标 agent。
这和 VSCode 官方行为不完全一样(官方每次新 prompt 都算一次),但比 OpenCode 当前乱标的情况好太多了。说白了就是投机取巧,但至少不像全标 agent 那么激进。
效果
一个 session 内不管多少轮对话、多少次 tool call 和子代理调用,只消耗 1 次 premium request × 模型倍率。
插件实现
用 OpenCode 的插件系统写一个全局插件:
import type { Hooks, PluginInput } from "@opencode-ai/plugin"
export default async function CopilotInitiatorPlugin(
_input: PluginInput
): Promise<Hooks> {
const seenSessions = new Set<string>()
return {
"chat.headers": async (input, output) => {
if (!input.model.providerID.includes("github-copilot")) return
const sessionID = input.sessionID
if (seenSessions.has(sessionID)) {
output.headers["x-initiator"] = "agent"
} else {
seenSessions.add(sessionID)
output.headers["x-initiator"] = "user"
}
},
}
}为什么能覆盖内置逻辑?
自定义插件在内置 CopilotAuthPlugin 之后执行,内置插件先设 header,我们的插件再覆盖:
内置 CopilotAuthPlugin
→ headers["x-initiator"] = isAgent ? "agent" : "user" // 可能误判
自定义插件
→ headers["x-initiator"] = seenBefore ? "agent" : "user" // 覆盖
最终 HTTP 请求
→ 以我们的值为准安装
mkdir -p ~/.opencode/plugins
# 把上面的代码保存为 ~/.opencode/plugins/copilot-initiator.ts
# 重启 opencode 生效OpenCode 会自动扫描以下目录的 {plugin,plugins}/*.{ts,js}:
~/.config/opencode/项目/.opencode/~/.opencode/← 推荐
效果验证
装好之后看日志:
action=set session=ses_34b2de2f wasSeen=false reason=first-seen-session x-initiator=user
action=set session=ses_34b2de2f wasSeen=true reason=seen-session-before x-initiator=agent
action=set session=ses_34b2de2f wasSeen=true reason=seen-session-before x-initiator=agent
action=set session=ses_34b2de2f wasSeen=true reason=seen-session-before x-initiator=agent
...第一条 user,后面全是 agent。亲测 premium requests 掉得明显慢了。
一些补充
premium requests 不可能完全降到零:VSCode 的补全、聊天等客户端和 OpenCode 共享配额;每开一个新 session 还是要消耗一次。另外 GPT-5 mini、GPT-4.1 这些 included models 本身不消耗 premium requests,不受这个影响。
日常建议:能用免费模型就用免费模型,需要质量的时候再切 Claude;不用 VSCode Copilot 扩展的话关掉省点配额;尽量在一个 session 里把事情做完,少开新 session。
总结
| 方案 | 效果 | 风险 |
|---|---|---|
| 不优化(OpenCode 默认) | 大量请求被误标 user,配额掉得飞快 | 无 |
| 全标 agent | 理论全免费 | 极高,容易封号 |
| Session 级标记(本文方案) | 每个 session 只消耗 1 次 | 有一定风险,本质是投机取巧 |
说实话这个方案也是钻空子。虽然比全标 agent 温和不少,但和官方预期的行为还是有差距——VSCode 里每次新 prompt 都会算一次,我们是把整个 session 压成了一次。
这类操作早晚可能被官方堵上,自行评估风险吧。
相关链接:
