web.ts 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import { Config } from "../../config/config"
  2. import { Server } from "../../server/server"
  3. import { UI } from "../ui"
  4. import { cmd } from "./cmd"
  5. import { withNetworkOptions, resolveNetworkOptions } from "../network"
  6. import open from "open"
  7. import { networkInterfaces } from "os"
  8. function getNetworkIPs() {
  9. const nets = networkInterfaces()
  10. const results: string[] = []
  11. for (const name of Object.keys(nets)) {
  12. const net = nets[name]
  13. if (!net) continue
  14. for (const netInfo of net) {
  15. // Skip internal and non-IPv4 addresses
  16. if (netInfo.internal || netInfo.family !== "IPv4") continue
  17. // Skip Docker bridge networks (typically 172.x.x.x)
  18. if (netInfo.address.startsWith("172.")) continue
  19. results.push(netInfo.address)
  20. }
  21. }
  22. return results
  23. }
  24. export const WebCommand = cmd({
  25. command: "web",
  26. builder: (yargs) => withNetworkOptions(yargs),
  27. describe: "starts a headless opencode server",
  28. handler: async (args) => {
  29. const config = await Config.get()
  30. const opts = resolveNetworkOptions(args, config)
  31. const server = Server.listen(opts)
  32. UI.empty()
  33. UI.println(UI.logo(" "))
  34. UI.empty()
  35. if (opts.hostname === "0.0.0.0") {
  36. // Show localhost for local access
  37. const localhostUrl = `http://localhost:${server.port}`
  38. UI.println(UI.Style.TEXT_INFO_BOLD + " Local access: ", UI.Style.TEXT_NORMAL, localhostUrl)
  39. // Show network IPs for remote access
  40. const networkIPs = getNetworkIPs()
  41. if (networkIPs.length > 0) {
  42. for (const ip of networkIPs) {
  43. UI.println(
  44. UI.Style.TEXT_INFO_BOLD + " Network access: ",
  45. UI.Style.TEXT_NORMAL,
  46. `http://${ip}:${server.port}`,
  47. )
  48. }
  49. }
  50. if (opts.mdns) {
  51. UI.println(UI.Style.TEXT_INFO_BOLD + " mDNS: ", UI.Style.TEXT_NORMAL, "opencode.local")
  52. }
  53. // Open localhost in browser
  54. open(localhostUrl.toString()).catch(() => {})
  55. } else {
  56. const displayUrl = server.url.toString()
  57. UI.println(UI.Style.TEXT_INFO_BOLD + " Web interface: ", UI.Style.TEXT_NORMAL, displayUrl)
  58. open(displayUrl).catch(() => {})
  59. }
  60. await new Promise(() => {})
  61. await server.stop()
  62. },
  63. })