@@ -3,36 +3,10 @@ import { Flag } from "@opencode-ai/core/flag/flag"
33import { Effect , Stream } from "effect"
44import { HttpBody , HttpClient , HttpClientRequest , HttpServerRequest , HttpServerResponse } from "effect/unstable/http"
55import { createHash } from "node:crypto"
6- import os from "node:os"
76import path from "node:path"
87import { fileURLToPath } from "node:url"
98import { ProxyUtil } from "../proxy-util"
109
11- const SERVER_HOSTNAME = ( ( ) => {
12- try {
13- return os . hostname ( ) . replace ( / \. l o c a l $ / i, "" )
14- } catch {
15- return ""
16- }
17- } ) ( )
18-
19- function serverDisplayName ( request : HttpServerRequest . HttpServerRequest ) {
20- if ( SERVER_HOSTNAME ) return SERVER_HOSTNAME
21- const host = request . headers [ "host" ] ?? ""
22- return host . split ( ":" ) [ 0 ] ?? ""
23- }
24-
25- function escapeHtml ( value : string ) {
26- return value . replace ( / [ & < > " ' ] / g, ( c ) =>
27- c === "&" ? "&" : c === "<" ? "<" : c === ">" ? ">" : c === '"' ? """ : "'" ,
28- )
29- }
30-
31- function rewriteTitle ( html : string , name : string ) {
32- if ( ! name ) return html
33- return html . replace ( / < t i t l e \b [ ^ > ] * > [ \s \S ] * ?< \/ t i t l e > / i, `<title>${ escapeHtml ( name ) } - OpenCode</title>` )
34- }
35-
3610const embeddedUIPromise = Flag . OPENCODE_DISABLE_EMBEDDED_WEB_UI
3711 ? Promise . resolve ( null )
3812 : // @ts -expect-error - generated file at build time
@@ -96,13 +70,11 @@ function notFound() {
9670 return HttpServerResponse . jsonUnsafe ( { error : "Not Found" } , { status : 404 } )
9771}
9872
99- function embeddedUIResponse ( file : string , body : Uint8Array , name : string ) {
73+ function embeddedUIResponse ( file : string , body : Uint8Array ) {
10074 const mime = AppFileSystem . mimeType ( file )
10175 const headers = new Headers ( { "content-type" : mime } )
10276 if ( mime . startsWith ( "text/html" ) ) {
103- const rewritten = rewriteTitle ( new TextDecoder ( ) . decode ( body ) , name )
104- headers . set ( "content-security-policy" , cspForHtml ( rewritten ) )
105- return HttpServerResponse . raw ( new TextEncoder ( ) . encode ( rewritten ) , { headers } )
77+ headers . set ( "content-security-policy" , cspForHtml ( new TextDecoder ( ) . decode ( body ) ) )
10678 }
10779 return HttpServerResponse . raw ( body , { headers } )
10880}
@@ -111,15 +83,14 @@ export function serveEmbeddedUIEffect(
11183 requestPath : string ,
11284 fs : AppFileSystem . Interface ,
11385 embeddedWebUI : Record < string , string > ,
114- name : string ,
11586) {
11687 const file = embeddedWebUI [ requestPath . replace ( / ^ \/ / , "" ) ] ?? embeddedWebUI [ "index.html" ] ?? null
11788 if ( ! file ) return Effect . succeed ( notFound ( ) )
11889
11990 const resolved = embeddedUIFile ( file )
12091
12192 return fs . readFile ( resolved ) . pipe (
122- Effect . map ( ( body ) => embeddedUIResponse ( resolved , body , name ) ) ,
93+ Effect . map ( ( body ) => embeddedUIResponse ( resolved , body ) ) ,
12394 Effect . catchReason ( "PlatformError" , "NotFound" , ( ) => Effect . succeed ( notFound ( ) ) ) ,
12495 )
12596}
@@ -128,14 +99,13 @@ function serveLocalDirEffect(
12899 requestPath : string ,
129100 fs : AppFileSystem . Interface ,
130101 dir : string ,
131- name : string ,
132102) {
133103 const filePath = path . join ( dir , requestPath === "/" ? "index.html" : requestPath )
134104 return fs . readFile ( filePath ) . pipe (
135- Effect . map ( ( body ) => embeddedUIResponse ( filePath , body , name ) ) ,
105+ Effect . map ( ( body ) => embeddedUIResponse ( filePath , body ) ) ,
136106 Effect . catchReason ( "PlatformError" , "NotFound" , ( ) =>
137107 fs . readFile ( path . join ( dir , "index.html" ) ) . pipe (
138- Effect . map ( ( body ) => embeddedUIResponse ( path . join ( dir , "index.html" ) , body , name ) ) ,
108+ Effect . map ( ( body ) => embeddedUIResponse ( path . join ( dir , "index.html" ) , body ) ) ,
139109 Effect . catchReason ( "PlatformError" , "NotFound" , ( ) => Effect . succeed ( notFound ( ) ) ) ,
140110 ) ,
141111 ) ,
@@ -149,13 +119,11 @@ export function serveUIEffect(
149119 return Effect . gen ( function * ( ) {
150120 const embeddedWebUI = yield * Effect . promise ( ( ) => embeddedUI ( ) )
151121 const requestPath = new URL ( request . url , "http://localhost" ) . pathname
152- const name = serverDisplayName ( request )
153122
154- if ( embeddedWebUI ) return yield * serveEmbeddedUIEffect ( requestPath , services . fs , embeddedWebUI , name )
123+ if ( embeddedWebUI ) return yield * serveEmbeddedUIEffect ( requestPath , services . fs , embeddedWebUI )
155124
156125 // Dev mode: serve from local build directory if configured
157- if ( Flag . OPENCODE_DEV_UI_DIR )
158- return yield * serveLocalDirEffect ( requestPath , services . fs , Flag . OPENCODE_DEV_UI_DIR , name )
126+ if ( Flag . OPENCODE_DEV_UI_DIR ) return yield * serveLocalDirEffect ( requestPath , services . fs , Flag . OPENCODE_DEV_UI_DIR )
159127
160128 const response = yield * services . client . execute (
161129 HttpClientRequest . make ( request . method ) ( upstreamURL ( requestPath ) , {
@@ -166,7 +134,7 @@ export function serveUIEffect(
166134 const headers = proxyResponseHeaders ( response . headers )
167135
168136 if ( response . headers [ "content-type" ] ?. includes ( "text/html" ) ) {
169- const body = rewriteTitle ( yield * response . text , name )
137+ const body = yield * response . text
170138 headers . set ( "Content-Security-Policy" , cspForHtml ( body ) )
171139 return HttpServerResponse . text ( body , { status : response . status , headers } )
172140 }
0 commit comments