agent-message 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +227 -0
- package/npm/bin/agent-messenger.mjs +386 -0
- package/npm/runtime/agent_gateway.mjs +175 -0
- package/npm/runtime/bin/agent-messenger-cli-darwin-amd64 +0 -0
- package/npm/runtime/bin/agent-messenger-cli-darwin-arm64 +0 -0
- package/npm/runtime/bin/agent-messenger-server-darwin-amd64 +0 -0
- package/npm/runtime/bin/agent-messenger-server-darwin-arm64 +0 -0
- package/npm/runtime/web-dist/apple-touch-icon.png +0 -0
- package/npm/runtime/web-dist/assets/index-BgmjffS2.js +182 -0
- package/npm/runtime/web-dist/assets/index-D_RPU5JN.css +1 -0
- package/npm/runtime/web-dist/assets/workbox-window.prod.es5-vqzQaGvo.js +2 -0
- package/npm/runtime/web-dist/favicon.svg +9 -0
- package/npm/runtime/web-dist/index.html +21 -0
- package/npm/runtime/web-dist/manifest.webmanifest +1 -0
- package/npm/runtime/web-dist/masked-icon.svg +9 -0
- package/npm/runtime/web-dist/pwa-192x192.png +0 -0
- package/npm/runtime/web-dist/pwa-512x512.png +0 -0
- package/npm/runtime/web-dist/pwa-artwork.svg +9 -0
- package/npm/runtime/web-dist/sw.js +1 -0
- package/npm/runtime/web-dist/workbox-8c29f6e4.js +1 -0
- package/package.json +33 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { createReadStream } from 'node:fs'
|
|
2
|
+
import { access, readFile, stat } from 'node:fs/promises'
|
|
3
|
+
import http from 'node:http'
|
|
4
|
+
import { basename, extname, join, normalize, resolve } from 'node:path'
|
|
5
|
+
|
|
6
|
+
const host = process.env.AGENT_GATEWAY_HOST ?? '127.0.0.1'
|
|
7
|
+
const port = Number(process.env.AGENT_GATEWAY_PORT ?? '8788')
|
|
8
|
+
const apiOrigin = process.env.AGENT_API_ORIGIN ?? 'http://127.0.0.1:18080'
|
|
9
|
+
const distDir = resolve(process.env.AGENT_WEB_DIST ?? join(process.cwd(), 'web', 'dist'))
|
|
10
|
+
const indexPath = join(distDir, 'index.html')
|
|
11
|
+
|
|
12
|
+
const contentTypes = new Map([
|
|
13
|
+
['.css', 'text/css; charset=utf-8'],
|
|
14
|
+
['.html', 'text/html; charset=utf-8'],
|
|
15
|
+
['.ico', 'image/x-icon'],
|
|
16
|
+
['.js', 'text/javascript; charset=utf-8'],
|
|
17
|
+
['.json', 'application/json; charset=utf-8'],
|
|
18
|
+
['.mjs', 'text/javascript; charset=utf-8'],
|
|
19
|
+
['.png', 'image/png'],
|
|
20
|
+
['.svg', 'image/svg+xml'],
|
|
21
|
+
['.txt', 'text/plain; charset=utf-8'],
|
|
22
|
+
['.webmanifest', 'application/manifest+json; charset=utf-8'],
|
|
23
|
+
['.woff2', 'font/woff2'],
|
|
24
|
+
])
|
|
25
|
+
|
|
26
|
+
function resolveCacheHeaders(path) {
|
|
27
|
+
const fileName = basename(path)
|
|
28
|
+
|
|
29
|
+
if (fileName === 'sw.js') {
|
|
30
|
+
return {
|
|
31
|
+
'cache-control': 'no-cache',
|
|
32
|
+
'cdn-cache-control': 'no-store',
|
|
33
|
+
'cloudflare-cdn-cache-control': 'no-store',
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (path === indexPath || fileName === 'manifest.webmanifest') {
|
|
38
|
+
return {
|
|
39
|
+
'cache-control': 'no-cache',
|
|
40
|
+
'cdn-cache-control': 'no-cache',
|
|
41
|
+
'cloudflare-cdn-cache-control': 'no-cache',
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
'cache-control': 'public, max-age=31536000, immutable',
|
|
47
|
+
'cdn-cache-control': 'public, max-age=31536000, immutable',
|
|
48
|
+
'cloudflare-cdn-cache-control': 'public, max-age=31536000, immutable',
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function setForwardHeaders(headers, req) {
|
|
53
|
+
headers.set('x-forwarded-for', req.socket.remoteAddress ?? '')
|
|
54
|
+
headers.set('x-forwarded-host', req.headers.host ?? '')
|
|
55
|
+
headers.set('x-forwarded-proto', 'https')
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function proxyRequest(req, res) {
|
|
59
|
+
const targetURL = new URL(req.url ?? '/', apiOrigin)
|
|
60
|
+
const headers = new Headers()
|
|
61
|
+
|
|
62
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
63
|
+
if (value === undefined) {
|
|
64
|
+
continue
|
|
65
|
+
}
|
|
66
|
+
if (Array.isArray(value)) {
|
|
67
|
+
for (const item of value) {
|
|
68
|
+
headers.append(key, item)
|
|
69
|
+
}
|
|
70
|
+
continue
|
|
71
|
+
}
|
|
72
|
+
headers.set(key, value)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
setForwardHeaders(headers, req)
|
|
76
|
+
|
|
77
|
+
const init = {
|
|
78
|
+
method: req.method,
|
|
79
|
+
headers,
|
|
80
|
+
body: req.method === 'GET' || req.method === 'HEAD' ? undefined : req,
|
|
81
|
+
duplex: 'half',
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const upstream = await fetch(targetURL, init)
|
|
85
|
+
|
|
86
|
+
res.writeHead(
|
|
87
|
+
upstream.status,
|
|
88
|
+
Object.fromEntries(upstream.headers.entries()),
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
if (!upstream.body) {
|
|
92
|
+
res.end()
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
for await (const chunk of upstream.body) {
|
|
97
|
+
res.write(chunk)
|
|
98
|
+
}
|
|
99
|
+
res.end()
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function resolveStaticPath(requestPath) {
|
|
103
|
+
const decodedPath = decodeURIComponent(requestPath.split('?')[0])
|
|
104
|
+
const normalizedPath = normalize(decodedPath).replace(/^(\.\.[/\\])+/, '')
|
|
105
|
+
const trimmedPath = normalizedPath.replace(/^[/\\]+/, '')
|
|
106
|
+
return join(distDir, trimmedPath)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function fileExists(path) {
|
|
110
|
+
try {
|
|
111
|
+
await access(path)
|
|
112
|
+
return true
|
|
113
|
+
} catch {
|
|
114
|
+
return false
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async function serveFile(res, path) {
|
|
119
|
+
const fileStats = await stat(path)
|
|
120
|
+
if (!fileStats.isFile()) {
|
|
121
|
+
return false
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const type = contentTypes.get(extname(path)) ?? 'application/octet-stream'
|
|
125
|
+
res.writeHead(200, {
|
|
126
|
+
...resolveCacheHeaders(path),
|
|
127
|
+
'content-length': String(fileStats.size),
|
|
128
|
+
'content-type': type,
|
|
129
|
+
})
|
|
130
|
+
createReadStream(path).pipe(res)
|
|
131
|
+
return true
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async function serveApp(req, res) {
|
|
135
|
+
const requestPath = req.url ?? '/'
|
|
136
|
+
let candidatePath = resolveStaticPath(requestPath)
|
|
137
|
+
|
|
138
|
+
if (await fileExists(candidatePath)) {
|
|
139
|
+
const served = await serveFile(res, candidatePath)
|
|
140
|
+
if (served) {
|
|
141
|
+
return
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
candidatePath = indexPath
|
|
146
|
+
res.writeHead(200, {
|
|
147
|
+
...resolveCacheHeaders(candidatePath),
|
|
148
|
+
'content-type': 'text/html; charset=utf-8',
|
|
149
|
+
})
|
|
150
|
+
res.end(await readFile(candidatePath))
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const server = http.createServer(async (req, res) => {
|
|
154
|
+
try {
|
|
155
|
+
const requestPath = req.url ?? '/'
|
|
156
|
+
if (requestPath.startsWith('/api/') || requestPath === '/api' || requestPath.startsWith('/static/uploads/')) {
|
|
157
|
+
await proxyRequest(req, res)
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
await serveApp(req, res)
|
|
162
|
+
} catch (error) {
|
|
163
|
+
console.error('gateway request failed', error)
|
|
164
|
+
if (!res.headersSent) {
|
|
165
|
+
res.writeHead(502, { 'content-type': 'text/plain; charset=utf-8' })
|
|
166
|
+
}
|
|
167
|
+
res.end('Bad gateway')
|
|
168
|
+
}
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
server.listen(port, host, () => {
|
|
172
|
+
console.log(`agent gateway listening on http://${host}:${port}`)
|
|
173
|
+
console.log(`serving dist from ${distDir}`)
|
|
174
|
+
console.log(`proxying API to ${apiOrigin}`)
|
|
175
|
+
})
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|