Explorar o código

add chat.headers hook, adjust codex and copilot plugins to use it

Aiden Cline hai 2 meses
pai
achega
c89f6e7ac6

+ 9 - 2
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
+    },
   }
 }

+ 16 - 2
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"
+    },
   }
 }

+ 16 - 7
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: [

+ 4 - 0
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 },