index.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import "zod-openapi/extend"
  2. import { App } from "./app/app"
  3. import { Server } from "./server/server"
  4. import fs from "fs/promises"
  5. import path from "path"
  6. import { Bus } from "./bus"
  7. import { Session } from "./session/session"
  8. import cac from "cac"
  9. import { Share } from "./share/share"
  10. import { Message } from "./session/message"
  11. import { Global } from "./global"
  12. import { Provider } from "./provider/provider"
  13. declare global {
  14. const OPENCODE_VERSION: string
  15. }
  16. const cli = cac("opencode")
  17. const version = typeof OPENCODE_VERSION === "string" ? OPENCODE_VERSION : "dev"
  18. cli.command("", "Start the opencode in interactive mode").action(async () => {
  19. await App.provide({ cwd: process.cwd(), version }, async () => {
  20. await Share.init()
  21. const server = Server.listen()
  22. let cmd = ["go", "run", "./main.go"]
  23. let cwd = new URL("../../tui/cmd/opencode", import.meta.url).pathname
  24. if (Bun.embeddedFiles.length > 0) {
  25. const blob = Bun.embeddedFiles[0] as File
  26. const binary = path.join(Global.Path.cache, "tui", blob.name)
  27. const file = Bun.file(binary)
  28. if (!(await file.exists())) {
  29. console.log("installing tui binary...")
  30. await Bun.write(file, blob, { mode: 0o755 })
  31. await fs.chmod(binary, 0o755)
  32. }
  33. cwd = process.cwd()
  34. cmd = [binary]
  35. }
  36. const proc = Bun.spawn({
  37. cmd,
  38. cwd,
  39. stdout: "inherit",
  40. stderr: "inherit",
  41. stdin: "inherit",
  42. onExit: () => {
  43. server.stop()
  44. },
  45. })
  46. await proc.exited
  47. await server.stop()
  48. })
  49. })
  50. cli.command("generate", "Generate OpenAPI and event specs").action(async () => {
  51. const specs = await Server.openapi()
  52. const dir = "gen"
  53. await fs.rmdir(dir, { recursive: true }).catch(() => {})
  54. await fs.mkdir(dir, { recursive: true })
  55. await Bun.write(
  56. path.join(dir, "openapi.json"),
  57. JSON.stringify(specs, null, 2),
  58. )
  59. })
  60. cli
  61. .command("run [...message]", "Run a chat message")
  62. .option("--session <id>", "Session ID")
  63. .action(async (message: string[], options) => {
  64. await App.provide({ cwd: process.cwd(), version }, async () => {
  65. await Share.init()
  66. const session = options.session
  67. ? await Session.get(options.session)
  68. : await Session.create()
  69. console.log("Session:", session.id)
  70. Bus.subscribe(Message.Event.Updated, async () => {
  71. console.log("Thinking...")
  72. })
  73. const unsub = Bus.subscribe(Session.Event.Updated, async (message) => {
  74. if (message.properties.info.share?.url)
  75. console.log("Share:", message.properties.info.share.url)
  76. unsub()
  77. })
  78. const { providerID, modelID } = await Provider.defaultModel()
  79. const result = await Session.chat({
  80. sessionID: session.id,
  81. providerID,
  82. modelID,
  83. parts: [
  84. {
  85. type: "text",
  86. text: message.join(" "),
  87. },
  88. ],
  89. })
  90. for (const part of result.parts) {
  91. if (part.type === "text") {
  92. console.log("opencode:", part.text)
  93. }
  94. }
  95. console.log({
  96. cost: result.metadata.assistant?.cost,
  97. tokens: result.metadata.assistant?.tokens,
  98. })
  99. })
  100. })
  101. cli.command("init", "Run a chat message").action(async () => {
  102. await App.provide({ cwd: process.cwd(), version }, async () => {
  103. const { modelID, providerID } = await Provider.defaultModel()
  104. console.log("Initializing...")
  105. const session = await Session.create()
  106. const unsub = Bus.subscribe(Session.Event.Updated, async (message) => {
  107. if (message.properties.info.share?.url)
  108. console.log("Share:", message.properties.info.share.url)
  109. unsub()
  110. })
  111. await Session.initialize({
  112. sessionID: session.id,
  113. modelID,
  114. providerID,
  115. })
  116. })
  117. })
  118. cli.version(typeof OPENCODE_VERSION === "string" ? OPENCODE_VERSION : "dev")
  119. cli.help()
  120. cli.parse()