@wrongstack/webui 0.5.7 → 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/assets/index-CFyVAbSB.js +94 -0
- package/dist/index.html +1 -1
- package/dist/index.js +89 -87
- package/dist/index.js.map +1 -1
- package/dist/server/entry.js +118 -20
- package/dist/server/entry.js.map +1 -1
- package/dist/server/index.js +118 -20
- package/dist/server/index.js.map +1 -1
- package/package.json +5 -5
- package/dist/assets/index-3Lo5wUfj.js +0 -94
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,
|
|
@@ -24,6 +25,7 @@ import {
|
|
|
24
25
|
repairToolUseAdjacency,
|
|
25
26
|
resolveContextWindowPolicy
|
|
26
27
|
} from "@wrongstack/core";
|
|
28
|
+
import { ToolExecutor } from "@wrongstack/core/execution";
|
|
27
29
|
import { decryptConfigSecrets, encryptConfigSecrets } from "@wrongstack/core/security";
|
|
28
30
|
import { buildProviderFactoriesFromRegistry, makeProviderFromConfig } from "@wrongstack/providers";
|
|
29
31
|
import { builtinToolsPack, forgetTool, rememberTool } from "@wrongstack/tools";
|
|
@@ -83,7 +85,13 @@ async function startWebUI(opts = {}) {
|
|
|
83
85
|
const { config: baseConfig, vault, globalConfigPath, projectRoot, wpaths, logger } = boot;
|
|
84
86
|
let config = baseConfig;
|
|
85
87
|
let configWriteLock = Promise.resolve();
|
|
86
|
-
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;
|
|
87
95
|
const modelsRegistry = new DefaultModelsRegistry({
|
|
88
96
|
cacheFile: wpaths.modelsCache,
|
|
89
97
|
ttlSeconds: 24 * 3600
|
|
@@ -151,22 +159,46 @@ async function startWebUI(opts = {}) {
|
|
|
151
159
|
provider: config.provider,
|
|
152
160
|
model: config.model
|
|
153
161
|
});
|
|
154
|
-
const providerConfig = config.providers?.[config.provider] ?? {
|
|
155
|
-
type: config.provider,
|
|
156
|
-
apiKey: config.apiKey,
|
|
157
|
-
baseUrl: config.baseUrl
|
|
158
|
-
};
|
|
159
162
|
let provider;
|
|
160
|
-
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
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
|
+
}
|
|
164
197
|
} else {
|
|
165
|
-
|
|
198
|
+
throw new Error(
|
|
199
|
+
"No provider configured. Run `wrongstack init` first, or configure via the WebUI."
|
|
200
|
+
);
|
|
166
201
|
}
|
|
167
|
-
} catch (err) {
|
|
168
|
-
console.error("[WebUI] Failed to create provider:", err);
|
|
169
|
-
throw err;
|
|
170
202
|
}
|
|
171
203
|
const context = new Context({
|
|
172
204
|
systemPrompt,
|
|
@@ -228,6 +260,18 @@ async function startWebUI(opts = {}) {
|
|
|
228
260
|
}
|
|
229
261
|
autoCompactor.setMaxContext(newMaxContext);
|
|
230
262
|
}
|
|
263
|
+
const secretScrubber = container.resolve(TOKENS.SecretScrubber);
|
|
264
|
+
const renderer = container.has(TOKENS.Renderer) ? container.resolve(TOKENS.Renderer) : void 0;
|
|
265
|
+
const toolExecutor = new ToolExecutor(toolRegistry, {
|
|
266
|
+
permissionPolicy: container.resolve(TOKENS.PermissionPolicy),
|
|
267
|
+
secretScrubber,
|
|
268
|
+
renderer,
|
|
269
|
+
events,
|
|
270
|
+
confirmAwaiter: void 0,
|
|
271
|
+
iterationTimeoutMs: config.tools?.iterationTimeoutMs ?? 12e4,
|
|
272
|
+
perIterationOutputCapBytes: config.tools?.perIterationOutputCapBytes ?? 5e4,
|
|
273
|
+
tracer: void 0
|
|
274
|
+
});
|
|
231
275
|
const agent = new Agent({
|
|
232
276
|
container,
|
|
233
277
|
tools: toolRegistry,
|
|
@@ -239,7 +283,8 @@ async function startWebUI(opts = {}) {
|
|
|
239
283
|
iterationTimeoutMs: config.tools?.iterationTimeoutMs ?? 12e4,
|
|
240
284
|
executionStrategy: config.tools?.defaultExecutionStrategy ?? "sequential",
|
|
241
285
|
perIterationOutputCapBytes: config.tools?.perIterationOutputCapBytes ?? 5e4,
|
|
242
|
-
confirmAwaiter: void 0
|
|
286
|
+
confirmAwaiter: void 0,
|
|
287
|
+
toolExecutor
|
|
243
288
|
});
|
|
244
289
|
console.log("[WebUI] Agent initialized");
|
|
245
290
|
async function sessionStartPayload() {
|
|
@@ -458,8 +503,8 @@ async function startWebUI(opts = {}) {
|
|
|
458
503
|
rateLimits.delete(ws);
|
|
459
504
|
console.log("[WebUI] Client disconnected, total:", clients.size);
|
|
460
505
|
if (pendingConfirms.size > 0) {
|
|
461
|
-
for (const [id,
|
|
462
|
-
|
|
506
|
+
for (const [id, resolve2] of pendingConfirms) {
|
|
507
|
+
resolve2("no");
|
|
463
508
|
pendingConfirms.delete(id);
|
|
464
509
|
}
|
|
465
510
|
}
|
|
@@ -539,10 +584,10 @@ async function startWebUI(opts = {}) {
|
|
|
539
584
|
}
|
|
540
585
|
case "tool.confirm_result": {
|
|
541
586
|
const { id, decision } = msg.payload;
|
|
542
|
-
const
|
|
543
|
-
if (
|
|
587
|
+
const resolve2 = pendingConfirms.get(id);
|
|
588
|
+
if (resolve2) {
|
|
544
589
|
pendingConfirms.delete(id);
|
|
545
|
-
|
|
590
|
+
resolve2(decision);
|
|
546
591
|
}
|
|
547
592
|
break;
|
|
548
593
|
}
|
|
@@ -1404,6 +1449,58 @@ async function startWebUI(opts = {}) {
|
|
|
1404
1449
|
sendResult(ws, false, err instanceof Error ? err.message : String(err));
|
|
1405
1450
|
}
|
|
1406
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
|
+
});
|
|
1407
1504
|
const shutdown = async () => {
|
|
1408
1505
|
console.log("[WebUI] Shutting down...");
|
|
1409
1506
|
try {
|
|
@@ -1417,6 +1514,7 @@ async function startWebUI(opts = {}) {
|
|
|
1417
1514
|
console.warn("[WebUI] Error closing session:", e);
|
|
1418
1515
|
}
|
|
1419
1516
|
for (const [ws] of clients) ws.close();
|
|
1517
|
+
httpServer.close();
|
|
1420
1518
|
wssPrimary.close();
|
|
1421
1519
|
wssSecondary?.close();
|
|
1422
1520
|
process.exit(0);
|