web.ts 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. import { Server } from "../../server/server"
  2. import { UI } from "../ui"
  3. import { cmd } from "./cmd"
  4. import { withNetworkOptions, resolveNetworkOptions } from "../network"
  5. import { Flag } from "../../flag/flag"
  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: "start opencode server and open web interface",
  28. handler: async (args) => {
  29. if (!Flag.OPENCODE_PASSWORD) {
  30. UI.println(UI.Style.TEXT_WARNING_BOLD + "! " + "OPENCODE_PASSWORD is not set; server is unsecured.")
  31. }
  32. const opts = await resolveNetworkOptions(args)
  33. const server = Server.listen(opts)
  34. UI.empty()
  35. UI.println(UI.logo(" "))
  36. UI.empty()
  37. if (opts.hostname === "0.0.0.0") {
  38. // Show localhost for local access
  39. const localhostUrl = `http://localhost:${server.port}`
  40. UI.println(UI.Style.TEXT_INFO_BOLD + " Local access: ", UI.Style.TEXT_NORMAL, localhostUrl)
  41. // Show network IPs for remote access
  42. const networkIPs = getNetworkIPs()
  43. if (networkIPs.length > 0) {
  44. for (const ip of networkIPs) {
  45. UI.println(
  46. UI.Style.TEXT_INFO_BOLD + " Network access: ",
  47. UI.Style.TEXT_NORMAL,
  48. `http://${ip}:${server.port}`,
  49. )
  50. }
  51. }
  52. if (opts.mdns) {
  53. UI.println(UI.Style.TEXT_INFO_BOLD + " mDNS: ", UI.Style.TEXT_NORMAL, "opencode.local")
  54. }
  55. // Open localhost in browser
  56. open(localhostUrl.toString()).catch(() => {})
  57. } else {
  58. const displayUrl = server.url.toString()
  59. UI.println(UI.Style.TEXT_INFO_BOLD + " Web interface: ", UI.Style.TEXT_NORMAL, displayUrl)
  60. open(displayUrl).catch(() => {})
  61. }
  62. await new Promise(() => {})
  63. await server.stop()
  64. },
  65. })