index.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  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 { UpgradeCommand } from "./cli/cmd/upgrade"
  9. import { ModelsCommand } from "./cli/cmd/models"
  10. import { UI } from "./cli/ui"
  11. import { Installation } from "./installation"
  12. import { NamedError } from "./util/error"
  13. import { FormatError } from "./cli/error"
  14. import { ServeCommand } from "./cli/cmd/serve"
  15. import { TuiCommand } from "./cli/cmd/tui"
  16. import { DebugCommand } from "./cli/cmd/debug"
  17. import { StatsCommand } from "./cli/cmd/stats"
  18. import { McpCommand } from "./cli/cmd/mcp"
  19. import { InstallGithubCommand } from "./cli/cmd/install-github"
  20. const cancel = new AbortController()
  21. process.on("unhandledRejection", (e) => {
  22. Log.Default.error("rejection", {
  23. e: e instanceof Error ? e.message : e,
  24. })
  25. })
  26. process.on("uncaughtException", (e) => {
  27. Log.Default.error("exception", {
  28. e: e instanceof Error ? e.message : e,
  29. })
  30. })
  31. const cli = yargs(hideBin(process.argv))
  32. .scriptName("opencode")
  33. .help("help", "show help")
  34. .version("version", "show version number", Installation.VERSION)
  35. .alias("version", "v")
  36. .option("print-logs", {
  37. describe: "print logs to stderr",
  38. type: "boolean",
  39. })
  40. .middleware(async () => {
  41. await Log.init({ print: process.argv.includes("--print-logs") })
  42. try {
  43. const { Config } = await import("./config/config")
  44. const { App } = await import("./app/app")
  45. App.provide({ cwd: process.cwd() }, async () => {
  46. const cfg = await Config.get()
  47. if (cfg.log_level) {
  48. Log.setLevel(cfg.log_level as Log.Level)
  49. } else {
  50. const defaultLevel = Installation.isDev() ? "DEBUG" : "INFO"
  51. Log.setLevel(defaultLevel)
  52. }
  53. })
  54. } catch (e) {
  55. Log.Default.error("failed to load config", { error: e })
  56. }
  57. Log.Default.info("opencode", {
  58. version: Installation.VERSION,
  59. args: process.argv.slice(2),
  60. })
  61. })
  62. .usage("\n" + UI.logo())
  63. .command(McpCommand)
  64. .command(TuiCommand)
  65. .command(RunCommand)
  66. .command(GenerateCommand)
  67. .command(DebugCommand)
  68. .command(AuthCommand)
  69. .command(UpgradeCommand)
  70. .command(ServeCommand)
  71. .command(ModelsCommand)
  72. .command(StatsCommand)
  73. .command(InstallGithubCommand)
  74. .fail((msg) => {
  75. if (msg.startsWith("Unknown argument") || msg.startsWith("Not enough non-option arguments")) {
  76. cli.showHelp("log")
  77. }
  78. })
  79. .strict()
  80. try {
  81. await cli.parse()
  82. } catch (e) {
  83. let data: Record<string, any> = {}
  84. if (e instanceof NamedError) {
  85. const obj = e.toObject()
  86. Object.assign(data, {
  87. ...obj.data,
  88. })
  89. }
  90. if (e instanceof Error) {
  91. Object.assign(data, {
  92. name: e.name,
  93. message: e.message,
  94. cause: e.cause?.toString(),
  95. })
  96. }
  97. if (e instanceof ResolveMessage) {
  98. Object.assign(data, {
  99. name: e.name,
  100. message: e.message,
  101. code: e.code,
  102. specifier: e.specifier,
  103. referrer: e.referrer,
  104. position: e.position,
  105. importKind: e.importKind,
  106. })
  107. }
  108. Log.Default.error("fatal", data)
  109. const formatted = FormatError(e)
  110. if (formatted) UI.error(formatted)
  111. if (formatted === undefined) UI.error("Unexpected error, check log file at " + Log.file() + " for more details")
  112. process.exitCode = 1
  113. }
  114. cancel.abort()