From 1ecf27f3891e7d57022e723af5b9aa8ba2e60452 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Wed, 20 May 2026 21:55:45 -0400 Subject: [PATCH] refactor(opencode): pass prepared request to native runtime --- packages/opencode/src/session/llm.ts | 11 +---- .../src/session/llm/native-request.ts | 15 ++++--- .../src/session/llm/native-runtime.ts | 40 +++++++++---------- packages/opencode/src/session/llm/request.ts | 6 +-- 4 files changed, 29 insertions(+), 43 deletions(-) diff --git a/packages/opencode/src/session/llm.ts b/packages/opencode/src/session/llm.ts index 23cefe1181..157044d45f 100644 --- a/packages/opencode/src/session/llm.ts +++ b/packages/opencode/src/session/llm.ts @@ -220,17 +220,8 @@ const live: Layer.Layer< provider: item, auth: info, llmClient, - isOpenaiOauth: prepared.isOpenaiOauth, - system: prepared.system, - messages: prepared.messages, - tools: prepared.tools, + request: prepared, toolChoice: input.toolChoice, - temperature: prepared.params.temperature, - topP: prepared.params.topP, - topK: prepared.params.topK, - maxOutputTokens: prepared.params.maxOutputTokens, - providerOptions: prepared.params.options, - headers: prepared.headers, abort: input.abort, }) if (native.type === "supported") { diff --git a/packages/opencode/src/session/llm/native-request.ts b/packages/opencode/src/session/llm/native-request.ts index 21e6413a29..d6532d63c9 100644 --- a/packages/opencode/src/session/llm/native-request.ts +++ b/packages/opencode/src/session/llm/native-request.ts @@ -12,26 +12,25 @@ import { import type { ModelMessage } from "ai" import type { Provider } from "@/provider/provider" import { isRecord } from "@/util/record" +import type { Prepared as PreparedRequest } from "./request" type ToolInput = { readonly description?: string readonly inputSchema?: unknown } -export type RequestInput = { +type GenerationInput = Omit + +export type RequestInput = GenerationInput & { readonly model: Provider.Model readonly apiKey?: string readonly baseURL?: string - readonly system?: readonly string[] - readonly messages: readonly ModelMessage[] + readonly system?: PreparedRequest["system"] + readonly messages: PreparedRequest["messages"] readonly tools?: Record readonly toolChoice?: "auto" | "required" | "none" - readonly temperature?: number - readonly topP?: number - readonly topK?: number - readonly maxOutputTokens?: number readonly providerOptions?: LLMRequest["providerOptions"] - readonly headers?: Record + readonly headers?: PreparedRequest["headers"] } const providerMetadata = (value: unknown): ProviderMetadata | undefined => { diff --git a/packages/opencode/src/session/llm/native-runtime.ts b/packages/opencode/src/session/llm/native-runtime.ts index b0cc811d4e..5a2f0deef4 100644 --- a/packages/opencode/src/session/llm/native-runtime.ts +++ b/packages/opencode/src/session/llm/native-runtime.ts @@ -3,12 +3,13 @@ import type { Provider } from "@/provider/provider" import { ProviderTransform } from "@/provider/transform" import { errorMessage } from "@/util/error" import { isRecord } from "@/util/record" -import { asSchema, type ModelMessage, type Tool } from "ai" +import { asSchema, type Tool } from "ai" import { Effect } from "effect" import * as Stream from "effect/Stream" import { tool as nativeTool, ToolFailure, type JsonSchema, type LLMEvent } from "@opencode-ai/llm" import type { LLMClientShape } from "@opencode-ai/llm/route" import { LLMNative } from "./native-request" +import type { Prepared as PreparedRequest } from "./request" export type RuntimeStatus = | { readonly type: "supported"; readonly apiKey: string; readonly baseURL?: string } @@ -22,17 +23,13 @@ type StreamInput = { readonly provider: Provider.Info readonly auth: Auth.Info | undefined readonly llmClient: LLMClientShape - readonly isOpenaiOauth: boolean - readonly system: string[] - readonly messages: ModelMessage[] - readonly tools: Record + readonly request: PreparedRequest readonly toolChoice?: "auto" | "required" | "none" - readonly temperature?: number - readonly topP?: number - readonly topK?: number - readonly maxOutputTokens?: number - readonly providerOptions?: Record - readonly headers: Record + readonly abort: AbortSignal +} + +type ToolContext = { + readonly messages: PreparedRequest["messages"] readonly abort: AbortSignal } @@ -68,17 +65,18 @@ export function stream(input: StreamInput): StreamResult { model: input.model, apiKey: current.apiKey, baseURL: current.baseURL, - system: input.isOpenaiOauth ? input.system : [], - messages: ProviderTransform.message(input.messages, input.model, input.providerOptions ?? {}), + system: [], + messages: ProviderTransform.message(input.request.messages, input.model, input.request.params.options), + tools: input.request.tools, toolChoice: input.toolChoice, - temperature: input.temperature, - topP: input.topP, - topK: input.topK, - maxOutputTokens: input.maxOutputTokens, - providerOptions: ProviderTransform.providerOptions(input.model, input.providerOptions ?? {}), - headers: { ...providerHeaders(input.provider.options.headers), ...input.headers }, + temperature: input.request.params.temperature, + topP: input.request.params.topP, + topK: input.request.params.topK, + maxOutputTokens: input.request.params.maxOutputTokens, + providerOptions: ProviderTransform.providerOptions(input.model, input.request.params.options), + headers: { ...providerHeaders(input.provider.options.headers), ...input.request.headers }, }), - tools: nativeTools(input.tools, input), + tools: nativeTools(input.request.tools, { messages: input.request.messages, abort: input.abort }), }), } } @@ -97,7 +95,7 @@ function nativeSchema(value: unknown): JsonSchema { return asSchema(value as Parameters[0]).jsonSchema as JsonSchema } -export function nativeTools(tools: Record, input: Pick) { +export function nativeTools(tools: Record, input: ToolContext) { return Object.fromEntries( Object.entries(tools).map(([name, item]) => [ name, diff --git a/packages/opencode/src/session/llm/request.ts b/packages/opencode/src/session/llm/request.ts index 97a539eadc..52e731b2f5 100644 --- a/packages/opencode/src/session/llm/request.ts +++ b/packages/opencode/src/session/llm/request.ts @@ -34,7 +34,6 @@ type PrepareInput = { } export type Prepared = { - readonly isOpenaiOauth: boolean readonly system: string[] readonly messages: ModelMessage[] readonly tools: Record @@ -123,7 +122,7 @@ export const prepare = Effect.fn("LLMRequestPrep.prepare")(function* (input: Pre }, ) - const { headers } = yield* input.plugin.trigger( + const { headers: pluginHeaders } = yield* input.plugin.trigger( "chat.headers", { sessionID: input.sessionID, @@ -161,7 +160,6 @@ export const prepare = Effect.fn("LLMRequestPrep.prepare")(function* (input: Pre : undefined return { - isOpenaiOauth, system, messages, tools: Object.fromEntries(Object.entries(tools).toSorted(([a], [b]) => a.localeCompare(b))), @@ -182,7 +180,7 @@ export const prepare = Effect.fn("LLMRequestPrep.prepare")(function* (input: Pre "User-Agent": USER_AGENT, }), ...input.model.headers, - ...headers, + ...pluginHeaders, }, } })