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