feat(copilot): send X-Interaction-Id header with session id (#47215)

Co-authored-by: rekram1-node <rekram1-node@users.noreply.github.com>
This commit is contained in:
opencode-agent[bot] 2026-09-03 23:24:55 -05:00 committed by GitHub
parent 8a6cf2c9aa
commit c0f09afef5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 57 additions and 0 deletions

View file

@ -361,6 +361,7 @@ export async function CopilotAuthPlugin(input: PluginInput): Promise<Hooks> {
if (!incoming.model.providerID.includes("github-copilot")) return
output.headers["X-GitHub-Api-Version"] = API_VERSION
output.headers["X-Interaction-Id"] = incoming.sessionID
if (incoming.agent === "title") {
output.headers["X-Interaction-Type"] = "agent-session-name-generation"
}

View file

@ -0,0 +1,56 @@
import { expect, test } from "bun:test"
import type { Hooks } from "@opencode-ai/plugin"
import { CopilotAuthPlugin } from "@/plugin/github-copilot/copilot"
type ChatHeaders = NonNullable<Hooks["chat.headers"]>
async function hook() {
const hooks = await CopilotAuthPlugin({
directory: "",
project: {} as never,
worktree: "",
experimental_workspace: { register() {} },
serverUrl: new URL("http://localhost"),
$: {} as never,
client: {
session: {
message: async () => ({ data: { parts: [] } }),
get: async () => ({ data: {} }),
},
} as never,
})
return hooks["chat.headers"]!
}
function input(sessionID: string, providerID: string, npm: string) {
return {
sessionID,
agent: "build",
model: { providerID, api: { npm } },
message: { id: "msg_test", sessionID },
} as Parameters<ChatHeaders>[0]
}
test.each([
["github-copilot", "@ai-sdk/github-copilot"],
["github-copilot", "@ai-sdk/anthropic"],
["github-copilot-enterprise", "@ai-sdk/github-copilot"],
["github-copilot-enterprise", "@ai-sdk/anthropic"],
])("uses the session ID for %s interaction headers with %s", async (providerID, npm) => {
const headers = await hook()
for (const sessionID of ["ses_one", "ses_one", "ses_two"]) {
const output = { headers: { "x-existing": "preserved" } }
await headers(input(sessionID, providerID, npm), output)
expect(output.headers).toMatchObject({
"X-Interaction-Id": sessionID,
"x-existing": "preserved",
})
}
})
test("does not add interaction headers to other providers", async () => {
const headers = await hook()
const output = { headers: { "x-existing": "preserved" } }
await headers(input("ses_one", "openai", "@ai-sdk/openai"), output)
expect(output.headers).toEqual({ "x-existing": "preserved" })
})