@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/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,
|
|
@@ -25,6 +26,7 @@ import {
|
|
|
25
26
|
repairToolUseAdjacency,
|
|
26
27
|
resolveContextWindowPolicy
|
|
27
28
|
} from "@wrongstack/core";
|
|
29
|
+
import { ToolExecutor } from "@wrongstack/core/execution";
|
|
28
30
|
import { decryptConfigSecrets, encryptConfigSecrets } from "@wrongstack/core/security";
|
|
29
31
|
import { buildProviderFactoriesFromRegistry, makeProviderFromConfig } from "@wrongstack/providers";
|
|
30
32
|
import { builtinToolsPack, forgetTool, rememberTool } from "@wrongstack/tools";
|
|
@@ -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,
|
|
@@ -229,6 +261,18 @@ async function startWebUI(opts = {}) {
|
|
|
229
261
|
}
|
|
230
262
|
autoCompactor.setMaxContext(newMaxContext);
|
|
231
263
|
}
|
|
264
|
+
const secretScrubber = container.resolve(TOKENS.SecretScrubber);
|
|
265
|
+
const renderer = container.has(TOKENS.Renderer) ? container.resolve(TOKENS.Renderer) : void 0;
|
|
266
|
+
const toolExecutor = new ToolExecutor(toolRegistry, {
|
|
267
|
+
permissionPolicy: container.resolve(TOKENS.PermissionPolicy),
|
|
268
|
+
secretScrubber,
|
|
269
|
+
renderer,
|
|
270
|
+
events,
|
|
271
|
+
confirmAwaiter: void 0,
|
|
272
|
+
iterationTimeoutMs: config.tools?.iterationTimeoutMs ?? 12e4,
|
|
273
|
+
perIterationOutputCapBytes: config.tools?.perIterationOutputCapBytes ?? 5e4,
|
|
274
|
+
tracer: void 0
|
|
275
|
+
});
|
|
232
276
|
const agent = new Agent({
|
|
233
277
|
container,
|
|
234
278
|
tools: toolRegistry,
|
|
@@ -240,7 +284,8 @@ async function startWebUI(opts = {}) {
|
|
|
240
284
|
iterationTimeoutMs: config.tools?.iterationTimeoutMs ?? 12e4,
|
|
241
285
|
executionStrategy: config.tools?.defaultExecutionStrategy ?? "sequential",
|
|
242
286
|
perIterationOutputCapBytes: config.tools?.perIterationOutputCapBytes ?? 5e4,
|
|
243
|
-
confirmAwaiter: void 0
|
|
287
|
+
confirmAwaiter: void 0,
|
|
288
|
+
toolExecutor
|
|
244
289
|
});
|
|
245
290
|
console.log("[WebUI] Agent initialized");
|
|
246
291
|
async function sessionStartPayload() {
|
|
@@ -459,8 +504,8 @@ async function startWebUI(opts = {}) {
|
|
|
459
504
|
rateLimits.delete(ws);
|
|
460
505
|
console.log("[WebUI] Client disconnected, total:", clients.size);
|
|
461
506
|
if (pendingConfirms.size > 0) {
|
|
462
|
-
for (const [id,
|
|
463
|
-
|
|
507
|
+
for (const [id, resolve2] of pendingConfirms) {
|
|
508
|
+
resolve2("no");
|
|
464
509
|
pendingConfirms.delete(id);
|
|
465
510
|
}
|
|
466
511
|
}
|
|
@@ -540,10 +585,10 @@ async function startWebUI(opts = {}) {
|
|
|
540
585
|
}
|
|
541
586
|
case "tool.confirm_result": {
|
|
542
587
|
const { id, decision } = msg.payload;
|
|
543
|
-
const
|
|
544
|
-
if (
|
|
588
|
+
const resolve2 = pendingConfirms.get(id);
|
|
589
|
+
if (resolve2) {
|
|
545
590
|
pendingConfirms.delete(id);
|
|
546
|
-
|
|
591
|
+
resolve2(decision);
|
|
547
592
|
}
|
|
548
593
|
break;
|
|
549
594
|
}
|
|
@@ -1405,6 +1450,58 @@ async function startWebUI(opts = {}) {
|
|
|
1405
1450
|
sendResult(ws, false, err instanceof Error ? err.message : String(err));
|
|
1406
1451
|
}
|
|
1407
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
|
+
});
|
|
1408
1505
|
const shutdown = async () => {
|
|
1409
1506
|
console.log("[WebUI] Shutting down...");
|
|
1410
1507
|
try {
|
|
@@ -1418,6 +1515,7 @@ async function startWebUI(opts = {}) {
|
|
|
1418
1515
|
console.warn("[WebUI] Error closing session:", e);
|
|
1419
1516
|
}
|
|
1420
1517
|
for (const [ws] of clients) ws.close();
|
|
1518
|
+
httpServer.close();
|
|
1421
1519
|
wssPrimary.close();
|
|
1422
1520
|
wssSecondary?.close();
|
|
1423
1521
|
process.exit(0);
|