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