refactor: unwrap ACP namespace + self-reexport (#22936)
This commit is contained in:
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user