index.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. import "zod-openapi/extend"
  2. import yargs from "yargs"
  3. import { hideBin } from "yargs/helpers"
  4. import { RunCommand } from "./cli/cmd/run"
  5. import { GenerateCommand } from "./cli/cmd/generate"
  6. import { Log } from "./util/log"
  7. import { AuthCommand } from "./cli/cmd/auth"
  8. import { AgentCommand } from "./cli/cmd/agent"
  9. import { UpgradeCommand } from "./cli/cmd/upgrade"
  10. import { ModelsCommand } from "./cli/cmd/models"
  11. import { UI } from "./cli/ui"
  12. import { Installation } from "./installation"
  13. import { NamedError } from "./util/error"
  14. import { FormatError } from "./cli/error"
  15. import { ServeCommand } from "./cli/cmd/serve"
  16. import { TuiCommand } from "./cli/cmd/tui"
  17. import { DebugCommand } from "./cli/cmd/debug"
  18. import { StatsCommand } from "./cli/cmd/stats"
  19. import { McpCommand } from "./cli/cmd/mcp"
  20. import { GithubCommand } from "./cli/cmd/github"
  21. import { ExportCommand } from "./cli/cmd/export"
  22. const cancel = new AbortController()
  23. try {
  24. } catch (e) {}
  25. process.on("unhandledRejection", (e) => {
  26. Log.Default.error("rejection", {
  27. e: e instanceof Error ? e.message : e,
  28. })
  29. })
  30. process.on("uncaughtException", (e) => {
  31. Log.Default.error("exception", {
  32. e: e instanceof Error ? e.message : e,
  33. })
  34. })
  35. const cli = yargs(hideBin(process.argv))
  36. .scriptName("opencode")
  37. .help("help", "show help")
  38. .version("version", "show version number", Installation.VERSION)
  39. .alias("version", "v")
  40. .option("print-logs", {
  41. describe: "print logs to stderr",
  42. type: "boolean",
  43. })
  44. .option("log-level", {
  45. describe: "log level",
  46. type: "string",
  47. choices: ["DEBUG", "INFO", "WARN", "ERROR"],
  48. })
  49. .middleware(async (opts) => {
  50. await Log.init({
  51. print: process.argv.includes("--print-logs"),
  52. dev: Installation.isDev(),
  53. level: (() => {
  54. if (opts.logLevel) return opts.logLevel as Log.Level
  55. if (Installation.isDev()) return "DEBUG"
  56. return "INFO"
  57. })(),
  58. })
  59. process.env["OPENCODE"] = "1"
  60. Log.Default.info("opencode", {
  61. version: Installation.VERSION,
  62. args: process.argv.slice(2),
  63. })
  64. })
  65. .usage("\n" + UI.logo())
  66. .command(McpCommand)
  67. .command(TuiCommand)
  68. .command(RunCommand)
  69. .command(GenerateCommand)
  70. .command(DebugCommand)
  71. .command(AuthCommand)
  72. .command(AgentCommand)
  73. .command(UpgradeCommand)
  74. .command(ServeCommand)
  75. .command(ModelsCommand)
  76. .command(StatsCommand)
  77. .command(ExportCommand)
  78. .command(GithubCommand)
  79. .fail((msg) => {
  80. if (
  81. msg.startsWith("Unknown argument") ||
  82. msg.startsWith("Not enough non-option arguments") ||
  83. msg.startsWith("Invalid values:")
  84. ) {
  85. cli.showHelp("log")
  86. }
  87. process.exit(1)
  88. })
  89. .strict()
  90. try {
  91. await cli.parse()
  92. } catch (e) {
  93. let data: Record<string, any> = {}
  94. if (e instanceof NamedError) {
  95. const obj = e.toObject()
  96. Object.assign(data, {
  97. ...obj.data,
  98. })
  99. }
  100. if (e instanceof Error) {
  101. Object.assign(data, {
  102. name: e.name,
  103. message: e.message,
  104. cause: e.cause?.toString(),
  105. stack: e.stack,
  106. })
  107. }
  108. if (e instanceof ResolveMessage) {
  109. Object.assign(data, {
  110. name: e.name,
  111. message: e.message,
  112. code: e.code,
  113. specifier: e.specifier,
  114. referrer: e.referrer,
  115. position: e.position,
  116. importKind: e.importKind,
  117. })
  118. }
  119. Log.Default.error("fatal", data)
  120. const formatted = FormatError(e)
  121. if (formatted) UI.error(formatted)
  122. if (formatted === undefined) UI.error("Unexpected error, check log file at " + Log.file() + " for more details")
  123. process.exitCode = 1
  124. }
  125. cancel.abort()