web.ts 2.2 KB

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