acp.ts 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. import { Log } from "@/util/log"
  2. import { bootstrap } from "../bootstrap"
  3. import { cmd } from "./cmd"
  4. import { AgentSideConnection, ndJsonStream } from "@agentclientprotocol/sdk"
  5. import { ACP } from "@/acp/agent"
  6. const log = Log.create({ service: "acp-command" })
  7. process.on("unhandledRejection", (reason, promise) => {
  8. log.error("Unhandled rejection", {
  9. promise,
  10. reason,
  11. })
  12. })
  13. export const AcpCommand = cmd({
  14. command: "acp",
  15. describe: "Start ACP (Agent Client Protocol) server",
  16. builder: (yargs) => {
  17. return yargs.option("cwd", {
  18. describe: "working directory",
  19. type: "string",
  20. default: process.cwd(),
  21. })
  22. },
  23. handler: async (opts) => {
  24. if (opts.cwd) process.chdir(opts["cwd"])
  25. await bootstrap(process.cwd(), async () => {
  26. const input = new WritableStream<Uint8Array>({
  27. write(chunk) {
  28. return new Promise<void>((resolve, reject) => {
  29. process.stdout.write(chunk, (err) => {
  30. if (err) {
  31. reject(err)
  32. } else {
  33. resolve()
  34. }
  35. })
  36. })
  37. },
  38. })
  39. const output = new ReadableStream<Uint8Array>({
  40. start(controller) {
  41. process.stdin.on("data", (chunk: Buffer) => {
  42. controller.enqueue(new Uint8Array(chunk))
  43. })
  44. process.stdin.on("end", () => controller.close())
  45. process.stdin.on("error", (err) => controller.error(err))
  46. },
  47. })
  48. const stream = ndJsonStream(input, output)
  49. const agent = await ACP.init()
  50. new AgentSideConnection((conn) => {
  51. return agent.create(conn, {})
  52. }, stream)
  53. log.info("setup connection")
  54. process.stdin.resume()
  55. await new Promise((resolve, reject) => {
  56. process.stdin.on("end", resolve)
  57. process.stdin.on("error", reject)
  58. })
  59. })
  60. },
  61. })