jishushell 0.0.1 → 0.4.2-beta2
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/INSTALL-NOTICE +41 -0
- package/LICENSE +202 -0
- package/README.md +36 -0
- package/THIRD-PARTY-NOTICES +387 -0
- package/dist/auth.d.ts +6 -0
- package/dist/auth.js +88 -0
- package/dist/auth.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +290 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +24 -0
- package/dist/config.js +226 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.js +15 -0
- package/dist/constants.js.map +1 -0
- package/dist/control.d.ts +44 -0
- package/dist/control.js +1359 -0
- package/dist/control.js.map +1 -0
- package/dist/crypto-shim.d.ts +1 -0
- package/dist/crypto-shim.js +2 -0
- package/dist/crypto-shim.js.map +1 -0
- package/dist/doctor.d.ts +46 -0
- package/dist/doctor.js +937 -0
- package/dist/doctor.js.map +1 -0
- package/dist/install.d.ts +27 -0
- package/dist/install.js +570 -0
- package/dist/install.js.map +1 -0
- package/dist/routes/auth.d.ts +4 -0
- package/dist/routes/auth.js +151 -0
- package/dist/routes/auth.js.map +1 -0
- package/dist/routes/instances.d.ts +2 -0
- package/dist/routes/instances.js +1303 -0
- package/dist/routes/instances.js.map +1 -0
- package/dist/routes/setup.d.ts +2 -0
- package/dist/routes/setup.js +139 -0
- package/dist/routes/setup.js.map +1 -0
- package/dist/routes/system.d.ts +2 -0
- package/dist/routes/system.js +102 -0
- package/dist/routes/system.js.map +1 -0
- package/dist/server.d.ts +6 -0
- package/dist/server.js +392 -0
- package/dist/server.js.map +1 -0
- package/dist/services/instance-manager.d.ts +67 -0
- package/dist/services/instance-manager.js +1319 -0
- package/dist/services/instance-manager.js.map +1 -0
- package/dist/services/llm-proxy/adapters.d.ts +3 -0
- package/dist/services/llm-proxy/adapters.js +309 -0
- package/dist/services/llm-proxy/adapters.js.map +1 -0
- package/dist/services/llm-proxy/circuit-breaker.d.ts +9 -0
- package/dist/services/llm-proxy/circuit-breaker.js +73 -0
- package/dist/services/llm-proxy/circuit-breaker.js.map +1 -0
- package/dist/services/llm-proxy/encryption.d.ts +6 -0
- package/dist/services/llm-proxy/encryption.js +61 -0
- package/dist/services/llm-proxy/encryption.js.map +1 -0
- package/dist/services/llm-proxy/index.d.ts +24 -0
- package/dist/services/llm-proxy/index.js +708 -0
- package/dist/services/llm-proxy/index.js.map +1 -0
- package/dist/services/llm-proxy/rate-limiter.d.ts +1 -0
- package/dist/services/llm-proxy/rate-limiter.js +39 -0
- package/dist/services/llm-proxy/rate-limiter.js.map +1 -0
- package/dist/services/llm-proxy/sse.d.ts +10 -0
- package/dist/services/llm-proxy/sse.js +378 -0
- package/dist/services/llm-proxy/sse.js.map +1 -0
- package/dist/services/llm-proxy/ssrf.d.ts +16 -0
- package/dist/services/llm-proxy/ssrf.js +185 -0
- package/dist/services/llm-proxy/ssrf.js.map +1 -0
- package/dist/services/llm-proxy/types.d.ts +52 -0
- package/dist/services/llm-proxy/types.js +2 -0
- package/dist/services/llm-proxy/types.js.map +1 -0
- package/dist/services/llm-proxy/usage.d.ts +12 -0
- package/dist/services/llm-proxy/usage.js +108 -0
- package/dist/services/llm-proxy/usage.js.map +1 -0
- package/dist/services/nomad-manager.d.ts +22 -0
- package/dist/services/nomad-manager.js +828 -0
- package/dist/services/nomad-manager.js.map +1 -0
- package/dist/services/plugin-installer.d.ts +22 -0
- package/dist/services/plugin-installer.js +102 -0
- package/dist/services/plugin-installer.js.map +1 -0
- package/dist/services/process-manager.d.ts +25 -0
- package/dist/services/process-manager.js +531 -0
- package/dist/services/process-manager.js.map +1 -0
- package/dist/services/setup-manager.d.ts +93 -0
- package/dist/services/setup-manager.js +1922 -0
- package/dist/services/setup-manager.js.map +1 -0
- package/dist/services/system-monitor.d.ts +1 -0
- package/dist/services/system-monitor.js +79 -0
- package/dist/services/system-monitor.js.map +1 -0
- package/dist/services/telemetry/activation.d.ts +12 -0
- package/dist/services/telemetry/activation.js +78 -0
- package/dist/services/telemetry/activation.js.map +1 -0
- package/dist/services/telemetry/client.d.ts +21 -0
- package/dist/services/telemetry/client.js +36 -0
- package/dist/services/telemetry/client.js.map +1 -0
- package/dist/services/telemetry/device-fingerprint.d.ts +18 -0
- package/dist/services/telemetry/device-fingerprint.js +123 -0
- package/dist/services/telemetry/device-fingerprint.js.map +1 -0
- package/dist/services/telemetry/heartbeat.d.ts +13 -0
- package/dist/services/telemetry/heartbeat.js +87 -0
- package/dist/services/telemetry/heartbeat.js.map +1 -0
- package/dist/services/telemetry/index.d.ts +3 -0
- package/dist/services/telemetry/index.js +4 -0
- package/dist/services/telemetry/index.js.map +1 -0
- package/dist/types.d.ts +51 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/safe-json.d.ts +2 -0
- package/dist/utils/safe-json.js +80 -0
- package/dist/utils/safe-json.js.map +1 -0
- package/dist/utils/ttl-cache.d.ts +29 -0
- package/dist/utils/ttl-cache.js +77 -0
- package/dist/utils/ttl-cache.js.map +1 -0
- package/install/jishu-install.sh +2920 -0
- package/install/jishu-uninstall.sh +811 -0
- package/install/post-install.sh +124 -0
- package/install/post-uninstall.sh +46 -0
- package/package.json +57 -8
- package/public/assets/Dashboard-Dxsq690N.js +1 -0
- package/public/assets/InitPassword-CslWYy8G.js +1 -0
- package/public/assets/InstanceDetail-DmEkMj-t.js +14 -0
- package/public/assets/Login-d45wtgVA.js +1 -0
- package/public/assets/NewInstance-Czp5-AJe.js +1 -0
- package/public/assets/Settings-BKMGck05.js +1 -0
- package/public/assets/Setup-D3rfLWjZ.js +1 -0
- package/public/assets/index-77Ug7feY.css +1 -0
- package/public/assets/index-DkDnIohs.js +16 -0
- package/public/assets/logo-black-theme-DywLAtFy.png +0 -0
- package/public/assets/logo-white-theme-DXffFAWw.png +0 -0
- package/public/assets/providers-lBSOjUWy.js +1 -0
- package/public/assets/usePolling-CqQ8hrNc.js +1 -0
- package/public/assets/vendor-i18n-Bvxxh8Di.js +9 -0
- package/public/assets/vendor-react-DONn7uBV.js +59 -0
- package/public/index.html +15 -0
- package/scripts/build-image.sh +55 -0
- package/scripts/run.sh +310 -0
- package/scripts/setup-pi.sh +80 -0
- package/scripts/start-feishu1.js +46 -0
- package/index.js +0 -0
- package/jishushell-0.0.1.tgz +0 -0
package/dist/server.js
ADDED
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import Fastify from "fastify";
|
|
2
|
+
import fastifyStatic from "@fastify/static";
|
|
3
|
+
import { join, dirname } from "path";
|
|
4
|
+
import { existsSync, realpathSync } from "fs";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
import { request as httpRequest } from "http";
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = dirname(__filename);
|
|
9
|
+
import { ensureDirs, ensurePanelConfig, getPanelConfig } from "./config.js";
|
|
10
|
+
import { verifyToken } from "./auth.js";
|
|
11
|
+
import { authRoutes } from "./routes/auth.js";
|
|
12
|
+
import { instanceRoutes } from "./routes/instances.js";
|
|
13
|
+
import { systemRoutes } from "./routes/system.js";
|
|
14
|
+
import { setupRoutes } from "./routes/setup.js";
|
|
15
|
+
import * as llmProxy from "./services/llm-proxy/index.js";
|
|
16
|
+
import * as nomadManager from "./services/nomad-manager.js";
|
|
17
|
+
import * as instanceManager from "./services/instance-manager.js";
|
|
18
|
+
import * as setupManager from "./services/setup-manager.js";
|
|
19
|
+
import { PROXY_IDENTITY_HEADERS } from "./constants.js";
|
|
20
|
+
const PUBLIC_PATHS = new Set(["/api/auth/status", "/api/auth/init", "/api/auth/login", "/api/setup/status"]);
|
|
21
|
+
export async function createServer(options = {}) {
|
|
22
|
+
const port = options.port || 8090;
|
|
23
|
+
const host = options.host || "0.0.0.0";
|
|
24
|
+
ensureDirs();
|
|
25
|
+
llmProxy.rebuildTokenMap();
|
|
26
|
+
setupManager.loadNomadToken();
|
|
27
|
+
const app = Fastify({
|
|
28
|
+
logger: true,
|
|
29
|
+
bodyLimit: 1048576,
|
|
30
|
+
});
|
|
31
|
+
// Allow empty JSON body for POST requests
|
|
32
|
+
app.addContentTypeParser("application/json", { parseAs: "string" }, (req, body, done) => {
|
|
33
|
+
if (!body || body.length === 0) {
|
|
34
|
+
done(null, {});
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
try {
|
|
38
|
+
done(null, JSON.parse(body));
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
done(e, undefined);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
// Auth middleware
|
|
46
|
+
app.addHook("onRequest", async (request, reply) => {
|
|
47
|
+
const path = request.url.split("?")[0];
|
|
48
|
+
if (!path.startsWith("/api/") || PUBLIC_PATHS.has(path))
|
|
49
|
+
return;
|
|
50
|
+
// Allow gateway proxy without panel auth (gateway has its own auth),
|
|
51
|
+
// but verify the instance actually exists to prevent probing.
|
|
52
|
+
if (/^\/api\/instances\/[^/]+\/gateway(\/|$)/.test(path)) {
|
|
53
|
+
const id = path.match(/^\/api\/instances\/([^/]+)\/gateway/)?.[1];
|
|
54
|
+
if (!id || !instanceManager.getInstance(id)) {
|
|
55
|
+
return reply.status(404).send({ detail: "Instance not found" });
|
|
56
|
+
}
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
// Check Authorization header first, then fall back to httpOnly cookie
|
|
60
|
+
const authHeader = request.headers.authorization || "";
|
|
61
|
+
const match = authHeader.match(/^Bearer\s+(\S+)$/);
|
|
62
|
+
let token = match?.[1] || "";
|
|
63
|
+
if (!token) {
|
|
64
|
+
const cookie = request.headers.cookie || "";
|
|
65
|
+
const cookieMatch = cookie.match(/(?:^|;\s*)jishushell_session=([^;]*)/);
|
|
66
|
+
token = cookieMatch?.[1] || "";
|
|
67
|
+
}
|
|
68
|
+
if (!token || token.length > 4096 || !verifyToken(token)) {
|
|
69
|
+
return reply.status(401).send({ detail: "Unauthorized" });
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
// Global error handler — hide stack traces in production
|
|
73
|
+
app.setErrorHandler((error, _request, reply) => {
|
|
74
|
+
const statusCode = error.statusCode || 500;
|
|
75
|
+
if (statusCode >= 500) {
|
|
76
|
+
console.error("[server] Internal error:", error.message || error);
|
|
77
|
+
}
|
|
78
|
+
reply.status(statusCode).send({
|
|
79
|
+
detail: statusCode >= 500 ? "Internal server error" : (error.message || "Error"),
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
// Register proxy routes before auth middleware (proxy uses its own token auth)
|
|
83
|
+
await llmProxy.registerProxyRoutes(app);
|
|
84
|
+
// Register routes
|
|
85
|
+
// authRoutes needs a rebind callback so /api/auth/init can switch from 127.0.0.1 → 0.0.0.0
|
|
86
|
+
// without calling process.exit(). We define the callback after listen() and patch it in below.
|
|
87
|
+
let _rebind = null;
|
|
88
|
+
await app.register(authRoutes, {
|
|
89
|
+
getRebind: () => _rebind,
|
|
90
|
+
});
|
|
91
|
+
await app.register(instanceRoutes);
|
|
92
|
+
await app.register(systemRoutes);
|
|
93
|
+
await app.register(setupRoutes);
|
|
94
|
+
// Serve frontend static files
|
|
95
|
+
// Look for frontend dist in multiple locations
|
|
96
|
+
const resolvedDir = existsSync(__dirname) ? realpathSync(__dirname) : __dirname;
|
|
97
|
+
const frontendCandidates = [
|
|
98
|
+
join(resolvedDir, "..", "public"), // npm package: dist/ + public/ siblings
|
|
99
|
+
join(resolvedDir, "..", "frontend", "dist"), // dev: project root legacy path
|
|
100
|
+
];
|
|
101
|
+
let frontendDir = "";
|
|
102
|
+
for (const candidate of frontendCandidates) {
|
|
103
|
+
if (existsSync(join(candidate, "index.html"))) {
|
|
104
|
+
frontendDir = candidate;
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (frontendDir) {
|
|
109
|
+
// Serve /assets/ directory
|
|
110
|
+
const assetsDir = join(frontendDir, "assets");
|
|
111
|
+
if (existsSync(assetsDir)) {
|
|
112
|
+
await app.register(fastifyStatic, {
|
|
113
|
+
root: assetsDir,
|
|
114
|
+
prefix: "/assets/",
|
|
115
|
+
decorateReply: false,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
// Serve other static files and SPA fallback
|
|
119
|
+
await app.register(fastifyStatic, {
|
|
120
|
+
root: frontendDir,
|
|
121
|
+
prefix: "/",
|
|
122
|
+
decorateReply: true,
|
|
123
|
+
wildcard: false,
|
|
124
|
+
});
|
|
125
|
+
// SPA fallback: serve index.html for non-API, non-asset routes
|
|
126
|
+
app.setNotFoundHandler(async (request, reply) => {
|
|
127
|
+
const path = request.url.split("?")[0];
|
|
128
|
+
if (path.startsWith("/api/")) {
|
|
129
|
+
return reply.status(404).send({ detail: "Not found" });
|
|
130
|
+
}
|
|
131
|
+
if (path.startsWith("/proxy/")) {
|
|
132
|
+
return reply.status(404).send({
|
|
133
|
+
error: { message: "proxy route not found", type: "server_error" },
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return reply.sendFile("index.html");
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
// Auto-start Nomad-managed instances on startup
|
|
140
|
+
app.addHook("onReady", async () => {
|
|
141
|
+
setTimeout(async () => {
|
|
142
|
+
try {
|
|
143
|
+
ensurePanelConfig();
|
|
144
|
+
const config = getPanelConfig();
|
|
145
|
+
if (config.service_manager === "nomad") {
|
|
146
|
+
const nomadResult = await setupManager.startNomad();
|
|
147
|
+
if (!nomadResult.ok) {
|
|
148
|
+
console.error(`[startup] Nomad not available: ${nomadResult.error || nomadResult.message}`);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
console.log(`[startup] Nomad: ${nomadResult.message}`);
|
|
152
|
+
}
|
|
153
|
+
// Auto-start stopped instances that were running before jishushell was restarted.
|
|
154
|
+
// Running instances are left alone — no forced restart to avoid unnecessary disruption.
|
|
155
|
+
try {
|
|
156
|
+
for (const inst of instanceManager.listInstances()) {
|
|
157
|
+
if (!inst.id)
|
|
158
|
+
continue;
|
|
159
|
+
const status = await nomadManager.getStatus(inst.id);
|
|
160
|
+
if (status.status === "running") {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
else if (status.status === "pending" || status.status === "stopped") {
|
|
164
|
+
const shouldStart = await nomadManager.shouldAutoStart(inst.id);
|
|
165
|
+
if (shouldStart) {
|
|
166
|
+
console.log(`[startup] Auto-starting Nomad instance ${inst.id} (was running before restart)...`);
|
|
167
|
+
await nomadManager.startInstance(inst.id);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
console.log("[startup] Nomad instances started/restarted.");
|
|
172
|
+
}
|
|
173
|
+
catch (e) {
|
|
174
|
+
console.error("[startup] Nomad restart failed:", e);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
catch (e) {
|
|
179
|
+
console.log(`[startup] Auto-start failed: ${e}`);
|
|
180
|
+
}
|
|
181
|
+
}, 0);
|
|
182
|
+
});
|
|
183
|
+
await app.listen({ port, host });
|
|
184
|
+
// Assign the rebind implementation now that the server is listening.
|
|
185
|
+
// Called by /api/auth/init to switch from 127.0.0.1 → 0.0.0.0 in-process.
|
|
186
|
+
_rebind = async (newHost) => {
|
|
187
|
+
await new Promise((resolve, reject) => {
|
|
188
|
+
app.server.close((err) => { if (err)
|
|
189
|
+
reject(err);
|
|
190
|
+
else
|
|
191
|
+
resolve(); });
|
|
192
|
+
});
|
|
193
|
+
await new Promise((resolve, reject) => {
|
|
194
|
+
app.server.listen(port, newHost, () => {
|
|
195
|
+
console.log(`[server] Rebound to http://${newHost}:${port}`);
|
|
196
|
+
resolve();
|
|
197
|
+
});
|
|
198
|
+
app.server.once("error", reject);
|
|
199
|
+
});
|
|
200
|
+
};
|
|
201
|
+
// Track active WebSocket proxy sockets for graceful shutdown
|
|
202
|
+
const activeWsSockets = new Set();
|
|
203
|
+
// Handle WebSocket upgrades directly on the HTTP server, bypassing Fastify's
|
|
204
|
+
// request lifecycle. Fastify's internal headersTimeout (73s) kills hijacked
|
|
205
|
+
// sockets, so we intercept upgrades before Fastify sees them.
|
|
206
|
+
const GATEWAY_WS_RE = /^\/api\/instances\/([a-z0-9][a-z0-9-]{0,62})\/gateway(?:\/(.*))?$/;
|
|
207
|
+
app.server.on("upgrade", async (req, socket, head) => {
|
|
208
|
+
const url = req.url || "";
|
|
209
|
+
const path = url.split("?")[0];
|
|
210
|
+
const match = path.match(GATEWAY_WS_RE);
|
|
211
|
+
if (!match) {
|
|
212
|
+
// Not a gateway WebSocket — let it drop (Fastify doesn't handle WS natively)
|
|
213
|
+
socket.destroy();
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
// Defense-in-depth: validate Origin header for WebSocket upgrades.
|
|
217
|
+
// Require Origin for non-loopback clients; gateway has its own token auth as primary.
|
|
218
|
+
const origin = req.headers.origin || "";
|
|
219
|
+
const remoteIp = socket.remoteAddress || "";
|
|
220
|
+
const isLoopback = remoteIp === "127.0.0.1" || remoteIp === "::1" || remoteIp === "::ffff:127.0.0.1";
|
|
221
|
+
if (!origin && !isLoopback) {
|
|
222
|
+
socket.write("HTTP/1.1 403 Forbidden\r\n\r\n");
|
|
223
|
+
socket.destroy();
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
if (origin) {
|
|
227
|
+
const reqHost = req.headers.host || "";
|
|
228
|
+
try {
|
|
229
|
+
const originHost = new URL(origin).host.toLowerCase();
|
|
230
|
+
if (originHost !== reqHost.toLowerCase()) {
|
|
231
|
+
socket.write("HTTP/1.1 403 Forbidden\r\n\r\n");
|
|
232
|
+
socket.destroy();
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
socket.write("HTTP/1.1 403 Forbidden\r\n\r\n");
|
|
238
|
+
socket.destroy();
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
const id = match[1];
|
|
243
|
+
const inst = instanceManager.getInstance(id);
|
|
244
|
+
if (!inst) {
|
|
245
|
+
socket.destroy();
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const gwPort = instanceManager.getGatewayPort(id);
|
|
249
|
+
const gwHost = await instanceManager.getGatewayHost(id);
|
|
250
|
+
const suffix = match[2] || "";
|
|
251
|
+
const qs = url.includes("?") ? url.slice(url.indexOf("?")) : "";
|
|
252
|
+
const targetPath = `/${suffix}${qs}`;
|
|
253
|
+
const upstreamHeaders = {};
|
|
254
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
255
|
+
if (value === undefined)
|
|
256
|
+
continue;
|
|
257
|
+
const lower = key.toLowerCase();
|
|
258
|
+
if (lower === "host" ||
|
|
259
|
+
PROXY_IDENTITY_HEADERS.has(lower) ||
|
|
260
|
+
// Strip panel auth credentials — do not leak to downstream OpenClaw gateway
|
|
261
|
+
lower === "cookie" ||
|
|
262
|
+
lower === "authorization")
|
|
263
|
+
continue;
|
|
264
|
+
upstreamHeaders[key] = value;
|
|
265
|
+
}
|
|
266
|
+
// Prevent any HTTP-level timeouts from killing this long-lived connection
|
|
267
|
+
socket.setTimeout?.(0);
|
|
268
|
+
socket.setNoDelay?.(true);
|
|
269
|
+
socket.setKeepAlive?.(true, 30000);
|
|
270
|
+
let proxyReq;
|
|
271
|
+
try {
|
|
272
|
+
proxyReq = httpRequest({
|
|
273
|
+
hostname: gwHost,
|
|
274
|
+
port: gwPort,
|
|
275
|
+
path: targetPath,
|
|
276
|
+
method: "GET",
|
|
277
|
+
timeout: 10000, // 10s timeout for upstream upgrade handshake
|
|
278
|
+
headers: {
|
|
279
|
+
...upstreamHeaders,
|
|
280
|
+
host: `${gwHost}:${gwPort}`,
|
|
281
|
+
},
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
catch {
|
|
285
|
+
try {
|
|
286
|
+
socket.destroy();
|
|
287
|
+
}
|
|
288
|
+
catch { }
|
|
289
|
+
activeWsSockets.delete(socket);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
proxyReq.on("timeout", () => {
|
|
293
|
+
proxyReq.destroy();
|
|
294
|
+
socket.destroy();
|
|
295
|
+
});
|
|
296
|
+
proxyReq.on("upgrade", (_res, proxySocket, proxyHead) => {
|
|
297
|
+
proxySocket.setTimeout(0);
|
|
298
|
+
proxySocket.setNoDelay(true);
|
|
299
|
+
proxySocket.setKeepAlive(true, 30000);
|
|
300
|
+
// Pause upstream until the 101 handshake is flushed to the client
|
|
301
|
+
proxySocket.pause();
|
|
302
|
+
// Build and send 101 response — forward all sec-websocket-* headers
|
|
303
|
+
let handshake = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\n";
|
|
304
|
+
for (const [k, v] of Object.entries(_res.headers)) {
|
|
305
|
+
if (v !== undefined && k.toLowerCase().startsWith("sec-websocket-")) {
|
|
306
|
+
handshake += `${k}: ${v}\r\n`;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
handshake += "\r\n";
|
|
310
|
+
socket.write(handshake);
|
|
311
|
+
if (head.length > 0)
|
|
312
|
+
proxySocket.write(head);
|
|
313
|
+
if (proxyHead.length > 0)
|
|
314
|
+
socket.write(proxyHead);
|
|
315
|
+
// Bidirectional pipe: forward all WebSocket frames without interception.
|
|
316
|
+
// OpenClaw manages its own upgrades inside the container.
|
|
317
|
+
proxySocket.pipe(socket);
|
|
318
|
+
socket.pipe(proxySocket);
|
|
319
|
+
proxySocket.resume();
|
|
320
|
+
activeWsSockets.add(socket);
|
|
321
|
+
activeWsSockets.add(proxySocket);
|
|
322
|
+
const release = (s) => {
|
|
323
|
+
activeWsSockets.delete(s);
|
|
324
|
+
};
|
|
325
|
+
const fail = () => {
|
|
326
|
+
try {
|
|
327
|
+
proxySocket.destroy();
|
|
328
|
+
}
|
|
329
|
+
catch { }
|
|
330
|
+
try {
|
|
331
|
+
socket.destroy();
|
|
332
|
+
}
|
|
333
|
+
catch { }
|
|
334
|
+
release(socket);
|
|
335
|
+
release(proxySocket);
|
|
336
|
+
};
|
|
337
|
+
// Do not destroy the peer on normal close. The upstream may have already
|
|
338
|
+
// sent a WebSocket close frame, and force-destroying the other side turns
|
|
339
|
+
// that graceful close into a browser-visible 1006.
|
|
340
|
+
proxySocket.on("close", () => {
|
|
341
|
+
release(proxySocket);
|
|
342
|
+
try {
|
|
343
|
+
if (!socket.destroyed && !socket.writableEnded)
|
|
344
|
+
socket.end();
|
|
345
|
+
}
|
|
346
|
+
catch { }
|
|
347
|
+
});
|
|
348
|
+
socket.on("close", () => {
|
|
349
|
+
release(socket);
|
|
350
|
+
try {
|
|
351
|
+
if (!proxySocket.destroyed && !proxySocket.writableEnded)
|
|
352
|
+
proxySocket.end();
|
|
353
|
+
}
|
|
354
|
+
catch { }
|
|
355
|
+
});
|
|
356
|
+
proxySocket.on("error", fail);
|
|
357
|
+
socket.on("error", fail);
|
|
358
|
+
});
|
|
359
|
+
proxyReq.on("error", () => {
|
|
360
|
+
try {
|
|
361
|
+
socket.write("HTTP/1.1 502 Bad Gateway\r\nConnection: close\r\n\r\n");
|
|
362
|
+
}
|
|
363
|
+
catch { }
|
|
364
|
+
socket.destroy();
|
|
365
|
+
activeWsSockets.delete(socket);
|
|
366
|
+
});
|
|
367
|
+
proxyReq.end();
|
|
368
|
+
});
|
|
369
|
+
llmProxy.setProxyPort(port);
|
|
370
|
+
setupManager.setServerPort(port);
|
|
371
|
+
nomadManager.setPanelPort(port);
|
|
372
|
+
console.log(`JishuShell listening on http://${host}:${port}`);
|
|
373
|
+
// Graceful shutdown — let in-flight requests finish before exiting
|
|
374
|
+
const shutdown = async () => {
|
|
375
|
+
console.log("[server] Shutting down gracefully...");
|
|
376
|
+
llmProxy.flushUsage();
|
|
377
|
+
// Destroy all active WebSocket proxy connections
|
|
378
|
+
for (const s of activeWsSockets) {
|
|
379
|
+
try {
|
|
380
|
+
s.destroy();
|
|
381
|
+
}
|
|
382
|
+
catch { }
|
|
383
|
+
}
|
|
384
|
+
activeWsSockets.clear();
|
|
385
|
+
await app.close();
|
|
386
|
+
process.exit(0);
|
|
387
|
+
};
|
|
388
|
+
process.on("SIGTERM", shutdown);
|
|
389
|
+
process.on("SIGINT", shutdown);
|
|
390
|
+
return app;
|
|
391
|
+
}
|
|
392
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
type ConfigChangeListener = (instanceId: string) => void;
|
|
2
|
+
export declare function onConfigChange(listener: ConfigChangeListener): () => void;
|
|
3
|
+
declare function instanceDir(instanceId: string): string;
|
|
4
|
+
export declare function getResolvedOpenclawBin(): string;
|
|
5
|
+
/**
|
|
6
|
+
* When jishushell runs as root (e.g. systemd service), returns the actual
|
|
7
|
+
* non-root user that should own instance files and run openclaw processes.
|
|
8
|
+
* Returns null when not running as root or when no suitable non-root user is found.
|
|
9
|
+
*/
|
|
10
|
+
export declare function resolveServiceUser(): {
|
|
11
|
+
username: string;
|
|
12
|
+
uid: number;
|
|
13
|
+
gid: number;
|
|
14
|
+
} | null;
|
|
15
|
+
export declare function parseEnvFile(path: string): Record<string, string>;
|
|
16
|
+
export declare function updateEnvFile(path: string, updates: Record<string, string>): void;
|
|
17
|
+
export declare function inferProviderApiKeyEnvName(providerId: string): string;
|
|
18
|
+
export declare const CHANNEL_PLUGIN_MAP: Record<string, string>;
|
|
19
|
+
/** Check if a channel plugin is installed for an instance. */
|
|
20
|
+
export declare function isChannelPluginInstalled(instanceId: string, channelId: string): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Install a single channel plugin on the host.
|
|
23
|
+
* This is the unified entry point for all plugin installation — never use docker exec.
|
|
24
|
+
*/
|
|
25
|
+
export declare function installChannelPlugin(instanceId: string, channelId: string): Promise<void>;
|
|
26
|
+
export declare function listInstances(): Record<string, any>[];
|
|
27
|
+
export declare function getInstance(instanceId: string): Record<string, any> | null;
|
|
28
|
+
export declare function createInstance(instanceId: string, name: string, description?: string, cloneFrom?: string, openclawHome?: string): Promise<Record<string, any>>;
|
|
29
|
+
export declare function updateInstance(instanceId: string, name?: string, description?: string): Record<string, any> | null;
|
|
30
|
+
export declare function deleteInstance(instanceId: string): {
|
|
31
|
+
ok: boolean;
|
|
32
|
+
warnings?: string[];
|
|
33
|
+
};
|
|
34
|
+
export declare function getConfig(instanceId: string): Record<string, any> | null;
|
|
35
|
+
export declare function getStoredConfig(instanceId: string): Record<string, any> | null;
|
|
36
|
+
export declare function saveConfig(instanceId: string, config: Record<string, any>): boolean;
|
|
37
|
+
export declare function getOpenclawHome(instanceId: string): string;
|
|
38
|
+
export declare function saveFeishuCredentials(instanceId: string, creds: {
|
|
39
|
+
appId: string;
|
|
40
|
+
appSecret: string;
|
|
41
|
+
domain: string;
|
|
42
|
+
channelKey?: string;
|
|
43
|
+
}): void;
|
|
44
|
+
export declare function saveWeixinCredentials(instanceId: string, creds: {
|
|
45
|
+
accountId: string;
|
|
46
|
+
token: string;
|
|
47
|
+
baseUrl: string;
|
|
48
|
+
userId: string;
|
|
49
|
+
}): void;
|
|
50
|
+
/**
|
|
51
|
+
* Get connected WeChat accounts for an instance.
|
|
52
|
+
*/
|
|
53
|
+
export declare function getWeixinAccounts(instanceId: string): Array<{
|
|
54
|
+
accountId: string;
|
|
55
|
+
userId?: string;
|
|
56
|
+
savedAt?: string;
|
|
57
|
+
}>;
|
|
58
|
+
export declare function getOpenclawConfigPath(instanceId: string): string;
|
|
59
|
+
export declare function getLegacyOpenclawConfigPath(instanceId: string): string;
|
|
60
|
+
export declare function getInstanceRuntime(instanceId: string): Record<string, any>;
|
|
61
|
+
export declare function getRuntimeEnvFiles(instanceId: string): string[];
|
|
62
|
+
export declare function getGatewayPort(instanceId: string): number;
|
|
63
|
+
export declare function getGatewayHost(instanceId: string): Promise<string>;
|
|
64
|
+
export declare function findInstancesSharingOpenclawHome(instanceId: string): string[];
|
|
65
|
+
export declare function findInstancesSharingGatewayPort(instanceId: string): string[];
|
|
66
|
+
export declare function getRuntimeEnv(instanceId: string): Record<string, string>;
|
|
67
|
+
export { instanceDir as getInstanceDir };
|