@wrongstack/webui 0.6.0 → 0.6.1
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/dist/server/entry.js +103 -19
- package/dist/server/entry.js.map +1 -1
- package/dist/server/index.js +103 -19
- package/dist/server/index.js.map +1 -1
- package/package.json +5 -5
package/dist/server/entry.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// src/server/index.ts
|
|
3
3
|
import * as fs2 from "fs/promises";
|
|
4
|
+
import * as http from "http";
|
|
4
5
|
import * as path from "path";
|
|
5
6
|
import {
|
|
6
7
|
Agent,
|
|
@@ -85,7 +86,13 @@ async function startWebUI(opts = {}) {
|
|
|
85
86
|
const { config: baseConfig, vault, globalConfigPath, projectRoot, wpaths, logger } = boot;
|
|
86
87
|
let config = baseConfig;
|
|
87
88
|
let configWriteLock = Promise.resolve();
|
|
88
|
-
console.log("[WebUI] Config loaded:", config.provider, "/", config.model);
|
|
89
|
+
console.log("[WebUI] Config loaded:", config.provider ?? "(none)", "/", config.model ?? "(none)");
|
|
90
|
+
if (!config.provider && config.providers && Object.keys(config.providers).length > 0) {
|
|
91
|
+
const firstKey = Object.keys(config.providers)[0];
|
|
92
|
+
config = patchConfig(config, { provider: firstKey });
|
|
93
|
+
console.log("[WebUI] No active provider \u2014 auto-selected:", firstKey);
|
|
94
|
+
}
|
|
95
|
+
const needsProvider = !config.provider || !config.model;
|
|
89
96
|
const modelsRegistry = new DefaultModelsRegistry({
|
|
90
97
|
cacheFile: wpaths.modelsCache,
|
|
91
98
|
ttlSeconds: 24 * 3600
|
|
@@ -153,22 +160,46 @@ async function startWebUI(opts = {}) {
|
|
|
153
160
|
provider: config.provider,
|
|
154
161
|
model: config.model
|
|
155
162
|
});
|
|
156
|
-
const providerConfig = config.providers?.[config.provider] ?? {
|
|
157
|
-
type: config.provider,
|
|
158
|
-
apiKey: config.apiKey,
|
|
159
|
-
baseUrl: config.baseUrl
|
|
160
|
-
};
|
|
161
163
|
let provider;
|
|
162
|
-
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
164
|
+
if (!needsProvider) {
|
|
165
|
+
const providerConfig = config.providers?.[config.provider] ?? {
|
|
166
|
+
type: config.provider,
|
|
167
|
+
apiKey: config.apiKey,
|
|
168
|
+
baseUrl: config.baseUrl
|
|
169
|
+
};
|
|
170
|
+
try {
|
|
171
|
+
const cfgWithType = { ...providerConfig, type: config.provider };
|
|
172
|
+
if (config.features.modelsRegistry && providerRegistry.has(config.provider)) {
|
|
173
|
+
provider = providerRegistry.create(cfgWithType);
|
|
174
|
+
} else {
|
|
175
|
+
provider = makeProviderFromConfig(config.provider, cfgWithType);
|
|
176
|
+
}
|
|
177
|
+
} catch (err) {
|
|
178
|
+
console.error("[WebUI] Failed to create provider:", err);
|
|
179
|
+
throw err;
|
|
180
|
+
}
|
|
181
|
+
} else {
|
|
182
|
+
const savedProviders = config.providers ?? {};
|
|
183
|
+
const firstKey = Object.keys(savedProviders)[0];
|
|
184
|
+
if (firstKey) {
|
|
185
|
+
const firstProvider = savedProviders[firstKey];
|
|
186
|
+
try {
|
|
187
|
+
provider = makeProviderFromConfig(firstKey, {
|
|
188
|
+
...firstProvider,
|
|
189
|
+
type: firstKey,
|
|
190
|
+
family: firstProvider.family,
|
|
191
|
+
apiKey: firstProvider.apiKey
|
|
192
|
+
});
|
|
193
|
+
console.log("[WebUI] Using saved provider:", firstKey);
|
|
194
|
+
} catch (err) {
|
|
195
|
+
console.error("[WebUI] Could not create provider stub:", err);
|
|
196
|
+
throw err;
|
|
197
|
+
}
|
|
166
198
|
} else {
|
|
167
|
-
|
|
199
|
+
throw new Error(
|
|
200
|
+
"No provider configured. Run `wrongstack init` first, or configure via the WebUI."
|
|
201
|
+
);
|
|
168
202
|
}
|
|
169
|
-
} catch (err) {
|
|
170
|
-
console.error("[WebUI] Failed to create provider:", err);
|
|
171
|
-
throw err;
|
|
172
203
|
}
|
|
173
204
|
const context = new Context({
|
|
174
205
|
systemPrompt,
|
|
@@ -473,8 +504,8 @@ async function startWebUI(opts = {}) {
|
|
|
473
504
|
rateLimits.delete(ws);
|
|
474
505
|
console.log("[WebUI] Client disconnected, total:", clients.size);
|
|
475
506
|
if (pendingConfirms.size > 0) {
|
|
476
|
-
for (const [id,
|
|
477
|
-
|
|
507
|
+
for (const [id, resolve2] of pendingConfirms) {
|
|
508
|
+
resolve2("no");
|
|
478
509
|
pendingConfirms.delete(id);
|
|
479
510
|
}
|
|
480
511
|
}
|
|
@@ -554,10 +585,10 @@ async function startWebUI(opts = {}) {
|
|
|
554
585
|
}
|
|
555
586
|
case "tool.confirm_result": {
|
|
556
587
|
const { id, decision } = msg.payload;
|
|
557
|
-
const
|
|
558
|
-
if (
|
|
588
|
+
const resolve2 = pendingConfirms.get(id);
|
|
589
|
+
if (resolve2) {
|
|
559
590
|
pendingConfirms.delete(id);
|
|
560
|
-
|
|
591
|
+
resolve2(decision);
|
|
561
592
|
}
|
|
562
593
|
break;
|
|
563
594
|
}
|
|
@@ -1419,6 +1450,58 @@ async function startWebUI(opts = {}) {
|
|
|
1419
1450
|
sendResult(ws, false, err instanceof Error ? err.message : String(err));
|
|
1420
1451
|
}
|
|
1421
1452
|
}
|
|
1453
|
+
const httpPort = Number.parseInt(process.env["PORT"] ?? "3456", 10);
|
|
1454
|
+
const DIST_DIR = path.resolve(import.meta.dirname, "../../dist");
|
|
1455
|
+
const mimeTypes = {
|
|
1456
|
+
".html": "text/html",
|
|
1457
|
+
".js": "application/javascript",
|
|
1458
|
+
".css": "text/css",
|
|
1459
|
+
".json": "application/json",
|
|
1460
|
+
".svg": "image/svg+xml",
|
|
1461
|
+
".png": "image/png",
|
|
1462
|
+
".ico": "image/x-icon"
|
|
1463
|
+
};
|
|
1464
|
+
const httpServer = http.createServer(async (req, res) => {
|
|
1465
|
+
try {
|
|
1466
|
+
const url = new URL(req.url ?? "/", `http://127.0.0.1:${httpPort}`);
|
|
1467
|
+
let filePath;
|
|
1468
|
+
if (url.pathname === "/" || url.pathname === "") {
|
|
1469
|
+
filePath = path.join(DIST_DIR, "index.html");
|
|
1470
|
+
} else if (url.pathname.startsWith("/assets/")) {
|
|
1471
|
+
filePath = path.join(DIST_DIR, url.pathname);
|
|
1472
|
+
} else if (url.pathname.startsWith("/")) {
|
|
1473
|
+
filePath = path.join(DIST_DIR, url.pathname);
|
|
1474
|
+
} else {
|
|
1475
|
+
filePath = path.join(DIST_DIR, "index.html");
|
|
1476
|
+
}
|
|
1477
|
+
const ext = path.extname(filePath);
|
|
1478
|
+
const contentType = mimeTypes[ext] ?? "application/octet-stream";
|
|
1479
|
+
res.setHeader("Content-Type", contentType);
|
|
1480
|
+
if (ext === ".html") {
|
|
1481
|
+
res.setHeader("Cache-Control", "no-cache");
|
|
1482
|
+
}
|
|
1483
|
+
const fileContent = await fs2.readFile(filePath);
|
|
1484
|
+
res.writeHead(200);
|
|
1485
|
+
res.end(fileContent);
|
|
1486
|
+
} catch (err) {
|
|
1487
|
+
if (err.code === "ENOENT") {
|
|
1488
|
+
try {
|
|
1489
|
+
const fileContent = await fs2.readFile(path.join(DIST_DIR, "index.html"));
|
|
1490
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
1491
|
+
res.end(fileContent);
|
|
1492
|
+
} catch {
|
|
1493
|
+
res.writeHead(404);
|
|
1494
|
+
res.end("Not found");
|
|
1495
|
+
}
|
|
1496
|
+
} else {
|
|
1497
|
+
res.writeHead(500);
|
|
1498
|
+
res.end("Server error");
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
});
|
|
1502
|
+
httpServer.listen(httpPort, wsHost2, () => {
|
|
1503
|
+
console.log(`[WebUI] HTTP server running on http://${wsHost2}:${httpPort}`);
|
|
1504
|
+
});
|
|
1422
1505
|
const shutdown = async () => {
|
|
1423
1506
|
console.log("[WebUI] Shutting down...");
|
|
1424
1507
|
try {
|
|
@@ -1432,6 +1515,7 @@ async function startWebUI(opts = {}) {
|
|
|
1432
1515
|
console.warn("[WebUI] Error closing session:", e);
|
|
1433
1516
|
}
|
|
1434
1517
|
for (const [ws] of clients) ws.close();
|
|
1518
|
+
httpServer.close();
|
|
1435
1519
|
wssPrimary.close();
|
|
1436
1520
|
wssSecondary?.close();
|
|
1437
1521
|
process.exit(0);
|