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
Continuationagent
子代理调用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}

  1. ~/.config/opencode/
  2. 项目/.opencode/
  3. ~/.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 压成了一次。

这类操作早晚可能被官方堵上,自行评估风险吧。


相关链接: