@oharness/server 0.1.0 → 0.2.0
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/README.md +23 -0
- package/dist/i18n.js +170 -4
- package/dist/i18n.js.map +1 -1
- package/dist/page.js +961 -52
- package/dist/page.js.map +1 -1
- package/dist/server.js +206 -20
- package/dist/server.js.map +1 -1
- package/package.json +2 -2
package/dist/page.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page.js","sourceRoot":"","sources":["../src/page.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7C;;;;;;;;;;;;;;GAcG;AAEH,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAw5CvB,CAAC;AAEF,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgrN5B,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,OAAO,GAAG;;;;;yCAKyB,CAAC;AAE1C,MAAM,CAAC,MAAM,IAAI,GAAG;;;;;;;4CAOwB,kBAAkB,CAAC,OAAO,CAAC;SAC9D,KAAK;EACZ,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAmRK,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;qBACvB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;EAC1C,aAAa;EACb,UAAU;EACV,gBAAgB;;;QAGV,CAAC"}
|
|
1
|
+
{"version":3,"file":"page.js","sourceRoot":"","sources":["../src/page.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7C;;;;;;;;;;;;;;GAcG;AAEH,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwkDvB,CAAC;AAEF,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA64O5B,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,OAAO,GAAG;;;;;yCAKyB,CAAC;AAE1C,MAAM,CAAC,MAAM,IAAI,GAAG;;;;;;;4CAOwB,kBAAkB,CAAC,OAAO,CAAC;SAC9D,KAAK;EACZ,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAmRK,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;qBACvB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;EAC1C,aAAa;EACb,UAAU;EACV,gBAAgB;;;QAGV,CAAC"}
|
package/dist/server.js
CHANGED
|
@@ -4,7 +4,7 @@ import { readFile, stat } from "node:fs/promises";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { homedir } from "node:os";
|
|
6
6
|
import { Harness } from "@oharness/engine/harness.ts";
|
|
7
|
-
import {
|
|
7
|
+
import { updateUserMcpConfig } from "@oharness/engine/config-files.ts";
|
|
8
8
|
import { connectorConfig, officialConnectors } from "@oharness/engine/mcp/registry.ts";
|
|
9
9
|
import { missingSecrets } from "@oharness/engine/mcp/secrets.ts";
|
|
10
10
|
import { connectorIcon } from "./icons.js";
|
|
@@ -13,7 +13,7 @@ import { isReadable } from "@oharness/engine/agent/workspace.ts";
|
|
|
13
13
|
import { messageText } from "@oharness/engine/core/types.ts";
|
|
14
14
|
import { errorMessage } from "@oharness/engine/core/errors.ts";
|
|
15
15
|
import { officialBaseUrl } from "@oharness/engine/auth/providers/official.ts";
|
|
16
|
-
import { browserSignInUrl, exchangeHandoff, siteUrl } from "@oharness/engine/auth/providers/account.ts";
|
|
16
|
+
import { accountsConfigured, browserKeyUrl, browserSignInUrl, exchangeHandoff, siteUrl, } from "@oharness/engine/auth/providers/account.ts";
|
|
17
17
|
import { ChangeLedger } from "./changes.js";
|
|
18
18
|
import { addProject, ensureProject, listProjects, removeProject } from "./projects.js";
|
|
19
19
|
import { readPrefs, writePrefs } from "./prefs.js";
|
|
@@ -259,6 +259,13 @@ export async function startWebServer(opts) {
|
|
|
259
259
|
for (const client of clients)
|
|
260
260
|
client.write(payload);
|
|
261
261
|
};
|
|
262
|
+
const connectionSubscriptions = [];
|
|
263
|
+
function watchConnections(harness) {
|
|
264
|
+
connectionSubscriptions.push(harness.cloudConnectors.subscribe((card) => {
|
|
265
|
+
broadcast({ type: "connection_card", session: card.session, card });
|
|
266
|
+
}));
|
|
267
|
+
}
|
|
268
|
+
watchConnections(opts.harness);
|
|
262
269
|
const permissionPrompt = (request) => new Promise((resolve) => {
|
|
263
270
|
const id = randomUUID();
|
|
264
271
|
pending.set(id, { id, request, resolve });
|
|
@@ -303,6 +310,58 @@ export async function startWebServer(opts) {
|
|
|
303
310
|
if (!authorized(url, req))
|
|
304
311
|
return send(res, 401, { error: "missing or bad token" });
|
|
305
312
|
switch (`${req.method} ${url.pathname}`) {
|
|
313
|
+
case "GET /plugin-pages": {
|
|
314
|
+
const runner = runnerFor(url.searchParams.get("session"));
|
|
315
|
+
return send(res, 200, { pages: runner?.harness.extensions.listPages() ?? [] });
|
|
316
|
+
}
|
|
317
|
+
case "GET /plugin-page": {
|
|
318
|
+
res.setHeader("cache-control", "no-store");
|
|
319
|
+
const runner = runnerFor(url.searchParams.get("session"));
|
|
320
|
+
const page = runner?.harness.extensions.page(url.searchParams.get("id") ?? "");
|
|
321
|
+
if (!page)
|
|
322
|
+
return send(res, 404, { error: "插件页面未启用。" });
|
|
323
|
+
try {
|
|
324
|
+
return send(res, 200, await page.read());
|
|
325
|
+
}
|
|
326
|
+
catch {
|
|
327
|
+
return send(res, 400, { error: "无法读取插件页面,请检查本地文件。" });
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
case "POST /plugin-page": {
|
|
331
|
+
res.setHeader("cache-control", "no-store");
|
|
332
|
+
const body = await readJson(req);
|
|
333
|
+
const runner = runnerFor(body.session);
|
|
334
|
+
const page = runner?.harness.extensions.page(typeof body.page === "string" ? body.page : "");
|
|
335
|
+
if (!page || !body.input || typeof body.input !== "object" || Array.isArray(body.input))
|
|
336
|
+
return send(res, 400, { error: "无效插件页面操作。" });
|
|
337
|
+
try {
|
|
338
|
+
return send(res, 200, await page.act(body.input));
|
|
339
|
+
}
|
|
340
|
+
catch (error) {
|
|
341
|
+
return send(res, 400, { error: errorMessage(error) });
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
case "POST /cloud-connection": {
|
|
345
|
+
res.setHeader("cache-control", "no-store");
|
|
346
|
+
const body = await readJson(req);
|
|
347
|
+
const id = typeof body.id === "string" ? body.id : "";
|
|
348
|
+
const harness = [...harnesses.values()].find((h) => h.cloudConnectors.snapshots().some((c) => c.id === id));
|
|
349
|
+
if (!harness)
|
|
350
|
+
return send(res, 404, { error: "连接请求不存在或已过期。" });
|
|
351
|
+
if (body.action === "cancel") {
|
|
352
|
+
harness.cloudConnectors.cancel(id);
|
|
353
|
+
return send(res, 200, { cancelled: true });
|
|
354
|
+
}
|
|
355
|
+
if (body.action !== "start")
|
|
356
|
+
return send(res, 400, { error: "未知连接操作。" });
|
|
357
|
+
try {
|
|
358
|
+
const redirectUrl = await harness.cloudConnectors.start(id);
|
|
359
|
+
return send(res, 200, { redirectUrl, connected: !redirectUrl });
|
|
360
|
+
}
|
|
361
|
+
catch {
|
|
362
|
+
return send(res, 400, { error: "无法创建授权链接,请检查 Cloud 连接配置。" });
|
|
363
|
+
}
|
|
364
|
+
}
|
|
306
365
|
case "GET /events":
|
|
307
366
|
return stream(res);
|
|
308
367
|
case "GET /state": {
|
|
@@ -762,10 +821,9 @@ export async function startWebServer(opts) {
|
|
|
762
821
|
return send(res, 400, { error: "id is required" });
|
|
763
822
|
if (body.remove === true) {
|
|
764
823
|
await current.harness.removeMcpServer(id);
|
|
765
|
-
await
|
|
766
|
-
const servers = { ...config.mcpServers };
|
|
824
|
+
await updateUserMcpConfig((servers) => {
|
|
767
825
|
delete servers[id];
|
|
768
|
-
return
|
|
826
|
+
return servers;
|
|
769
827
|
});
|
|
770
828
|
return send(res, 200, { removed: id, ...contextOffer() });
|
|
771
829
|
}
|
|
@@ -790,10 +848,7 @@ export async function startWebServer(opts) {
|
|
|
790
848
|
await current.harness.removeMcpServer(id);
|
|
791
849
|
return send(res, 400, { error: status.error ?? `${id} did not start` });
|
|
792
850
|
}
|
|
793
|
-
await
|
|
794
|
-
...existing,
|
|
795
|
-
mcpServers: { ...existing.mcpServers, [id]: config },
|
|
796
|
-
}));
|
|
851
|
+
await updateUserMcpConfig((existing) => ({ ...existing, [id]: config }));
|
|
797
852
|
return send(res, 200, { status, ...contextOffer() });
|
|
798
853
|
}
|
|
799
854
|
catch (err) {
|
|
@@ -1108,9 +1163,18 @@ export async function startWebServer(opts) {
|
|
|
1108
1163
|
if (!token)
|
|
1109
1164
|
return send(res, 400, { error: "sign in first" });
|
|
1110
1165
|
const locale = typeof body.locale === "string" ? body.locale : undefined;
|
|
1166
|
+
// A top-up is the one plan sold at an amount the buyer picks. The
|
|
1167
|
+
// gateway has always taken it and this hop dropped it, which is why
|
|
1168
|
+
// the ladder in the catalogue could only ever be bought at its bottom
|
|
1169
|
+
// rung. Passed through rather than checked here: the bounds are the
|
|
1170
|
+
// catalogue's, and a second copy of them in front of it is a second
|
|
1171
|
+
// place to be wrong about what is for sale.
|
|
1172
|
+
const amount = typeof body.amount === "number" && Number.isFinite(body.amount) && body.amount > 0
|
|
1173
|
+
? Math.round(body.amount)
|
|
1174
|
+
: undefined;
|
|
1111
1175
|
const result = await gatewayJson("/api/v1/billing/checkout", {
|
|
1112
1176
|
token,
|
|
1113
|
-
body: { plan, ...(locale ? { locale } : {}) },
|
|
1177
|
+
body: { plan, ...(locale ? { locale } : {}), ...(amount ? { amountCents: amount } : {}) },
|
|
1114
1178
|
});
|
|
1115
1179
|
if (!result.ok)
|
|
1116
1180
|
return send(res, 400, { error: result.error });
|
|
@@ -1381,18 +1445,85 @@ export async function startWebServer(opts) {
|
|
|
1381
1445
|
// environment variable from a stored key; the panel could not, so a
|
|
1382
1446
|
// provider connected purely by env looked the same as an unconnected
|
|
1383
1447
|
// one with a stale entry.
|
|
1384
|
-
const
|
|
1385
|
-
|
|
1386
|
-
//
|
|
1387
|
-
//
|
|
1448
|
+
const status = await current.harness.authStatus();
|
|
1449
|
+
const sources = new Map(status.map((entry) => [entry.providerId, entry.source]));
|
|
1450
|
+
// Why a renewal failed, when one did. An expired access token is not
|
|
1451
|
+
// news — they last an hour and are renewed on the way into a request —
|
|
1452
|
+
// so what separates a dead session from a live one is whether the
|
|
1453
|
+
// renewal could happen, not whether the token ran out.
|
|
1454
|
+
const renewFailures = new Map(status.flatMap((entry) => entry.refreshError ? [[entry.providerId, entry.refreshError]] : []));
|
|
1455
|
+
// One pass over the stored credentials, for the two things the panel
|
|
1456
|
+
// asks of them: whose account this is, and whether the session behind
|
|
1457
|
+
// it can still be renewed. Separate loops read as separate concerns
|
|
1458
|
+
// and were the same await twice.
|
|
1459
|
+
//
|
|
1460
|
+
// "Connected" answers whether a credential exists; on an account-backed
|
|
1461
|
+
// plan the useful question is *whose*, which is the one thing a stale
|
|
1462
|
+
// login gets wrong.
|
|
1388
1463
|
const accounts = new Map();
|
|
1464
|
+
const keyLabels = new Map();
|
|
1465
|
+
const renewable = new Map();
|
|
1466
|
+
const hadCredential = new Set();
|
|
1389
1467
|
for (const provider of current.harness.auth.list()) {
|
|
1390
1468
|
const credential = await current.harness.auth.store.get(provider.id);
|
|
1391
|
-
|
|
1469
|
+
if (!credential)
|
|
1470
|
+
continue;
|
|
1471
|
+
hadCredential.add(provider.id);
|
|
1472
|
+
if (credential.type === "api") {
|
|
1473
|
+
// The head of the key and what it was called. Never the key: the
|
|
1474
|
+
// point of showing anything is so somebody can find this one in
|
|
1475
|
+
// the list on the site and revoke it, and the list has only these.
|
|
1476
|
+
const meta = credential.metadata ?? {};
|
|
1477
|
+
const label = [meta["name"], meta["prefix"]].filter(Boolean).join(" · ");
|
|
1478
|
+
if (label)
|
|
1479
|
+
keyLabels.set(provider.id, label);
|
|
1480
|
+
continue;
|
|
1481
|
+
}
|
|
1482
|
+
if (credential.type !== "oauth")
|
|
1483
|
+
continue;
|
|
1484
|
+
renewable.set(provider.id, Boolean(credential.refresh));
|
|
1485
|
+
const email = accountEmail(credential.access);
|
|
1392
1486
|
if (email)
|
|
1393
1487
|
accounts.set(provider.id, email);
|
|
1394
1488
|
}
|
|
1489
|
+
/**
|
|
1490
|
+
* Why a provider is not ready, when it is not.
|
|
1491
|
+
*
|
|
1492
|
+
* `configured` is one boolean over five situations and most of them
|
|
1493
|
+
* want different sentences. Collapsing them is how a build with no
|
|
1494
|
+
* account project produced a sign-in dialog whose button could not
|
|
1495
|
+
* possibly work — the same dialog offered to somebody who has simply
|
|
1496
|
+
* never signed in.
|
|
1497
|
+
*
|
|
1498
|
+
* Undefined means ready, or means "never signed in", which the plain
|
|
1499
|
+
* sign-in already answers correctly.
|
|
1500
|
+
*/
|
|
1501
|
+
const readiness = (id) => {
|
|
1502
|
+
if (configured.has(id))
|
|
1503
|
+
return undefined;
|
|
1504
|
+
// Only the account-backed plans can be missing an account project;
|
|
1505
|
+
// for a vendor whose credential is a pasted key the question does
|
|
1506
|
+
// not arise. Checked first because it explains every other symptom
|
|
1507
|
+
// on such a build, including a renewal that never had anywhere to go.
|
|
1508
|
+
if (signInMethod(id) && !accountsConfigured())
|
|
1509
|
+
return "no-account-system";
|
|
1510
|
+
// A renewal was attempted and failed. Distinct from expiry, and the
|
|
1511
|
+
// distinction is the point of this function: an access token lasts
|
|
1512
|
+
// an hour and is renewed on the way into every request, so running
|
|
1513
|
+
// out is the normal state and never worth reporting. What is worth
|
|
1514
|
+
// reporting is a renewal that could not happen — and if the account
|
|
1515
|
+
// system was merely unreachable, telling someone their login expired
|
|
1516
|
+
// sends them to sign in again over something that was never theirs.
|
|
1517
|
+
if (renewFailures.has(id))
|
|
1518
|
+
return "cannot-renew";
|
|
1519
|
+
// Nothing left to renew with. This is the one that really does mean
|
|
1520
|
+
// sign in again.
|
|
1521
|
+
return hadCredential.has(id) && renewable.get(id) === false ? "expired" : undefined;
|
|
1522
|
+
};
|
|
1395
1523
|
return send(res, 200, {
|
|
1524
|
+
// Where to go for a key. Has a default even on a build that knows no
|
|
1525
|
+
// account project, which is exactly the build that needs the link.
|
|
1526
|
+
site: siteUrl(),
|
|
1396
1527
|
models: current.harness.listModels().map((model) => ({
|
|
1397
1528
|
id: model.id,
|
|
1398
1529
|
provider: model.provider,
|
|
@@ -1413,7 +1544,20 @@ export async function startWebServer(opts) {
|
|
|
1413
1544
|
description: entry.description,
|
|
1414
1545
|
source: sources.get(entry.id),
|
|
1415
1546
|
account: accounts.get(entry.id),
|
|
1547
|
+
// Which key this machine holds, when it holds one rather than a
|
|
1548
|
+
// session. Enough to recognise it on the site and revoke it.
|
|
1549
|
+
keyLabel: keyLabels.get(entry.id),
|
|
1416
1550
|
configured: configured.has(entry.id),
|
|
1551
|
+
// Absent when there is nothing to explain. Present, it names which
|
|
1552
|
+
// of the unusable states this is, so the panel can say something
|
|
1553
|
+
// true instead of offering the one action that cannot help.
|
|
1554
|
+
...(readiness(entry.id) ? { readiness: readiness(entry.id) } : {}),
|
|
1555
|
+
// Only for cannot-renew. The other states have a sentence written
|
|
1556
|
+
// for them; a build with no account project would otherwise carry
|
|
1557
|
+
// the engine's own wording of the same fact, twice on one card.
|
|
1558
|
+
...(readiness(entry.id) === "cannot-renew"
|
|
1559
|
+
? { readinessDetail: renewFailures.get(entry.id) }
|
|
1560
|
+
: {}),
|
|
1417
1561
|
// Which vendors can be signed into from here rather than pasted a
|
|
1418
1562
|
// key into. The panel has no other way to tell, and offering a key
|
|
1419
1563
|
// field for an account-backed plan is a dead end.
|
|
@@ -1519,13 +1663,31 @@ export async function startWebServer(opts) {
|
|
|
1519
1663
|
fallback: "code",
|
|
1520
1664
|
});
|
|
1521
1665
|
}
|
|
1666
|
+
// Two errands down one road. A key is minted on the site's own key
|
|
1667
|
+
// page, which already lists, creates and revokes them — so the app
|
|
1668
|
+
// sends the person there and takes back whatever they made, rather
|
|
1669
|
+
// than growing a second place that mints credentials.
|
|
1670
|
+
const wantsKey = body.intent === "key";
|
|
1522
1671
|
const state = randomUUID() + randomUUID();
|
|
1523
|
-
pendingBrowserSignIns.set(state, {
|
|
1672
|
+
pendingBrowserSignIns.set(state, {
|
|
1673
|
+
provider: providerId,
|
|
1674
|
+
started: Date.now(),
|
|
1675
|
+
...(wantsKey ? { intent: "key" } : {}),
|
|
1676
|
+
});
|
|
1524
1677
|
setTimeout(() => pendingBrowserSignIns.delete(state), BROWSER_SIGNIN_TTL_MS).unref?.();
|
|
1525
1678
|
const origin = `http://${host}`;
|
|
1526
1679
|
const locale = typeof body.locale === "string" ? body.locale : undefined;
|
|
1680
|
+
// A top-up is the one plan sold at an amount the buyer picks. The
|
|
1681
|
+
// gateway has always taken it and this hop dropped it, which is why
|
|
1682
|
+
// the ladder in the catalogue could only ever be bought at its bottom
|
|
1683
|
+
// rung. Passed through rather than checked here: the bounds are the
|
|
1684
|
+
// catalogue's, and a second copy of them in front of it is a second
|
|
1685
|
+
// place to be wrong about what is for sale.
|
|
1686
|
+
const amount = typeof body.amount === "number" && Number.isFinite(body.amount) && body.amount > 0
|
|
1687
|
+
? Math.round(body.amount)
|
|
1688
|
+
: undefined;
|
|
1527
1689
|
return send(res, 200, {
|
|
1528
|
-
url: browserSignInUrl({
|
|
1690
|
+
url: (wantsKey ? browserKeyUrl : browserSignInUrl)({
|
|
1529
1691
|
state,
|
|
1530
1692
|
redirectUri: `${origin}/signin/handoff`,
|
|
1531
1693
|
...(locale ? { locale } : {}),
|
|
@@ -1861,7 +2023,10 @@ export async function startWebServer(opts) {
|
|
|
1861
2023
|
const result = await exchangeHandoff(code, state);
|
|
1862
2024
|
if (result.type !== "success") {
|
|
1863
2025
|
const message = result.error ?? "that sign-in was not accepted";
|
|
1864
|
-
broadcast({
|
|
2026
|
+
broadcast({
|
|
2027
|
+
type: "notice",
|
|
2028
|
+
message: `${pending.intent === "key" ? "getting a key" : "sign-in"} failed: ${message}`,
|
|
2029
|
+
});
|
|
1865
2030
|
return closeTab(res, 400, message);
|
|
1866
2031
|
}
|
|
1867
2032
|
try {
|
|
@@ -1870,7 +2035,12 @@ export async function startWebServer(opts) {
|
|
|
1870
2035
|
catch (err) {
|
|
1871
2036
|
return closeTab(res, 500, errorMessage(err));
|
|
1872
2037
|
}
|
|
1873
|
-
|
|
2038
|
+
// What happened, in the words of the errand that was run. "Signed in" on
|
|
2039
|
+
// a tab where somebody just created an API key is a small lie that makes
|
|
2040
|
+
// them wonder which of the two actually took.
|
|
2041
|
+
closeTab(res, 200, pending.intent === "key"
|
|
2042
|
+
? `That key is now in use for ${pending.provider}. You can close this tab.`
|
|
2043
|
+
: `Signed in to ${pending.provider}.`);
|
|
1874
2044
|
// Same as a saved key: the credential is stored, now go ask the gateway
|
|
1875
2045
|
// what the account can actually call.
|
|
1876
2046
|
void current.harness
|
|
@@ -1925,7 +2095,13 @@ export async function startWebServer(opts) {
|
|
|
1925
2095
|
servers: Object.keys(plugin.mcpServers ?? {}),
|
|
1926
2096
|
subagents: plugin.subagents?.length ?? 0,
|
|
1927
2097
|
}));
|
|
1928
|
-
|
|
2098
|
+
const runtime = (harness.runtimePluginStatus?.() ?? []).map((plugin) => ({
|
|
2099
|
+
name: plugin.id,
|
|
2100
|
+
description: `${plugin.description ?? "Runtime plugin"} [${plugin.state}]${plugin.error ? ` — ${plugin.error}` : ""}`,
|
|
2101
|
+
source: "runtime", servers: [], subagents: 0,
|
|
2102
|
+
state: plugin.state, error: plugin.error,
|
|
2103
|
+
}));
|
|
2104
|
+
return { connectors, plugins: [...plugins, ...runtime] };
|
|
1929
2105
|
}
|
|
1930
2106
|
/**
|
|
1931
2107
|
* What the composer attached to one message, as a block above the prompt.
|
|
@@ -2080,6 +2256,7 @@ export async function startWebServer(opts) {
|
|
|
2080
2256
|
permissionPrompt: (request) => permissionPrompt(request),
|
|
2081
2257
|
}));
|
|
2082
2258
|
harnesses.set(project.path, harness);
|
|
2259
|
+
watchConnections(harness);
|
|
2083
2260
|
return harness;
|
|
2084
2261
|
}
|
|
2085
2262
|
/**
|
|
@@ -2234,6 +2411,11 @@ export async function startWebServer(opts) {
|
|
|
2234
2411
|
});
|
|
2235
2412
|
res.write(": connected\n\n");
|
|
2236
2413
|
clients.add(res);
|
|
2414
|
+
for (const harness of harnesses.values()) {
|
|
2415
|
+
for (const card of harness.cloudConnectors.snapshots()) {
|
|
2416
|
+
res.write(`data: ${JSON.stringify({ type: "connection_card", session: card.session, card })}\n\n`);
|
|
2417
|
+
}
|
|
2418
|
+
}
|
|
2237
2419
|
// A heartbeat keeps intermediaries from closing an idle stream while the
|
|
2238
2420
|
// model is thinking.
|
|
2239
2421
|
const beat = setInterval(() => res.write(": ping\n\n"), 15_000);
|
|
@@ -2402,6 +2584,10 @@ export async function startWebServer(opts) {
|
|
|
2402
2584
|
token,
|
|
2403
2585
|
permissionPrompt,
|
|
2404
2586
|
async close() {
|
|
2587
|
+
for (const unsubscribe of connectionSubscriptions)
|
|
2588
|
+
unsubscribe();
|
|
2589
|
+
for (const harness of harnesses.values())
|
|
2590
|
+
harness.cloudConnectors.close();
|
|
2405
2591
|
for (const client of clients)
|
|
2406
2592
|
client.end();
|
|
2407
2593
|
clients.clear();
|