refactor: unwrap ACP namespace + self-reexport (#22936)

This commit is contained in:
Kit Langton
2026-04-17 00:00:50 +00:00
committed by GitHub
parent 19d15d9ff7
commit 1291e82bb4
+43 -43
View File
@@ -57,15 +57,14 @@ type ModelOption = { modelId: string; name: string }
const DEFAULT_VARIANT_VALUE = "default" const DEFAULT_VARIANT_VALUE = "default"
export namespace ACP { const log = Log.create({ service: "acp-agent" })
const log = Log.create({ service: "acp-agent" })
async function getContextLimit( async function getContextLimit(
sdk: OpencodeClient, sdk: OpencodeClient,
providerID: ProviderID, providerID: ProviderID,
modelID: ModelID, modelID: ModelID,
directory: string, directory: string,
): Promise<number | null> { ): Promise<number | null> {
const providers = await sdk.config const providers = await sdk.config
.providers({ directory }) .providers({ directory })
.then((x) => x.data?.providers ?? []) .then((x) => x.data?.providers ?? [])
@@ -77,14 +76,14 @@ export namespace ACP {
const provider = providers.find((p) => p.id === providerID) const provider = providers.find((p) => p.id === providerID)
const model = provider?.models[modelID] const model = provider?.models[modelID]
return model?.limit.context ?? null return model?.limit.context ?? null
} }
async function sendUsageUpdate( async function sendUsageUpdate(
connection: AgentSideConnection, connection: AgentSideConnection,
sdk: OpencodeClient, sdk: OpencodeClient,
sessionID: string, sessionID: string,
directory: string, directory: string,
): Promise<void> { ): Promise<void> {
const messages = await sdk.session const messages = await sdk.session
.messages({ sessionID, directory }, { throwOnError: true }) .messages({ sessionID, directory }, { throwOnError: true })
.then((x) => x.data) .then((x) => x.data)
@@ -127,17 +126,17 @@ export namespace ACP {
.catch((error) => { .catch((error) => {
log.error("failed to send usage update", { error }) log.error("failed to send usage update", { error })
}) })
} }
export async function init({ sdk: _sdk }: { sdk: OpencodeClient }) { export async function init({ sdk: _sdk }: { sdk: OpencodeClient }) {
return { return {
create: (connection: AgentSideConnection, fullConfig: ACPConfig) => { create: (connection: AgentSideConnection, fullConfig: ACPConfig) => {
return new Agent(connection, fullConfig) return new Agent(connection, fullConfig)
}, },
} }
} }
export class Agent implements ACPAgent { export class Agent implements ACPAgent {
private connection: AgentSideConnection private connection: AgentSideConnection
private config: ACPConfig private config: ACPConfig
private sdk: OpencodeClient private sdk: OpencodeClient
@@ -1547,9 +1546,9 @@ export namespace ACP {
{ throwOnError: true }, { throwOnError: true },
) )
} }
} }
function toToolKind(toolName: string): ToolKind { function toToolKind(toolName: string): ToolKind {
const tool = toolName.toLocaleLowerCase() const tool = toolName.toLocaleLowerCase()
switch (tool) { switch (tool) {
case "bash": case "bash":
@@ -1574,9 +1573,9 @@ export namespace ACP {
default: default:
return "other" return "other"
} }
} }
function toLocations(toolName: string, input: Record<string, any>): { path: string }[] { function toLocations(toolName: string, input: Record<string, any>): { path: string }[] {
const tool = toolName.toLocaleLowerCase() const tool = toolName.toLocaleLowerCase()
switch (tool) { switch (tool) {
case "read": case "read":
@@ -1591,9 +1590,9 @@ export namespace ACP {
default: default:
return [] return []
} }
} }
async function defaultModel(config: ACPConfig, cwd?: string): Promise<{ providerID: ProviderID; modelID: ModelID }> { async function defaultModel(config: ACPConfig, cwd?: string): Promise<{ providerID: ProviderID; modelID: ModelID }> {
const sdk = config.sdk const sdk = config.sdk
const configured = config.defaultModel const configured = config.defaultModel
if (configured) return configured if (configured) return configured
@@ -1653,11 +1652,11 @@ export namespace ACP {
if (specified) return specified if (specified) return specified
return { providerID: ProviderID.opencode, modelID: ModelID.make("big-pickle") } return { providerID: ProviderID.opencode, modelID: ModelID.make("big-pickle") }
} }
function parseUri( function parseUri(
uri: string, uri: string,
): { type: "file"; url: string; filename: string; mime: string } | { type: "text"; text: string } { ): { type: "file"; url: string; filename: string; mime: string } | { type: "text"; text: string } {
try { try {
if (uri.startsWith("file://")) { if (uri.startsWith("file://")) {
const path = uri.slice(7) const path = uri.slice(7)
@@ -1692,18 +1691,18 @@ export namespace ACP {
text: uri, text: uri,
} }
} }
} }
function getNewContent(fileOriginal: string, unifiedDiff: string): string | undefined { function getNewContent(fileOriginal: string, unifiedDiff: string): string | undefined {
const result = applyPatch(fileOriginal, unifiedDiff) const result = applyPatch(fileOriginal, unifiedDiff)
if (result === false) { if (result === false) {
log.error("Failed to apply unified diff (context mismatch)") log.error("Failed to apply unified diff (context mismatch)")
return undefined return undefined
} }
return result return result
} }
function sortProvidersByName<T extends { name: string }>(providers: T[]): T[] { function sortProvidersByName<T extends { name: string }>(providers: T[]): T[] {
return [...providers].sort((a, b) => { return [...providers].sort((a, b) => {
const nameA = a.name.toLowerCase() const nameA = a.name.toLowerCase()
const nameB = b.name.toLowerCase() const nameB = b.name.toLowerCase()
@@ -1711,23 +1710,23 @@ export namespace ACP {
if (nameA > nameB) return 1 if (nameA > nameB) return 1
return 0 return 0
}) })
} }
function modelVariantsFromProviders( function modelVariantsFromProviders(
providers: Array<{ id: string; models: Record<string, { variants?: Record<string, any> }> }>, providers: Array<{ id: string; models: Record<string, { variants?: Record<string, any> }> }>,
model: { providerID: ProviderID; modelID: ModelID }, model: { providerID: ProviderID; modelID: ModelID },
): string[] { ): string[] {
const provider = providers.find((entry) => entry.id === model.providerID) const provider = providers.find((entry) => entry.id === model.providerID)
if (!provider) return [] if (!provider) return []
const modelInfo = provider.models[model.modelID] const modelInfo = provider.models[model.modelID]
if (!modelInfo?.variants) return [] if (!modelInfo?.variants) return []
return Object.keys(modelInfo.variants) return Object.keys(modelInfo.variants)
} }
function buildAvailableModels( function buildAvailableModels(
providers: Array<{ id: string; name: string; models: Record<string, any> }>, providers: Array<{ id: string; name: string; models: Record<string, any> }>,
options: { includeVariants?: boolean } = {}, options: { includeVariants?: boolean } = {},
): ModelOption[] { ): ModelOption[] {
const includeVariants = options.includeVariants ?? false const includeVariants = options.includeVariants ?? false
return providers.flatMap((provider) => { return providers.flatMap((provider) => {
const unsorted: Array<{ id: string; name: string; variants?: Record<string, any> }> = Object.values( const unsorted: Array<{ id: string; name: string; variants?: Record<string, any> }> = Object.values(
@@ -1748,24 +1747,24 @@ export namespace ACP {
return [base, ...variantOptions] return [base, ...variantOptions]
}) })
}) })
} }
function formatModelIdWithVariant( function formatModelIdWithVariant(
model: { providerID: ProviderID; modelID: ModelID }, model: { providerID: ProviderID; modelID: ModelID },
variant: string | undefined, variant: string | undefined,
availableVariants: string[], availableVariants: string[],
includeVariant: boolean, includeVariant: boolean,
) { ) {
const base = `${model.providerID}/${model.modelID}` const base = `${model.providerID}/${model.modelID}`
if (!includeVariant || !variant || !availableVariants.includes(variant)) return base if (!includeVariant || !variant || !availableVariants.includes(variant)) return base
return `${base}/${variant}` return `${base}/${variant}`
} }
function buildVariantMeta(input: { function buildVariantMeta(input: {
model: { providerID: ProviderID; modelID: ModelID } model: { providerID: ProviderID; modelID: ModelID }
variant?: string variant?: string
availableVariants: string[] availableVariants: string[]
}) { }) {
return { return {
opencode: { opencode: {
modelId: `${input.model.providerID}/${input.model.modelID}`, modelId: `${input.model.providerID}/${input.model.modelID}`,
@@ -1773,12 +1772,12 @@ export namespace ACP {
availableVariants: input.availableVariants, availableVariants: input.availableVariants,
}, },
} }
} }
function parseModelSelection( function parseModelSelection(
modelId: string, modelId: string,
providers: Array<{ id: string; models: Record<string, { variants?: Record<string, any> }> }>, providers: Array<{ id: string; models: Record<string, { variants?: Record<string, any> }> }>,
): { model: { providerID: ProviderID; modelID: ModelID }; variant?: string } { ): { model: { providerID: ProviderID; modelID: ModelID }; variant?: string } {
const parsed = Provider.parseModel(modelId) const parsed = Provider.parseModel(modelId)
const provider = providers.find((p) => p.id === parsed.providerID) const provider = providers.find((p) => p.id === parsed.providerID)
if (!provider) { if (!provider) {
@@ -1805,13 +1804,13 @@ export namespace ACP {
} }
return { model: parsed, variant: undefined } return { model: parsed, variant: undefined }
} }
function buildConfigOptions(input: { function buildConfigOptions(input: {
currentModelId: string currentModelId: string
availableModels: ModelOption[] availableModels: ModelOption[]
modes?: { availableModes: ModeOption[]; currentModeId: string } | undefined modes?: { availableModes: ModeOption[]; currentModeId: string } | undefined
}): SessionConfigOption[] { }): SessionConfigOption[] {
const options: SessionConfigOption[] = [ const options: SessionConfigOption[] = [
{ {
id: "model", id: "model",
@@ -1837,5 +1836,6 @@ export namespace ACP {
}) })
} }
return options return options
}
} }
export * as ACP from "./agent"