@wrongstack/webui 0.6.0 → 0.6.3
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 +105 -29
- package/dist/server/entry.js.map +1 -1
- package/dist/server/index.js +105 -29
- 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,
|
|
@@ -13,6 +14,7 @@ import {
|
|
|
13
14
|
DefaultSkillLoader,
|
|
14
15
|
DefaultSystemPromptBuilder,
|
|
15
16
|
DefaultTokenCounter,
|
|
17
|
+
estimateRequestTokens,
|
|
16
18
|
EventBus,
|
|
17
19
|
HybridCompactor,
|
|
18
20
|
ProviderRegistry,
|
|
@@ -85,7 +87,13 @@ async function startWebUI(opts = {}) {
|
|
|
85
87
|
const { config: baseConfig, vault, globalConfigPath, projectRoot, wpaths, logger } = boot;
|
|
86
88
|
let config = baseConfig;
|
|
87
89
|
let configWriteLock = Promise.resolve();
|
|
88
|
-
console.log("[WebUI] Config loaded:", config.provider, "/", config.model);
|
|
90
|
+
console.log("[WebUI] Config loaded:", config.provider ?? "(none)", "/", config.model ?? "(none)");
|
|
91
|
+
if (!config.provider && config.providers && Object.keys(config.providers).length > 0) {
|
|
92
|
+
const firstKey = Object.keys(config.providers)[0];
|
|
93
|
+
config = patchConfig(config, { provider: firstKey });
|
|
94
|
+
console.log("[WebUI] No active provider \u2014 auto-selected:", firstKey);
|
|
95
|
+
}
|
|
96
|
+
const needsProvider = !config.provider || !config.model;
|
|
89
97
|
const modelsRegistry = new DefaultModelsRegistry({
|
|
90
98
|
cacheFile: wpaths.modelsCache,
|
|
91
99
|
ttlSeconds: 24 * 3600
|
|
@@ -153,22 +161,46 @@ async function startWebUI(opts = {}) {
|
|
|
153
161
|
provider: config.provider,
|
|
154
162
|
model: config.model
|
|
155
163
|
});
|
|
156
|
-
const providerConfig = config.providers?.[config.provider] ?? {
|
|
157
|
-
type: config.provider,
|
|
158
|
-
apiKey: config.apiKey,
|
|
159
|
-
baseUrl: config.baseUrl
|
|
160
|
-
};
|
|
161
164
|
let provider;
|
|
162
|
-
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
165
|
+
if (!needsProvider) {
|
|
166
|
+
const providerConfig = config.providers?.[config.provider] ?? {
|
|
167
|
+
type: config.provider,
|
|
168
|
+
apiKey: config.apiKey,
|
|
169
|
+
baseUrl: config.baseUrl
|
|
170
|
+
};
|
|
171
|
+
try {
|
|
172
|
+
const cfgWithType = { ...providerConfig, type: config.provider };
|
|
173
|
+
if (config.features.modelsRegistry && providerRegistry.has(config.provider)) {
|
|
174
|
+
provider = providerRegistry.create(cfgWithType);
|
|
175
|
+
} else {
|
|
176
|
+
provider = makeProviderFromConfig(config.provider, cfgWithType);
|
|
177
|
+
}
|
|
178
|
+
} catch (err) {
|
|
179
|
+
console.error("[WebUI] Failed to create provider:", err);
|
|
180
|
+
throw err;
|
|
181
|
+
}
|
|
182
|
+
} else {
|
|
183
|
+
const savedProviders = config.providers ?? {};
|
|
184
|
+
const firstKey = Object.keys(savedProviders)[0];
|
|
185
|
+
if (firstKey) {
|
|
186
|
+
const firstProvider = savedProviders[firstKey];
|
|
187
|
+
try {
|
|
188
|
+
provider = makeProviderFromConfig(firstKey, {
|
|
189
|
+
...firstProvider,
|
|
190
|
+
type: firstKey,
|
|
191
|
+
family: firstProvider.family,
|
|
192
|
+
apiKey: firstProvider.apiKey
|
|
193
|
+
});
|
|
194
|
+
console.log("[WebUI] Using saved provider:", firstKey);
|
|
195
|
+
} catch (err) {
|
|
196
|
+
console.error("[WebUI] Could not create provider stub:", err);
|
|
197
|
+
throw err;
|
|
198
|
+
}
|
|
166
199
|
} else {
|
|
167
|
-
|
|
200
|
+
throw new Error(
|
|
201
|
+
"No provider configured. Run `wrongstack init` first, or configure via the WebUI."
|
|
202
|
+
);
|
|
168
203
|
}
|
|
169
|
-
} catch (err) {
|
|
170
|
-
console.error("[WebUI] Failed to create provider:", err);
|
|
171
|
-
throw err;
|
|
172
204
|
}
|
|
173
205
|
const context = new Context({
|
|
174
206
|
systemPrompt,
|
|
@@ -194,16 +226,7 @@ async function startWebUI(opts = {}) {
|
|
|
194
226
|
autoCompactor = new AutoCompactionMiddleware(
|
|
195
227
|
compactor,
|
|
196
228
|
effectiveMaxContext,
|
|
197
|
-
(ctx) =>
|
|
198
|
-
let total = 0;
|
|
199
|
-
for (const m of ctx.messages) {
|
|
200
|
-
if (typeof m.content === "string") total += Math.ceil(m.content.length / 4);
|
|
201
|
-
else if (Array.isArray(m.content)) {
|
|
202
|
-
for (const b of m.content) total += Math.ceil(JSON.stringify(b).length / 4);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
return total;
|
|
206
|
-
},
|
|
229
|
+
(ctx) => estimateRequestTokens(ctx.messages, ctx.systemPrompt, ctx.tools ?? []).total,
|
|
207
230
|
{
|
|
208
231
|
warn: initialContextPolicy.thresholds.warn,
|
|
209
232
|
soft: initialContextPolicy.thresholds.soft,
|
|
@@ -473,8 +496,8 @@ async function startWebUI(opts = {}) {
|
|
|
473
496
|
rateLimits.delete(ws);
|
|
474
497
|
console.log("[WebUI] Client disconnected, total:", clients.size);
|
|
475
498
|
if (pendingConfirms.size > 0) {
|
|
476
|
-
for (const [id,
|
|
477
|
-
|
|
499
|
+
for (const [id, resolve2] of pendingConfirms) {
|
|
500
|
+
resolve2("no");
|
|
478
501
|
pendingConfirms.delete(id);
|
|
479
502
|
}
|
|
480
503
|
}
|
|
@@ -554,10 +577,10 @@ async function startWebUI(opts = {}) {
|
|
|
554
577
|
}
|
|
555
578
|
case "tool.confirm_result": {
|
|
556
579
|
const { id, decision } = msg.payload;
|
|
557
|
-
const
|
|
558
|
-
if (
|
|
580
|
+
const resolve2 = pendingConfirms.get(id);
|
|
581
|
+
if (resolve2) {
|
|
559
582
|
pendingConfirms.delete(id);
|
|
560
|
-
|
|
583
|
+
resolve2(decision);
|
|
561
584
|
}
|
|
562
585
|
break;
|
|
563
586
|
}
|
|
@@ -1419,6 +1442,58 @@ async function startWebUI(opts = {}) {
|
|
|
1419
1442
|
sendResult(ws, false, err instanceof Error ? err.message : String(err));
|
|
1420
1443
|
}
|
|
1421
1444
|
}
|
|
1445
|
+
const httpPort = Number.parseInt(process.env["PORT"] ?? "3456", 10);
|
|
1446
|
+
const DIST_DIR = path.resolve(import.meta.dirname, "../../dist");
|
|
1447
|
+
const mimeTypes = {
|
|
1448
|
+
".html": "text/html",
|
|
1449
|
+
".js": "application/javascript",
|
|
1450
|
+
".css": "text/css",
|
|
1451
|
+
".json": "application/json",
|
|
1452
|
+
".svg": "image/svg+xml",
|
|
1453
|
+
".png": "image/png",
|
|
1454
|
+
".ico": "image/x-icon"
|
|
1455
|
+
};
|
|
1456
|
+
const httpServer = http.createServer(async (req, res) => {
|
|
1457
|
+
try {
|
|
1458
|
+
const url = new URL(req.url ?? "/", `http://127.0.0.1:${httpPort}`);
|
|
1459
|
+
let filePath;
|
|
1460
|
+
if (url.pathname === "/" || url.pathname === "") {
|
|
1461
|
+
filePath = path.join(DIST_DIR, "index.html");
|
|
1462
|
+
} else if (url.pathname.startsWith("/assets/")) {
|
|
1463
|
+
filePath = path.join(DIST_DIR, url.pathname);
|
|
1464
|
+
} else if (url.pathname.startsWith("/")) {
|
|
1465
|
+
filePath = path.join(DIST_DIR, url.pathname);
|
|
1466
|
+
} else {
|
|
1467
|
+
filePath = path.join(DIST_DIR, "index.html");
|
|
1468
|
+
}
|
|
1469
|
+
const ext = path.extname(filePath);
|
|
1470
|
+
const contentType = mimeTypes[ext] ?? "application/octet-stream";
|
|
1471
|
+
res.setHeader("Content-Type", contentType);
|
|
1472
|
+
if (ext === ".html") {
|
|
1473
|
+
res.setHeader("Cache-Control", "no-cache");
|
|
1474
|
+
}
|
|
1475
|
+
const fileContent = await fs2.readFile(filePath);
|
|
1476
|
+
res.writeHead(200);
|
|
1477
|
+
res.end(fileContent);
|
|
1478
|
+
} catch (err) {
|
|
1479
|
+
if (err.code === "ENOENT") {
|
|
1480
|
+
try {
|
|
1481
|
+
const fileContent = await fs2.readFile(path.join(DIST_DIR, "index.html"));
|
|
1482
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
1483
|
+
res.end(fileContent);
|
|
1484
|
+
} catch {
|
|
1485
|
+
res.writeHead(404);
|
|
1486
|
+
res.end("Not found");
|
|
1487
|
+
}
|
|
1488
|
+
} else {
|
|
1489
|
+
res.writeHead(500);
|
|
1490
|
+
res.end("Server error");
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
});
|
|
1494
|
+
httpServer.listen(httpPort, wsHost2, () => {
|
|
1495
|
+
console.log(`[WebUI] HTTP server running on http://${wsHost2}:${httpPort}`);
|
|
1496
|
+
});
|
|
1422
1497
|
const shutdown = async () => {
|
|
1423
1498
|
console.log("[WebUI] Shutting down...");
|
|
1424
1499
|
try {
|
|
@@ -1432,6 +1507,7 @@ async function startWebUI(opts = {}) {
|
|
|
1432
1507
|
console.warn("[WebUI] Error closing session:", e);
|
|
1433
1508
|
}
|
|
1434
1509
|
for (const [ws] of clients) ws.close();
|
|
1510
|
+
httpServer.close();
|
|
1435
1511
|
wssPrimary.close();
|
|
1436
1512
|
wssSecondary?.close();
|
|
1437
1513
|
process.exit(0);
|