77 lines
2.4 KiB
TypeScript
77 lines
2.4 KiB
TypeScript
import * as Log from "@opencode-ai/core/util/log"
|
|
import { Effect } from "effect"
|
|
import { effectCmd } from "../effect-cmd"
|
|
import { AgentSideConnection, ndJsonStream } from "@agentclientprotocol/sdk"
|
|
import { ServerAuth } from "@/server/auth"
|
|
import { createOpencodeClient } from "@opencode-ai/sdk/v2"
|
|
import { withNetworkOptions, resolveNetworkOptions } from "../network"
|
|
import { ACPProfile } from "@/acp/profile"
|
|
|
|
const log = Log.create({ service: "acp-command" })
|
|
|
|
export const AcpCommand = effectCmd({
|
|
command: "acp",
|
|
describe: "start ACP (Agent Client Protocol) server",
|
|
builder: (yargs) => {
|
|
return withNetworkOptions(yargs).option("cwd", {
|
|
describe: "working directory",
|
|
type: "string",
|
|
default: process.cwd(),
|
|
})
|
|
},
|
|
handler: Effect.fn("Cli.acp")(function* (args) {
|
|
const { Server } = yield* Effect.promise(() => import("@/server/server"))
|
|
const { ACP } = yield* Effect.promise(() => import("@/acp/agent"))
|
|
ACPProfile.mark("cli.acp.handler")
|
|
process.env.OPENCODE_CLIENT = "acp"
|
|
const opts = yield* resolveNetworkOptions(args)
|
|
const server = yield* Effect.promise(() => ACPProfile.measure("cli.acp.server.listen", () => Server.listen(opts)))
|
|
|
|
const sdk = createOpencodeClient({
|
|
baseUrl: `http://${server.hostname}:${server.port}`,
|
|
headers: ServerAuth.headers(),
|
|
})
|
|
|
|
const input = new WritableStream<Uint8Array>({
|
|
write(chunk) {
|
|
return new Promise<void>((resolve, reject) => {
|
|
process.stdout.write(chunk, (err) => {
|
|
if (err) {
|
|
reject(err)
|
|
} else {
|
|
resolve()
|
|
}
|
|
})
|
|
})
|
|
},
|
|
})
|
|
const output = new ReadableStream<Uint8Array>({
|
|
start(controller) {
|
|
process.stdin.on("data", (chunk: Buffer) => {
|
|
controller.enqueue(new Uint8Array(chunk))
|
|
})
|
|
process.stdin.on("end", () => controller.close())
|
|
process.stdin.on("error", (err) => controller.error(err))
|
|
},
|
|
})
|
|
|
|
const stream = ndJsonStream(input, output)
|
|
const agent = ACP.init({ sdk })
|
|
|
|
new AgentSideConnection((conn) => {
|
|
ACPProfile.mark("cli.acp.connection.create")
|
|
return agent.create(conn)
|
|
}, stream)
|
|
|
|
log.info("setup connection")
|
|
process.stdin.resume()
|
|
yield* Effect.promise(
|
|
() =>
|
|
new Promise<void>((resolve, reject) => {
|
|
process.stdin.on("end", () => resolve())
|
|
process.stdin.on("error", reject)
|
|
}),
|
|
)
|
|
}),
|
|
})
|