add chat.headers hook, adjust codex and copilot plugins to use it
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
import type { Hooks, PluginInput } from "@opencode-ai/plugin"
|
import type { Hooks, PluginInput } from "@opencode-ai/plugin"
|
||||||
import { Log } from "../util/log"
|
import { Log } from "../util/log"
|
||||||
import { OAUTH_DUMMY_KEY } from "../auth"
|
import { Installation } from "../installation"
|
||||||
import { ProviderTransform } from "../provider/transform"
|
import { Auth, OAUTH_DUMMY_KEY } from "../auth"
|
||||||
|
import os from "os"
|
||||||
|
|
||||||
const log = Log.create({ service: "plugin.codex" })
|
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
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ const CLIENT_ID = "Ov23li8tweQw6odWQebz"
|
|||||||
// Add a small safety buffer when polling to avoid hitting the server
|
// Add a small safety buffer when polling to avoid hitting the server
|
||||||
// slightly too early due to clock skew / timer drift.
|
// slightly too early due to clock skew / timer drift.
|
||||||
const OAUTH_POLLING_SAFETY_MARGIN_MS = 3000 // 3 seconds
|
const OAUTH_POLLING_SAFETY_MARGIN_MS = 3000 // 3 seconds
|
||||||
|
|
||||||
function normalizeDomain(url: string) {
|
function normalizeDomain(url: string) {
|
||||||
return url.replace(/^https?:\/\//, "").replace(/\/$/, "")
|
return url.replace(/^https?:\/\//, "").replace(/\/$/, "")
|
||||||
}
|
}
|
||||||
@@ -19,6 +18,7 @@ function getUrls(domain: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function CopilotAuthPlugin(input: PluginInput): Promise<Hooks> {
|
export async function CopilotAuthPlugin(input: PluginInput): Promise<Hooks> {
|
||||||
|
const sdk = input.client
|
||||||
return {
|
return {
|
||||||
auth: {
|
auth: {
|
||||||
provider: "github-copilot",
|
provider: "github-copilot",
|
||||||
@@ -83,11 +83,11 @@ export async function CopilotAuthPlugin(input: PluginInput): Promise<Hooks> {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const headers: Record<string, string> = {
|
const headers: Record<string, string> = {
|
||||||
|
"x-initiator": isAgent ? "agent" : "user",
|
||||||
...(init?.headers as Record<string, string>),
|
...(init?.headers as Record<string, string>),
|
||||||
"User-Agent": `opencode/${Installation.VERSION}`,
|
"User-Agent": `opencode/${Installation.VERSION}`,
|
||||||
Authorization: `Bearer ${info.refresh}`,
|
Authorization: `Bearer ${info.refresh}`,
|
||||||
"Openai-Intent": "conversation-edits",
|
"Openai-Intent": "conversation-edits",
|
||||||
"X-Initiator": isAgent ? "agent" : "user",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isVision) {
|
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"
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ export namespace LLM {
|
|||||||
.tag("sessionID", input.sessionID)
|
.tag("sessionID", input.sessionID)
|
||||||
.tag("small", (input.small ?? false).toString())
|
.tag("small", (input.small ?? false).toString())
|
||||||
.tag("agent", input.agent.name)
|
.tag("agent", input.agent.name)
|
||||||
|
.tag("mode", input.agent.mode)
|
||||||
l.info("stream", {
|
l.info("stream", {
|
||||||
modelID: input.model.id,
|
modelID: input.model.id,
|
||||||
providerID: input.model.providerID,
|
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
|
const maxOutputTokens = isCodex
|
||||||
? undefined
|
? undefined
|
||||||
: ProviderTransform.maxOutputTokens(
|
: ProviderTransform.maxOutputTokens(
|
||||||
@@ -198,13 +213,6 @@ export namespace LLM {
|
|||||||
maxOutputTokens,
|
maxOutputTokens,
|
||||||
abortSignal: input.abort,
|
abortSignal: input.abort,
|
||||||
headers: {
|
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")
|
...(input.model.providerID.startsWith("opencode")
|
||||||
? {
|
? {
|
||||||
"x-opencode-project": Instance.project.id,
|
"x-opencode-project": Instance.project.id,
|
||||||
@@ -218,6 +226,7 @@ export namespace LLM {
|
|||||||
}
|
}
|
||||||
: undefined),
|
: undefined),
|
||||||
...input.model.headers,
|
...input.model.headers,
|
||||||
|
...headers,
|
||||||
},
|
},
|
||||||
maxRetries: input.retries ?? 0,
|
maxRetries: input.retries ?? 0,
|
||||||
messages: [
|
messages: [
|
||||||
|
|||||||
@@ -172,6 +172,10 @@ export interface Hooks {
|
|||||||
input: { sessionID: string; agent: string; model: Model; provider: ProviderContext; message: UserMessage },
|
input: { sessionID: string; agent: string; model: Model; provider: ProviderContext; message: UserMessage },
|
||||||
output: { temperature: number; topP: number; topK: number; options: Record<string, any> },
|
output: { temperature: number; topP: number; topK: number; options: Record<string, any> },
|
||||||
) => Promise<void>
|
) => 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>
|
"permission.ask"?: (input: Permission, output: { status: "ask" | "deny" | "allow" }) => Promise<void>
|
||||||
"command.execute.before"?: (
|
"command.execute.before"?: (
|
||||||
input: { command: string; sessionID: string; arguments: string },
|
input: { command: string; sessionID: string; arguments: string },
|
||||||
|
|||||||
Reference in New Issue
Block a user