summaryrefslogtreecommitdiffhomepage
path: root/packages
diff options
context:
space:
mode:
authorAiden Cline <[email protected]>2026-01-21 15:09:56 -0600
committerAiden Cline <[email protected]>2026-01-21 15:10:08 -0600
commitc89f6e7ac61e0dd5404888df87555627efce6087 (patch)
treeec91cad94ac94ab931bf2f441b483ddd316adb82 /packages
parent17a5f75b543b2a6f30fecc87b3c5444e9264d239 (diff)
downloadopencode-c89f6e7ac61e0dd5404888df87555627efce6087.tar.gz
opencode-c89f6e7ac61e0dd5404888df87555627efce6087.zip
add chat.headers hook, adjust codex and copilot plugins to use it
Diffstat (limited to 'packages')
-rw-r--r--packages/opencode/src/plugin/codex.ts11
-rw-r--r--packages/opencode/src/plugin/copilot.ts18
-rw-r--r--packages/opencode/src/session/llm.ts23
-rw-r--r--packages/plugin/src/index.ts4
4 files changed, 45 insertions, 11 deletions
diff --git a/packages/opencode/src/plugin/codex.ts b/packages/opencode/src/plugin/codex.ts
index fc172dad9..3e31c6ce4 100644
--- a/packages/opencode/src/plugin/codex.ts
+++ b/packages/opencode/src/plugin/codex.ts
@@ -1,7 +1,8 @@
import type { Hooks, PluginInput } from "@opencode-ai/plugin"
import { Log } from "../util/log"
-import { OAUTH_DUMMY_KEY } from "../auth"
-import { ProviderTransform } from "../provider/transform"
+import { Installation } from "../installation"
+import { Auth, OAUTH_DUMMY_KEY } from "../auth"
+import os from "os"
const log = Log.create({ service: "plugin.codex" })
@@ -489,5 +490,11 @@ export async function CodexAuthPlugin(input: PluginInput): Promise<Hooks> {
},
],
},
+ "chat.headers": async (input, output) => {
+ if (input.model.providerID !== "openai") return
+ output.headers.originator = "opencode"
+ output.headers["User-Agent"] = `opencode/${Installation.VERSION} (${os.platform()} ${os.release()}; ${os.arch()})`
+ output.headers.session_id = input.sessionID
+ },
}
}
diff --git a/packages/opencode/src/plugin/copilot.ts b/packages/opencode/src/plugin/copilot.ts
index 932b3fd6a..bf0f91dcd 100644
--- a/packages/opencode/src/plugin/copilot.ts
+++ b/packages/opencode/src/plugin/copilot.ts
@@ -6,7 +6,6 @@ const CLIENT_ID = "Ov23li8tweQw6odWQebz"
// Add a small safety buffer when polling to avoid hitting the server
// slightly too early due to clock skew / timer drift.
const OAUTH_POLLING_SAFETY_MARGIN_MS = 3000 // 3 seconds
-
function normalizeDomain(url: string) {
return url.replace(/^https?:\/\//, "").replace(/\/$/, "")
}
@@ -19,6 +18,7 @@ function getUrls(domain: string) {
}
export async function CopilotAuthPlugin(input: PluginInput): Promise<Hooks> {
+ const sdk = input.client
return {
auth: {
provider: "github-copilot",
@@ -83,11 +83,11 @@ export async function CopilotAuthPlugin(input: PluginInput): Promise<Hooks> {
})
const headers: Record<string, string> = {
+ "x-initiator": isAgent ? "agent" : "user",
...(init?.headers as Record<string, string>),
"User-Agent": `opencode/${Installation.VERSION}`,
Authorization: `Bearer ${info.refresh}`,
"Openai-Intent": "conversation-edits",
- "X-Initiator": isAgent ? "agent" : "user",
}
if (isVision) {
@@ -265,5 +265,19 @@ export async function CopilotAuthPlugin(input: PluginInput): Promise<Hooks> {
},
],
},
+ "chat.headers": async (input, output) => {
+ if (!input.model.providerID.includes("github-copilot")) return
+ const session = await sdk.session
+ .get({
+ path: {
+ id: input.sessionID,
+ },
+ throwOnError: true,
+ })
+ .catch(() => undefined)
+ if (!session || !session.data.parentID) return
+ // TODO: mark subagent sessions as agent initiated once copilot gives ok
+ // output.headers["x-initiator"] = "agent"
+ },
}
}
diff --git a/packages/opencode/src/session/llm.ts b/packages/opencode/src/session/llm.ts
index 1029b45ea..e73f20403 100644
--- a/packages/opencode/src/session/llm.ts
+++ b/packages/opencode/src/session/llm.ts
@@ -53,6 +53,7 @@ export namespace LLM {
.tag("sessionID", input.sessionID)
.tag("small", (input.small ?? false).toString())
.tag("agent", input.agent.name)
+ .tag("mode", input.agent.mode)
l.info("stream", {
modelID: input.model.id,
providerID: input.model.providerID,
@@ -131,6 +132,20 @@ export namespace LLM {
},
)
+ const { headers } = await Plugin.trigger(
+ "chat.headers",
+ {
+ sessionID: input.sessionID,
+ agent: input.agent,
+ model: input.model,
+ provider,
+ message: input.user,
+ },
+ {
+ headers: {},
+ },
+ )
+
const maxOutputTokens = isCodex
? undefined
: ProviderTransform.maxOutputTokens(
@@ -198,13 +213,6 @@ export namespace LLM {
maxOutputTokens,
abortSignal: input.abort,
headers: {
- ...(isCodex
- ? {
- originator: "opencode",
- "User-Agent": `opencode/${Installation.VERSION} (${os.platform()} ${os.release()}; ${os.arch()})`,
- session_id: input.sessionID,
- }
- : undefined),
...(input.model.providerID.startsWith("opencode")
? {
"x-opencode-project": Instance.project.id,
@@ -218,6 +226,7 @@ export namespace LLM {
}
: undefined),
...input.model.headers,
+ ...headers,
},
maxRetries: input.retries ?? 0,
messages: [
diff --git a/packages/plugin/src/index.ts b/packages/plugin/src/index.ts
index 36a4657d7..d02c8bfe5 100644
--- a/packages/plugin/src/index.ts
+++ b/packages/plugin/src/index.ts
@@ -172,6 +172,10 @@ export interface Hooks {
input: { sessionID: string; agent: string; model: Model; provider: ProviderContext; message: UserMessage },
output: { temperature: number; topP: number; topK: number; options: Record<string, any> },
) => Promise<void>
+ "chat.headers"?: (
+ input: { sessionID: string; agent: string; model: Model; provider: ProviderContext; message: UserMessage },
+ output: { headers: Record<string, string> },
+ ) => Promise<void>
"permission.ask"?: (input: Permission, output: { status: "ask" | "deny" | "allow" }) => Promise<void>
"command.execute.before"?: (
input: { command: string; sessionID: string; arguments: string },