FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
opencode/packages/opencode/src/server/shared/ui.ts at dev · argszero/opencode · GitHub
argszero
/
opencode
Public
forked from
anomalyco/opencode
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Pull requests
0
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
opencode
/
packages
/
opencode
/
src
/
server
/
shared
/
ui.ts
Copy path
More file actions
More file actions
Latest commit
History
History
History
108 lines (90 loc) · 4.24 KB
Breadcrumbs
opencode
/
packages
/
opencode
/
src
/
server
/
shared
/
ui.ts
Copy path
File metadata and controls
108 lines (90 loc) · 4.24 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import
{
FSUtil
}
from
"@opencode-ai/core/fs-util"
import
{
Effect
,
Stream
}
from
"effect"
import
{
HttpBody
,
HttpClient
,
HttpClientRequest
,
HttpServerRequest
,
HttpServerResponse
}
from
"effect/unstable/http"
import
{
createHash
}
from
"node:crypto"
import
{
ProxyUtil
}
from
"../proxy-util"
let
embeddedUIPromise
:
Promise
<
Record
<
string
,
string
>
|
null
>
|
undefined
export
const
UI_UPSTREAM
=
new
URL
(
"https://app.opencode.ai"
)
export
const
csp
=
(
hash
=
""
)
=>
`default-src 'self'; script-src 'self' 'wasm-unsafe-eval'
${
hash
?
` 'sha256-
${
hash
}
'`
:
""
}
; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; media-src 'self' data:; connect-src * data:`
export
const
DEFAULT_CSP
=
csp
(
)
export
function
themePreloadHash
(
body
:
string
)
{
return
body
.
match
(
/
<
s
c
r
i
p
t
\b
(?
!
[
^
>
]
*
\b
s
r
c
\s
*
=
)
[
^
>
]
*
\b
i
d
=
(
[
'
"
]
)
o
c
-
t
h
e
m
e
-
p
r
e
l
o
a
d
-
s
c
r
i
p
t
\1
[
^
>
]
*
>
(
[
\s
\S
]
*
?
)
<
\/
s
c
r
i
p
t
>
/
i
)
}
export
function
cspForHtml
(
body
:
string
)
{
const
match
=
themePreloadHash
(
body
)
return
csp
(
match
?
createHash
(
"sha256"
)
.
update
(
match
[
2
]
)
.
digest
(
"base64"
)
:
""
)
}
function
requestBody
(
request
:
HttpServerRequest
.
HttpServerRequest
)
{
if
(
request
.
method
===
"GET"
||
request
.
method
===
"HEAD"
)
return
HttpBody
.
empty
const
len
=
request
.
headers
[
"content-length"
]
return
HttpBody
.
stream
(
request
.
stream
,
request
.
headers
[
"content-type"
]
,
len
===
undefined
?
undefined
:
Number
(
len
)
)
}
function
proxyResponseHeaders
(
headers
:
Record
<
string
,
string
>
)
{
const
result
=
new
Headers
(
headers
)
// FetchHttpClient exposes decoded response bodies, so forwarding upstream
// transfer metadata makes browsers decode already-decoded assets again.
result
.
delete
(
"content-encoding"
)
result
.
delete
(
"content-length"
)
result
.
delete
(
"transfer-encoding"
)
return
result
}
export
function
upstreamURL
(
path
:
string
)
{
return
new
URL
(
path
,
UI_UPSTREAM
)
.
toString
(
)
}
export
function
embeddedUI
(
disableEmbeddedWebUi
:
boolean
)
{
if
(
disableEmbeddedWebUi
)
return
Promise
.
resolve
(
null
)
return
(
embeddedUIPromise
??=
//
@ts
-expect-error - generated file at build time
import
(
"opencode-web-ui.gen.ts"
)
.
then
(
(
module
)
=>
module
.
default
as
Record
<
string
,
string
>
)
.
catch
(
(
)
=>
null
)
)
}
function
notFound
(
)
{
return
HttpServerResponse
.
jsonUnsafe
(
{
error
:
"Not Found"
}
,
{
status
:
404
}
)
}
function
embeddedUIResponse
(
file
:
string
,
body
:
Uint8Array
)
{
const
mime
=
FSUtil
.
mimeType
(
file
)
const
headers
=
new
Headers
(
{
"content-type"
:
mime
}
)
if
(
mime
.
startsWith
(
"text/html"
)
)
{
headers
.
set
(
"content-security-policy"
,
cspForHtml
(
new
TextDecoder
(
)
.
decode
(
body
)
)
)
}
return
HttpServerResponse
.
raw
(
body
,
{
headers
}
)
}
export
function
serveEmbeddedUIEffect
(
requestPath
:
string
,
fs
:
FSUtil
.
Interface
,
embeddedWebUI
:
Record
<
string
,
string
>
,
)
{
const
file
=
embeddedWebUI
[
requestPath
.
replace
(
/
^
\/
/
,
""
)
]
??
embeddedWebUI
[
"index.html"
]
??
null
if
(
!
file
)
return
Effect
.
succeed
(
notFound
(
)
)
return
fs
.
readFile
(
file
)
.
pipe
(
Effect
.
map
(
(
body
)
=>
embeddedUIResponse
(
file
,
body
)
)
,
Effect
.
catchReason
(
"PlatformError"
,
"NotFound"
,
(
)
=>
Effect
.
succeed
(
notFound
(
)
)
)
,
)
}
export
function
serveUIEffect
(
request
:
HttpServerRequest
.
HttpServerRequest
,
services
:
{
fs
:
FSUtil
.
Interface
;
client
:
HttpClient
.
HttpClient
;
disableEmbeddedWebUi
:
boolean
}
,
)
{
return
Effect
.
gen
(
function
*
(
)
{
const
embeddedWebUI
=
yield
*
Effect
.
promise
(
(
)
=>
embeddedUI
(
services
.
disableEmbeddedWebUi
)
)
const
path
=
new
URL
(
request
.
url
,
"http://localhost"
)
.
pathname
if
(
embeddedWebUI
)
return
yield
*
serveEmbeddedUIEffect
(
path
,
services
.
fs
,
embeddedWebUI
)
const
response
=
yield
*
services
.
client
.
execute
(
HttpClientRequest
.
make
(
request
.
method
)
(
upstreamURL
(
path
)
,
{
headers
:
ProxyUtil
.
headers
(
request
.
headers
,
{
host
:
UI_UPSTREAM
.
host
}
)
,
body
:
requestBody
(
request
)
,
}
)
,
)
const
headers
=
proxyResponseHeaders
(
response
.
headers
)
if
(
response
.
headers
[
"content-type"
]
?.
includes
(
"text/html"
)
)
{
const
body
=
yield
*
response
.
text
headers
.
set
(
"Content-Security-Policy"
,
cspForHtml
(
body
)
)
return
HttpServerResponse
.
text
(
body
,
{
status
:
response
.
status
,
headers
}
)
}
headers
.
set
(
"Content-Security-Policy"
,
csp
(
)
)
return
HttpServerResponse
.
stream
(
response
.
stream
.
pipe
(
Stream
.
catchCause
(
(
)
=>
Stream
.
empty
)
)
,
{
status
:
response
.
status
,
headers
,
}
)
}
)
}
Back
|
FazBrowse Home
|
New Git URL