@rubytech/create-maxy-code 0.1.312 → 0.1.313
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/package.json +1 -1
- package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -0
- package/payload/platform/plugins/admin/hooks/lib/maxy-mcp-plugins.txt +1 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +37 -3
- package/payload/platform/plugins/docs/references/admin-ui.md +2 -2
- package/payload/platform/plugins/docs/references/quickbooks.md +29 -0
- package/payload/platform/plugins/quickbooks/.claude-plugin/plugin.json +21 -0
- package/payload/platform/plugins/quickbooks/PLUGIN.md +91 -0
- package/payload/platform/plugins/quickbooks/lib/mcp-spawn-tee/index.js +159 -0
- package/payload/platform/plugins/quickbooks/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/plugins/quickbooks/mcp/dist/index.d.ts +2 -0
- package/payload/platform/plugins/quickbooks/mcp/dist/index.d.ts.map +1 -0
- package/payload/platform/plugins/quickbooks/mcp/dist/index.js +218 -0
- package/payload/platform/plugins/quickbooks/mcp/dist/index.js.map +1 -0
- package/payload/platform/plugins/quickbooks/mcp/dist/lib/oauth.d.ts +37 -0
- package/payload/platform/plugins/quickbooks/mcp/dist/lib/oauth.d.ts.map +1 -0
- package/payload/platform/plugins/quickbooks/mcp/dist/lib/oauth.js +75 -0
- package/payload/platform/plugins/quickbooks/mcp/dist/lib/oauth.js.map +1 -0
- package/payload/platform/plugins/quickbooks/mcp/dist/lib/qbo-client.d.ts +39 -0
- package/payload/platform/plugins/quickbooks/mcp/dist/lib/qbo-client.d.ts.map +1 -0
- package/payload/platform/plugins/quickbooks/mcp/dist/lib/qbo-client.js +178 -0
- package/payload/platform/plugins/quickbooks/mcp/dist/lib/qbo-client.js.map +1 -0
- package/payload/platform/plugins/quickbooks/mcp/dist/lib/secrets.d.ts +36 -0
- package/payload/platform/plugins/quickbooks/mcp/dist/lib/secrets.d.ts.map +1 -0
- package/payload/platform/plugins/quickbooks/mcp/dist/lib/secrets.js +107 -0
- package/payload/platform/plugins/quickbooks/mcp/dist/lib/secrets.js.map +1 -0
- package/payload/platform/plugins/quickbooks/mcp/package.json +19 -0
- package/payload/platform/plugins/quickbooks/skills/quickbooks/SKILL.md +37 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +16 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/server/{chunk-J6WDAWFJ.js → chunk-Q7EWROVN.js} +4 -0
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/public/assets/{AccessGate-Dh5A79FU.js → AccessGate-Byskkf47.js} +1 -1
- package/payload/server/public/assets/{AdminLoginScreens-B8s2TbT7.js → AdminLoginScreens-DgwQi3HN.js} +1 -1
- package/payload/server/public/assets/AdminShell-DQfL2c_L.js +1 -0
- package/payload/server/public/assets/{Checkbox-B_sOAyv1.js → Checkbox-C54JSreC.js} +1 -1
- package/payload/server/public/assets/OperatorConversations-DulQyF8c.js +1 -0
- package/payload/server/public/assets/{admin-gZEndvJT.js → admin-B25rkI9Q.js} +1 -1
- package/payload/server/public/assets/{audio-attachment-mime-B0b89VnH.js → audio-attachment-mime-BlwrgPQa.js} +1 -1
- package/payload/server/public/assets/{brand-BcNavK6q.css → brand-TWflEl22.css} +1 -1
- package/payload/server/public/assets/{browser-BUlB5_MD.js → browser-C9Z5dLlN.js} +1 -1
- package/payload/server/public/assets/chat-CGNWDmid.js +1 -0
- package/payload/server/public/assets/data-DCQDh0-Y.js +1 -0
- package/payload/server/public/assets/{graph-labels-AZLGoVy8.js → graph-labels-BBtL--_M.js} +1 -1
- package/payload/server/public/assets/{graph-DMCKpW6P.js → graph-sMzOI71g.js} +2 -2
- package/payload/server/public/assets/operator-hI6kJi0I.js +1 -0
- package/payload/server/public/assets/page-DbsqlpuX.js +1 -0
- package/payload/server/public/assets/{public-G_-UI9nB.js → public-Cs5N4-Az.js} +1 -1
- package/payload/server/public/assets/{public-next-C8_nExQB.js → public-next-DoGPYX6T.js} +1 -1
- package/payload/server/public/assets/{useSelectionMode-Bf6Rt-sl.js → useSelectionMode-Cs-vtuKI.js} +1 -1
- package/payload/server/public/browser.html +6 -6
- package/payload/server/public/chat.html +8 -8
- package/payload/server/public/data.html +5 -5
- package/payload/server/public/graph.html +8 -8
- package/payload/server/public/index.html +8 -8
- package/payload/server/public/operator.html +10 -10
- package/payload/server/public/public-next.html +9 -9
- package/payload/server/public/public.html +7 -7
- package/payload/server/server.js +600 -491
- package/payload/server/public/assets/AdminShell-Cu1zlb6L.js +0 -1
- package/payload/server/public/assets/OperatorConversations-hm0Gpu_Q.js +0 -1
- package/payload/server/public/assets/chat-BnceaVl7.js +0 -1
- package/payload/server/public/assets/data-3Nl3P5wt.js +0 -1
- package/payload/server/public/assets/operator-BF4F7k23.js +0 -1
- package/payload/server/public/assets/page-DQUEst1o.js +0 -1
- /package/payload/server/public/assets/{brand-BQ_u9UdS.js → brand-CYjs10m-.js} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -110,7 +110,7 @@ import {
|
|
|
110
110
|
vncLog,
|
|
111
111
|
walkPremiumBundles,
|
|
112
112
|
writeAdminUserAndPerson
|
|
113
|
-
} from "./chunk-
|
|
113
|
+
} from "./chunk-Q7EWROVN.js";
|
|
114
114
|
import {
|
|
115
115
|
__commonJS,
|
|
116
116
|
__toESM
|
|
@@ -1271,8 +1271,8 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
1271
1271
|
};
|
|
1272
1272
|
|
|
1273
1273
|
// server/index.ts
|
|
1274
|
-
import { readFileSync as
|
|
1275
|
-
import { resolve as resolve31, join as
|
|
1274
|
+
import { readFileSync as readFileSync29, existsSync as existsSync31, watchFile } from "fs";
|
|
1275
|
+
import { resolve as resolve31, join as join27, basename as basename9 } from "path";
|
|
1276
1276
|
import { homedir as homedir3 } from "os";
|
|
1277
1277
|
import { monitorEventLoopDelay } from "perf_hooks";
|
|
1278
1278
|
|
|
@@ -5225,8 +5225,8 @@ function webchatTurnTimeoutMs() {
|
|
|
5225
5225
|
return Number(process.env.WEBCHAT_TURN_TIMEOUT_MS ?? String(2 * 6e4));
|
|
5226
5226
|
}
|
|
5227
5227
|
function createChatRoutes(deps) {
|
|
5228
|
-
const
|
|
5229
|
-
|
|
5228
|
+
const app53 = new Hono();
|
|
5229
|
+
app53.post("/", async (c) => {
|
|
5230
5230
|
console.log(`[chat-route] entered route=public method=POST`);
|
|
5231
5231
|
const contentType = c.req.header("content-type") ?? "";
|
|
5232
5232
|
const account = resolveAccount();
|
|
@@ -5449,7 +5449,7 @@ ${result.result.text}` : result.result.text;
|
|
|
5449
5449
|
}
|
|
5450
5450
|
});
|
|
5451
5451
|
});
|
|
5452
|
-
return
|
|
5452
|
+
return app53;
|
|
5453
5453
|
}
|
|
5454
5454
|
|
|
5455
5455
|
// server/routes/whatsapp.ts
|
|
@@ -8031,8 +8031,8 @@ async function reapplyLeversViaManager() {
|
|
|
8031
8031
|
var WEBCHAT_SEND_TURN_WINDOW_MS = Number(process.env.WEBCHAT_SEND_TURN_WINDOW_MS ?? String(15e3));
|
|
8032
8032
|
var sendSeq = 0;
|
|
8033
8033
|
function createWebchatRoutes(deps) {
|
|
8034
|
-
const
|
|
8035
|
-
|
|
8034
|
+
const app53 = new Hono();
|
|
8035
|
+
app53.post("/send", requireAdminSession, async (c) => {
|
|
8036
8036
|
let accountId;
|
|
8037
8037
|
try {
|
|
8038
8038
|
accountId = resolvePlatformAccountId();
|
|
@@ -8191,7 +8191,7 @@ ${note}` : note;
|
|
|
8191
8191
|
if (turnTimer.unref) turnTimer.unref();
|
|
8192
8192
|
return c.json({ ok: true });
|
|
8193
8193
|
});
|
|
8194
|
-
|
|
8194
|
+
app53.post("/settings", requireAdminSession, async (c) => {
|
|
8195
8195
|
const body = await c.req.json().catch(() => null);
|
|
8196
8196
|
const op = body?.op;
|
|
8197
8197
|
const value = body?.value;
|
|
@@ -8231,7 +8231,7 @@ ${note}` : note;
|
|
|
8231
8231
|
console.log(`[webchat:settings] op=${op} outcome=accepted value=${value} settingsApplied=${settingsApplied}`);
|
|
8232
8232
|
return c.json({ ok: true, settingsApplied });
|
|
8233
8233
|
});
|
|
8234
|
-
|
|
8234
|
+
app53.get("/session", requireAdminSession, async (c) => {
|
|
8235
8235
|
let accountId;
|
|
8236
8236
|
try {
|
|
8237
8237
|
accountId = resolvePlatformAccountId();
|
|
@@ -8291,7 +8291,7 @@ ${note}` : note;
|
|
|
8291
8291
|
const indicators = await fetchComposerIndicators(sessionId);
|
|
8292
8292
|
return c.json({ sessionId, projectDir, sizeBytes: jsonlSizeBytes(projectDir, sessionId), ...indicators, ...readLevers(account) });
|
|
8293
8293
|
});
|
|
8294
|
-
return
|
|
8294
|
+
return app53;
|
|
8295
8295
|
}
|
|
8296
8296
|
|
|
8297
8297
|
// server/routes/webchat-greeting.ts
|
|
@@ -9424,14 +9424,122 @@ app7.post("/", async (c) => {
|
|
|
9424
9424
|
});
|
|
9425
9425
|
var telegram_default = app7;
|
|
9426
9426
|
|
|
9427
|
+
// server/routes/quickbooks.ts
|
|
9428
|
+
import { join as join17 } from "path";
|
|
9429
|
+
import { existsSync as existsSync12, readFileSync as readFileSync17, writeFileSync as writeFileSync8, mkdirSync as mkdirSync3, rmSync, renameSync as renameSync4 } from "fs";
|
|
9430
|
+
var TAG24 = "[quickbooks]";
|
|
9431
|
+
var INTUIT_TOKEN_URL = "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer";
|
|
9432
|
+
var STATE_RE = /^[A-Za-z0-9_-]+$/;
|
|
9433
|
+
function pendingPath(accountDir, state) {
|
|
9434
|
+
return join17(accountDir, "secrets", "quickbooks-pending", `${state}.json`);
|
|
9435
|
+
}
|
|
9436
|
+
function storePath(accountDir) {
|
|
9437
|
+
return join17(accountDir, "secrets", "quickbooks.json");
|
|
9438
|
+
}
|
|
9439
|
+
async function completeConsent(args) {
|
|
9440
|
+
const { accountDir, code, realmId } = args;
|
|
9441
|
+
const state = args.state;
|
|
9442
|
+
if (!state || !STATE_RE.test(state) || !existsSync12(pendingPath(accountDir, state))) {
|
|
9443
|
+
console.error(`${TAG24} op=callback state=${state ?? ""} stateValid=false realmId=${realmId ?? ""}`);
|
|
9444
|
+
return { ok: false, status: 400, message: "Invalid or unknown authorization state.", stateValid: false };
|
|
9445
|
+
}
|
|
9446
|
+
const claimFile = `${pendingPath(accountDir, state)}.claimed`;
|
|
9447
|
+
try {
|
|
9448
|
+
renameSync4(pendingPath(accountDir, state), claimFile);
|
|
9449
|
+
} catch {
|
|
9450
|
+
console.error(`${TAG24} op=callback state=${state} stateValid=false realmId=${realmId ?? ""}`);
|
|
9451
|
+
return { ok: false, status: 400, message: "Invalid or unknown authorization state.", stateValid: false };
|
|
9452
|
+
}
|
|
9453
|
+
try {
|
|
9454
|
+
let pending;
|
|
9455
|
+
try {
|
|
9456
|
+
pending = JSON.parse(readFileSync17(claimFile, "utf-8"));
|
|
9457
|
+
} catch {
|
|
9458
|
+
console.error(`${TAG24} op=callback state=${state} stateValid=false realmId=${realmId ?? ""}`);
|
|
9459
|
+
return { ok: false, status: 400, message: "Authorization state could not be read.", stateValid: false };
|
|
9460
|
+
}
|
|
9461
|
+
if (Date.now() > pending.expiresAt) {
|
|
9462
|
+
console.error(`${TAG24} op=callback state=${state} stateValid=false realmId=${realmId ?? ""}`);
|
|
9463
|
+
return { ok: false, status: 400, message: "Authorization request expired. Generate a new consent link.", stateValid: false };
|
|
9464
|
+
}
|
|
9465
|
+
console.error(`${TAG24} op=callback state=${state} stateValid=true realmId=${realmId ?? ""}`);
|
|
9466
|
+
if (!code || !realmId) {
|
|
9467
|
+
return { ok: false, status: 400, message: "Missing code or realmId in the callback.", stateValid: true };
|
|
9468
|
+
}
|
|
9469
|
+
if (!existsSync12(storePath(accountDir))) {
|
|
9470
|
+
return { ok: false, status: 500, message: "No QuickBooks credentials are stored for this account.", stateValid: true };
|
|
9471
|
+
}
|
|
9472
|
+
const store2 = JSON.parse(readFileSync17(storePath(accountDir), "utf-8"));
|
|
9473
|
+
const form = new URLSearchParams({
|
|
9474
|
+
grant_type: "authorization_code",
|
|
9475
|
+
code,
|
|
9476
|
+
redirect_uri: pending.redirectUri
|
|
9477
|
+
});
|
|
9478
|
+
const res = await fetch(args.tokenUrl ?? INTUIT_TOKEN_URL, {
|
|
9479
|
+
method: "POST",
|
|
9480
|
+
headers: {
|
|
9481
|
+
Authorization: "Basic " + Buffer.from(`${store2.clientId}:${store2.clientSecret}`).toString("base64"),
|
|
9482
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
9483
|
+
Accept: "application/json"
|
|
9484
|
+
},
|
|
9485
|
+
body: form.toString()
|
|
9486
|
+
});
|
|
9487
|
+
const text = await res.text();
|
|
9488
|
+
if (!res.ok) {
|
|
9489
|
+
console.error(`${TAG24} op=token-exchange realmId=${realmId} persisted=false`);
|
|
9490
|
+
return { ok: false, status: 502, message: `Token exchange failed (${res.status}). Generate a new consent link to retry.`, stateValid: true };
|
|
9491
|
+
}
|
|
9492
|
+
const body = JSON.parse(text);
|
|
9493
|
+
if (!body.refresh_token) {
|
|
9494
|
+
console.error(`${TAG24} op=token-exchange realmId=${realmId} persisted=false`);
|
|
9495
|
+
return { ok: false, status: 502, message: "Token exchange returned no refresh token.", stateValid: true };
|
|
9496
|
+
}
|
|
9497
|
+
const now = Date.now();
|
|
9498
|
+
store2.connections = store2.connections ?? {};
|
|
9499
|
+
store2.connections[realmId] = {
|
|
9500
|
+
refreshToken: body.refresh_token,
|
|
9501
|
+
refreshTokenExpiry: now + (body.x_refresh_token_expires_in ?? 864e4) * 1e3,
|
|
9502
|
+
lastRefresh: now
|
|
9503
|
+
};
|
|
9504
|
+
mkdirSync3(join17(accountDir, "secrets"), { recursive: true });
|
|
9505
|
+
writeFileSync8(storePath(accountDir), JSON.stringify(store2, null, 2), { mode: 384 });
|
|
9506
|
+
const persisted = JSON.parse(readFileSync17(storePath(accountDir), "utf-8")).connections?.[realmId]?.refreshToken === body.refresh_token;
|
|
9507
|
+
console.error(`${TAG24} op=token-exchange realmId=${realmId} persisted=${persisted}`);
|
|
9508
|
+
return { ok: persisted, status: persisted ? 200 : 500, message: persisted ? `Connected company ${realmId}.` : "Failed to persist the connection.", stateValid: true };
|
|
9509
|
+
} finally {
|
|
9510
|
+
rmSync(claimFile, { force: true });
|
|
9511
|
+
}
|
|
9512
|
+
}
|
|
9513
|
+
function page(title, detail) {
|
|
9514
|
+
return `<!doctype html><html><head><meta charset="utf-8"><title>${title}</title></head><body style="font-family:system-ui;max-width:32rem;margin:4rem auto;text-align:center"><h1>${title}</h1><p>${detail}</p><p>You can close this tab.</p></body></html>`;
|
|
9515
|
+
}
|
|
9516
|
+
var app8 = new Hono();
|
|
9517
|
+
app8.get("/callback", async (c) => {
|
|
9518
|
+
const account = resolveAccount();
|
|
9519
|
+
if (!account) {
|
|
9520
|
+
console.error(`${TAG24} op=callback stateValid=false realmId= reason=no-account`);
|
|
9521
|
+
return c.html(page("QuickBooks", "This install has no account configured."), 500);
|
|
9522
|
+
}
|
|
9523
|
+
const result = await completeConsent({
|
|
9524
|
+
accountDir: account.accountDir,
|
|
9525
|
+
code: c.req.query("code"),
|
|
9526
|
+
state: c.req.query("state"),
|
|
9527
|
+
realmId: c.req.query("realmId"),
|
|
9528
|
+
tokenUrl: process.env.QUICKBOOKS_TOKEN_URL
|
|
9529
|
+
});
|
|
9530
|
+
const title = result.ok ? "QuickBooks connected" : "QuickBooks authorization failed";
|
|
9531
|
+
return c.html(page(title, result.message), result.status);
|
|
9532
|
+
});
|
|
9533
|
+
var quickbooks_default = app8;
|
|
9534
|
+
|
|
9427
9535
|
// server/routes/onboarding.ts
|
|
9428
9536
|
import { spawn, spawnSync as spawnSync2, execFileSync as execFileSync2 } from "child_process";
|
|
9429
|
-
import { openSync as openSync3, closeSync as closeSync3, writeFileSync as
|
|
9537
|
+
import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeFileSync10, writeSync, existsSync as existsSync14, readFileSync as readFileSync19, unlinkSync as unlinkSync2 } from "fs";
|
|
9430
9538
|
import { createHash as createHash3, randomUUID as randomUUID8 } from "crypto";
|
|
9431
9539
|
|
|
9432
9540
|
// ../lib/admins-write/src/index.ts
|
|
9433
|
-
import { existsSync as
|
|
9434
|
-
import { dirname as dirname4, join as
|
|
9541
|
+
import { existsSync as existsSync13, readFileSync as readFileSync18, writeFileSync as writeFileSync9, renameSync as renameSync5, mkdirSync as mkdirSync4, readdirSync as readdirSync10, statSync as statSync7 } from "fs";
|
|
9542
|
+
import { dirname as dirname4, join as join18 } from "path";
|
|
9435
9543
|
function logLine(input, result) {
|
|
9436
9544
|
const userIdShort = input.userId.slice(0, 8);
|
|
9437
9545
|
console.error(
|
|
@@ -9439,17 +9547,17 @@ function logLine(input, result) {
|
|
|
9439
9547
|
);
|
|
9440
9548
|
}
|
|
9441
9549
|
function writeFileAtomic(filePath, contents, mode) {
|
|
9442
|
-
|
|
9550
|
+
mkdirSync4(dirname4(filePath), { recursive: true });
|
|
9443
9551
|
const tempPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
9444
|
-
|
|
9445
|
-
|
|
9552
|
+
writeFileSync9(tempPath, contents, mode !== void 0 ? { mode } : void 0);
|
|
9553
|
+
renameSync5(tempPath, filePath);
|
|
9446
9554
|
}
|
|
9447
9555
|
function writeAdminEntry(input) {
|
|
9448
9556
|
const result = { usersJsonResult: "noop", accountJsonResult: "noop" };
|
|
9449
9557
|
try {
|
|
9450
9558
|
let users = [];
|
|
9451
|
-
if (
|
|
9452
|
-
const raw =
|
|
9559
|
+
if (existsSync13(input.usersFile)) {
|
|
9560
|
+
const raw = readFileSync18(input.usersFile, "utf-8").trim();
|
|
9453
9561
|
if (raw) {
|
|
9454
9562
|
const parsed = JSON.parse(raw);
|
|
9455
9563
|
if (!Array.isArray(parsed)) {
|
|
@@ -9473,11 +9581,11 @@ function writeAdminEntry(input) {
|
|
|
9473
9581
|
return result;
|
|
9474
9582
|
}
|
|
9475
9583
|
try {
|
|
9476
|
-
const accountJsonPath =
|
|
9477
|
-
if (!
|
|
9584
|
+
const accountJsonPath = join18(input.accountDir, "account.json");
|
|
9585
|
+
if (!existsSync13(accountJsonPath)) {
|
|
9478
9586
|
throw new Error(`account.json not found at ${accountJsonPath}`);
|
|
9479
9587
|
}
|
|
9480
|
-
const config = JSON.parse(
|
|
9588
|
+
const config = JSON.parse(readFileSync18(accountJsonPath, "utf-8"));
|
|
9481
9589
|
const admins = config.admins ?? [];
|
|
9482
9590
|
if (admins.some((a) => a.userId === input.userId)) {
|
|
9483
9591
|
result.accountJsonResult = "noop";
|
|
@@ -9501,9 +9609,9 @@ function checkAdminAuthInvariant(input) {
|
|
|
9501
9609
|
usersWithoutAccount: []
|
|
9502
9610
|
};
|
|
9503
9611
|
const usersUserIds = /* @__PURE__ */ new Set();
|
|
9504
|
-
if (
|
|
9612
|
+
if (existsSync13(input.usersFile)) {
|
|
9505
9613
|
try {
|
|
9506
|
-
const raw =
|
|
9614
|
+
const raw = readFileSync18(input.usersFile, "utf-8").trim();
|
|
9507
9615
|
if (raw) {
|
|
9508
9616
|
const users = JSON.parse(raw);
|
|
9509
9617
|
for (const u of users) {
|
|
@@ -9516,7 +9624,7 @@ function checkAdminAuthInvariant(input) {
|
|
|
9516
9624
|
}
|
|
9517
9625
|
}
|
|
9518
9626
|
const accountUserIds = /* @__PURE__ */ new Set();
|
|
9519
|
-
if (
|
|
9627
|
+
if (existsSync13(input.accountsDir)) {
|
|
9520
9628
|
let entries;
|
|
9521
9629
|
try {
|
|
9522
9630
|
entries = readdirSync10(input.accountsDir);
|
|
@@ -9528,17 +9636,17 @@ function checkAdminAuthInvariant(input) {
|
|
|
9528
9636
|
}
|
|
9529
9637
|
for (const entry of entries) {
|
|
9530
9638
|
if (entry.startsWith(".")) continue;
|
|
9531
|
-
const accountDir =
|
|
9639
|
+
const accountDir = join18(input.accountsDir, entry);
|
|
9532
9640
|
try {
|
|
9533
9641
|
if (!statSync7(accountDir).isDirectory()) continue;
|
|
9534
9642
|
} catch {
|
|
9535
9643
|
continue;
|
|
9536
9644
|
}
|
|
9537
|
-
const accountJsonPath =
|
|
9538
|
-
if (!
|
|
9645
|
+
const accountJsonPath = join18(accountDir, "account.json");
|
|
9646
|
+
if (!existsSync13(accountJsonPath)) continue;
|
|
9539
9647
|
let admins = [];
|
|
9540
9648
|
try {
|
|
9541
|
-
const config = JSON.parse(
|
|
9649
|
+
const config = JSON.parse(readFileSync18(accountJsonPath, "utf-8"));
|
|
9542
9650
|
admins = config.admins ?? [];
|
|
9543
9651
|
} catch (err) {
|
|
9544
9652
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -9578,8 +9686,8 @@ function hashPin2(pin) {
|
|
|
9578
9686
|
return createHash3("sha256").update(pin).digest("hex");
|
|
9579
9687
|
}
|
|
9580
9688
|
function readUsersFile2() {
|
|
9581
|
-
if (!
|
|
9582
|
-
const raw =
|
|
9689
|
+
if (!existsSync14(USERS_FILE)) return null;
|
|
9690
|
+
const raw = readFileSync19(USERS_FILE, "utf-8").trim();
|
|
9583
9691
|
if (!raw) return [];
|
|
9584
9692
|
return JSON.parse(raw);
|
|
9585
9693
|
}
|
|
@@ -9609,11 +9717,11 @@ async function waitForAuthPage(timeoutMs = 2e4) {
|
|
|
9609
9717
|
}
|
|
9610
9718
|
return false;
|
|
9611
9719
|
}
|
|
9612
|
-
var
|
|
9613
|
-
|
|
9720
|
+
var app9 = new Hono();
|
|
9721
|
+
app9.get("/claude-auth", async (c) => {
|
|
9614
9722
|
return c.json({ authenticated: await checkAuthStatus() });
|
|
9615
9723
|
});
|
|
9616
|
-
|
|
9724
|
+
app9.post("/claude-auth", async (c) => {
|
|
9617
9725
|
let body = {};
|
|
9618
9726
|
try {
|
|
9619
9727
|
body = await c.req.json();
|
|
@@ -9632,7 +9740,7 @@ app8.post("/claude-auth", async (c) => {
|
|
|
9632
9740
|
} catch (err) {
|
|
9633
9741
|
logoutError = err instanceof Error ? err.message : String(err);
|
|
9634
9742
|
}
|
|
9635
|
-
const credentialsPresent =
|
|
9743
|
+
const credentialsPresent = existsSync14(CLAUDE_CREDENTIALS_FILE);
|
|
9636
9744
|
const ranMs = Date.now() - start;
|
|
9637
9745
|
console.log(`[onboarding] op=claude-logout credentialsPresent=${credentialsPresent} ranMs=${ranMs} logoutError=${logoutError ? JSON.stringify(logoutError.slice(0, 120)) : "none"}`);
|
|
9638
9746
|
return c.json({ logged_out: !credentialsPresent });
|
|
@@ -9650,7 +9758,7 @@ app8.post("/claude-auth", async (c) => {
|
|
|
9650
9758
|
return c.json({ launched: cdpReady });
|
|
9651
9759
|
}
|
|
9652
9760
|
ensureLogDir();
|
|
9653
|
-
|
|
9761
|
+
writeFileSync10(logPath("claude-auth"), "");
|
|
9654
9762
|
const claudeAuthLogFd = openSync3(logPath("claude-auth"), "a");
|
|
9655
9763
|
const onClaudeOutput = (chunk) => writeSync(claudeAuthLogFd, chunk);
|
|
9656
9764
|
if (process.platform === "darwin") {
|
|
@@ -9683,7 +9791,7 @@ app8.post("/claude-auth", async (c) => {
|
|
|
9683
9791
|
await waitForAuthPage(2e4);
|
|
9684
9792
|
return c.json({ started: true, transport });
|
|
9685
9793
|
});
|
|
9686
|
-
|
|
9794
|
+
app9.post("/set-pin", async (c) => {
|
|
9687
9795
|
let existingUsers = null;
|
|
9688
9796
|
try {
|
|
9689
9797
|
existingUsers = readUsersFile2();
|
|
@@ -9739,9 +9847,9 @@ app8.post("/set-pin", async (c) => {
|
|
|
9739
9847
|
console.log(`[set-pin] wrote users.json + account.json admins: userId=${userId.slice(0, 8)}\u2026 role=owner`);
|
|
9740
9848
|
if (process.platform === "linux") {
|
|
9741
9849
|
let installOwner = null;
|
|
9742
|
-
if (
|
|
9850
|
+
if (existsSync14(INSTALL_OWNER_FILE)) {
|
|
9743
9851
|
try {
|
|
9744
|
-
const raw =
|
|
9852
|
+
const raw = readFileSync19(INSTALL_OWNER_FILE, "utf-8").trim();
|
|
9745
9853
|
if (raw.length > 0) installOwner = raw;
|
|
9746
9854
|
} catch (err) {
|
|
9747
9855
|
console.error(`[set-pin] install-owner-read-failed path=${INSTALL_OWNER_FILE} error=${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -9785,7 +9893,7 @@ ${body.pin}
|
|
|
9785
9893
|
}
|
|
9786
9894
|
return c.json({ ok: true });
|
|
9787
9895
|
});
|
|
9788
|
-
|
|
9896
|
+
app9.delete("/set-pin", async (c) => {
|
|
9789
9897
|
let users = null;
|
|
9790
9898
|
try {
|
|
9791
9899
|
users = readUsersFile2();
|
|
@@ -9814,17 +9922,17 @@ app8.delete("/set-pin", async (c) => {
|
|
|
9814
9922
|
unlinkSync2(USERS_FILE);
|
|
9815
9923
|
console.log(`[set-pin] cleared users.json (last entry removed): userId=${matchedUser.userId.slice(0, 8)}\u2026`);
|
|
9816
9924
|
} else {
|
|
9817
|
-
|
|
9925
|
+
writeFileSync10(USERS_FILE, JSON.stringify(remaining), { mode: 384 });
|
|
9818
9926
|
console.log(`[set-pin] removed entry from users.json: userId=${matchedUser.userId.slice(0, 8)}\u2026 remaining=${remaining.length}`);
|
|
9819
9927
|
}
|
|
9820
9928
|
return c.json({ ok: true });
|
|
9821
9929
|
});
|
|
9822
|
-
var onboarding_default =
|
|
9930
|
+
var onboarding_default = app9;
|
|
9823
9931
|
|
|
9824
9932
|
// server/routes/client-error.ts
|
|
9825
|
-
import { appendFileSync, existsSync as
|
|
9826
|
-
import { join as
|
|
9827
|
-
var CLIENT_ERRORS_LOG =
|
|
9933
|
+
import { appendFileSync, existsSync as existsSync15, renameSync as renameSync6, statSync as statSync8 } from "fs";
|
|
9934
|
+
import { join as join19 } from "path";
|
|
9935
|
+
var CLIENT_ERRORS_LOG = join19(LOG_DIR, "client-errors.log");
|
|
9828
9936
|
var MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
9829
9937
|
var MAX_BODY_SIZE = 8 * 1024;
|
|
9830
9938
|
var MAX_STACK_LEN = 2e3;
|
|
@@ -9867,16 +9975,16 @@ function stackHead(stack) {
|
|
|
9867
9975
|
}
|
|
9868
9976
|
function rotateIfNeeded() {
|
|
9869
9977
|
try {
|
|
9870
|
-
if (!
|
|
9978
|
+
if (!existsSync15(CLIENT_ERRORS_LOG)) return;
|
|
9871
9979
|
const stats = statSync8(CLIENT_ERRORS_LOG);
|
|
9872
9980
|
if (stats.size < MAX_LOG_SIZE) return;
|
|
9873
|
-
|
|
9981
|
+
renameSync6(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
|
|
9874
9982
|
} catch (err) {
|
|
9875
9983
|
console.error(`[client-error] log rotation failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
9876
9984
|
}
|
|
9877
9985
|
}
|
|
9878
|
-
var
|
|
9879
|
-
|
|
9986
|
+
var app10 = new Hono();
|
|
9987
|
+
app10.post("/", async (c) => {
|
|
9880
9988
|
const client = resolveClientIp(
|
|
9881
9989
|
c.env?.incoming?.socket?.remoteAddress,
|
|
9882
9990
|
c.req.header("x-forwarded-for")
|
|
@@ -9978,7 +10086,7 @@ app9.post("/", async (c) => {
|
|
|
9978
10086
|
}
|
|
9979
10087
|
return c.json({ ok: true });
|
|
9980
10088
|
});
|
|
9981
|
-
var client_error_default =
|
|
10089
|
+
var client_error_default = app10;
|
|
9982
10090
|
|
|
9983
10091
|
// server/routes/admin/session.ts
|
|
9984
10092
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
@@ -10036,8 +10144,8 @@ async function createAdminSession(accountId, thinkingView, userId, userName, rol
|
|
|
10036
10144
|
sessionId: initialSessionId
|
|
10037
10145
|
};
|
|
10038
10146
|
}
|
|
10039
|
-
var
|
|
10040
|
-
|
|
10147
|
+
var app11 = new Hono();
|
|
10148
|
+
app11.get("/", async (c) => {
|
|
10041
10149
|
const signedSessionToken = c.req.query("session_key");
|
|
10042
10150
|
if (!signedSessionToken) {
|
|
10043
10151
|
return c.json({ error: "Invalid or expired admin session" }, 401);
|
|
@@ -10083,7 +10191,7 @@ app10.get("/", async (c) => {
|
|
|
10083
10191
|
sessionId: getSessionIdForSession(cacheKey) ?? null
|
|
10084
10192
|
});
|
|
10085
10193
|
});
|
|
10086
|
-
|
|
10194
|
+
app11.post("/", async (c) => {
|
|
10087
10195
|
let body;
|
|
10088
10196
|
try {
|
|
10089
10197
|
body = await c.req.json();
|
|
@@ -10146,21 +10254,21 @@ app10.post("/", async (c) => {
|
|
|
10146
10254
|
const payload = await createAdminSession(selected.accountId, selected.config.thinkingView, userId, userName, selected.role, avatar);
|
|
10147
10255
|
return c.json(payload);
|
|
10148
10256
|
});
|
|
10149
|
-
var session_default =
|
|
10257
|
+
var session_default = app11;
|
|
10150
10258
|
|
|
10151
10259
|
// server/routes/admin/logs.ts
|
|
10152
|
-
import { existsSync as
|
|
10260
|
+
import { existsSync as existsSync17, readdirSync as readdirSync11, readFileSync as readFileSync20, statSync as statSync9 } from "fs";
|
|
10153
10261
|
import { resolve as resolve16, basename as basename5 } from "path";
|
|
10154
10262
|
|
|
10155
10263
|
// app/lib/logs-read-resolve.ts
|
|
10156
|
-
import { existsSync as
|
|
10157
|
-
import { join as
|
|
10264
|
+
import { existsSync as existsSync16 } from "fs";
|
|
10265
|
+
import { join as join20 } from "path";
|
|
10158
10266
|
function resolveSessionLogPaths(filename, logDirs) {
|
|
10159
10267
|
const tried = [filename];
|
|
10160
10268
|
const hits = [];
|
|
10161
10269
|
for (const dir of logDirs) {
|
|
10162
|
-
const fullPath =
|
|
10163
|
-
if (
|
|
10270
|
+
const fullPath = join20(dir, filename);
|
|
10271
|
+
if (existsSync16(fullPath)) {
|
|
10164
10272
|
hits.push({ path: fullPath, dir });
|
|
10165
10273
|
}
|
|
10166
10274
|
}
|
|
@@ -10169,8 +10277,8 @@ function resolveSessionLogPaths(filename, logDirs) {
|
|
|
10169
10277
|
|
|
10170
10278
|
// server/routes/admin/logs.ts
|
|
10171
10279
|
var TAIL_BYTES = 8192;
|
|
10172
|
-
var
|
|
10173
|
-
|
|
10280
|
+
var app12 = new Hono();
|
|
10281
|
+
app12.get("/", async (c) => {
|
|
10174
10282
|
const fileParam = c.req.query("file");
|
|
10175
10283
|
const typeParam = c.req.query("type");
|
|
10176
10284
|
const sessionIdParam = c.req.query("sessionId");
|
|
@@ -10188,7 +10296,7 @@ app11.get("/", async (c) => {
|
|
|
10188
10296
|
const filePath = resolve16(dir, safe);
|
|
10189
10297
|
searched.push(filePath);
|
|
10190
10298
|
try {
|
|
10191
|
-
const buffer =
|
|
10299
|
+
const buffer = readFileSync20(filePath);
|
|
10192
10300
|
const onDiskBytes = statSync9(filePath).size;
|
|
10193
10301
|
const headers = {
|
|
10194
10302
|
"Content-Type": "text/plain; charset=utf-8",
|
|
@@ -10253,7 +10361,7 @@ app11.get("/", async (c) => {
|
|
|
10253
10361
|
console.info(`[admin/logs] resolved cacheKey=${cacheKeySlice} sessionId=${sessionIdSlice} via=${primaryId === cacheKey ? "cacheKey" : primaryId === sessionKeyFromConv ? "reverse-lookup" : "sessionId-fallback"}`);
|
|
10254
10362
|
try {
|
|
10255
10363
|
const filename = basename5(hit.path);
|
|
10256
|
-
const buffer =
|
|
10364
|
+
const buffer = readFileSync20(hit.path);
|
|
10257
10365
|
const onDiskBytes = statSync9(hit.path).size;
|
|
10258
10366
|
const headers = {
|
|
10259
10367
|
"Content-Type": "text/plain; charset=utf-8",
|
|
@@ -10288,7 +10396,7 @@ app11.get("/", async (c) => {
|
|
|
10288
10396
|
const seen = /* @__PURE__ */ new Set();
|
|
10289
10397
|
const logs = {};
|
|
10290
10398
|
for (const dir of logDirs) {
|
|
10291
|
-
if (!
|
|
10399
|
+
if (!existsSync17(dir)) continue;
|
|
10292
10400
|
let files;
|
|
10293
10401
|
try {
|
|
10294
10402
|
files = readdirSync11(dir).filter((f) => f.endsWith(".log"));
|
|
@@ -10300,7 +10408,7 @@ app11.get("/", async (c) => {
|
|
|
10300
10408
|
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync9(resolve16(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
|
|
10301
10409
|
seen.add(name);
|
|
10302
10410
|
try {
|
|
10303
|
-
const content =
|
|
10411
|
+
const content = readFileSync20(resolve16(dir, name));
|
|
10304
10412
|
const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
|
|
10305
10413
|
logs[name] = tail.trim() || "(empty)";
|
|
10306
10414
|
} catch (err) {
|
|
@@ -10312,12 +10420,12 @@ app11.get("/", async (c) => {
|
|
|
10312
10420
|
}
|
|
10313
10421
|
return c.json({ logs });
|
|
10314
10422
|
});
|
|
10315
|
-
var logs_default =
|
|
10423
|
+
var logs_default = app12;
|
|
10316
10424
|
|
|
10317
10425
|
// server/routes/admin/claude-info.ts
|
|
10318
10426
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
10319
|
-
var
|
|
10320
|
-
|
|
10427
|
+
var app13 = new Hono();
|
|
10428
|
+
app13.get("/", (c) => {
|
|
10321
10429
|
let version = "unknown";
|
|
10322
10430
|
try {
|
|
10323
10431
|
const raw = execFileSync3("claude", ["--version"], { encoding: "utf-8", timeout: 5e3 });
|
|
@@ -10335,14 +10443,14 @@ app12.get("/", (c) => {
|
|
|
10335
10443
|
const thinkingView = resolvedAccount?.config.thinkingView ?? "default";
|
|
10336
10444
|
return c.json({ version, account, model, thinkingView });
|
|
10337
10445
|
});
|
|
10338
|
-
var claude_info_default =
|
|
10446
|
+
var claude_info_default = app13;
|
|
10339
10447
|
|
|
10340
10448
|
// server/routes/admin/attachment.ts
|
|
10341
10449
|
import { readFile as readFile2, readdir } from "fs/promises";
|
|
10342
|
-
import { existsSync as
|
|
10450
|
+
import { existsSync as existsSync18 } from "fs";
|
|
10343
10451
|
import { resolve as resolve17 } from "path";
|
|
10344
|
-
var
|
|
10345
|
-
|
|
10452
|
+
var app14 = new Hono();
|
|
10453
|
+
app14.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
10346
10454
|
const attachmentId = c.req.param("attachmentId");
|
|
10347
10455
|
const cacheKey = c.var.cacheKey;
|
|
10348
10456
|
const accountId = getAccountIdForSession(cacheKey);
|
|
@@ -10353,11 +10461,11 @@ app13.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
10353
10461
|
return new Response("Not found", { status: 404 });
|
|
10354
10462
|
}
|
|
10355
10463
|
const dir = resolve17(DATA_ROOT, "accounts", accountId, "uploads", attachmentId);
|
|
10356
|
-
if (!
|
|
10464
|
+
if (!existsSync18(dir)) {
|
|
10357
10465
|
return new Response("Not found", { status: 404 });
|
|
10358
10466
|
}
|
|
10359
10467
|
const metaPath = resolve17(dir, `${attachmentId}.meta.json`);
|
|
10360
|
-
if (!
|
|
10468
|
+
if (!existsSync18(metaPath)) {
|
|
10361
10469
|
return new Response("Not found", { status: 404 });
|
|
10362
10470
|
}
|
|
10363
10471
|
let meta;
|
|
@@ -10381,17 +10489,17 @@ app13.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
10381
10489
|
}
|
|
10382
10490
|
});
|
|
10383
10491
|
});
|
|
10384
|
-
var attachment_default =
|
|
10492
|
+
var attachment_default = app14;
|
|
10385
10493
|
|
|
10386
10494
|
// server/routes/admin/agents.ts
|
|
10387
10495
|
import { resolve as resolve18 } from "path";
|
|
10388
|
-
import { readdirSync as readdirSync12, readFileSync as
|
|
10389
|
-
var
|
|
10390
|
-
|
|
10496
|
+
import { readdirSync as readdirSync12, readFileSync as readFileSync21, existsSync as existsSync19, rmSync as rmSync2 } from "fs";
|
|
10497
|
+
var app15 = new Hono();
|
|
10498
|
+
app15.get("/", (c) => {
|
|
10391
10499
|
const account = resolveAccount();
|
|
10392
10500
|
if (!account) return c.json({ agents: [] });
|
|
10393
10501
|
const agentsDir = resolve18(account.accountDir, "agents");
|
|
10394
|
-
if (!
|
|
10502
|
+
if (!existsSync19(agentsDir)) return c.json({ agents: [] });
|
|
10395
10503
|
const agents = [];
|
|
10396
10504
|
try {
|
|
10397
10505
|
const entries = readdirSync12(agentsDir, { withFileTypes: true });
|
|
@@ -10399,9 +10507,9 @@ app14.get("/", (c) => {
|
|
|
10399
10507
|
if (!entry.isDirectory()) continue;
|
|
10400
10508
|
if (entry.name === "admin") continue;
|
|
10401
10509
|
const configPath2 = resolve18(agentsDir, entry.name, "config.json");
|
|
10402
|
-
if (!
|
|
10510
|
+
if (!existsSync19(configPath2)) continue;
|
|
10403
10511
|
try {
|
|
10404
|
-
const config = JSON.parse(
|
|
10512
|
+
const config = JSON.parse(readFileSync21(configPath2, "utf-8"));
|
|
10405
10513
|
agents.push({
|
|
10406
10514
|
slug: entry.name,
|
|
10407
10515
|
displayName: config.displayName ?? entry.name,
|
|
@@ -10417,7 +10525,7 @@ app14.get("/", (c) => {
|
|
|
10417
10525
|
}
|
|
10418
10526
|
return c.json({ agents });
|
|
10419
10527
|
});
|
|
10420
|
-
|
|
10528
|
+
app15.delete("/:slug", async (c) => {
|
|
10421
10529
|
const slug = c.req.param("slug");
|
|
10422
10530
|
const account = resolveAccount();
|
|
10423
10531
|
if (!account) return c.json({ error: "No account resolved" }, 400);
|
|
@@ -10428,7 +10536,7 @@ app14.delete("/:slug", async (c) => {
|
|
|
10428
10536
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
10429
10537
|
}
|
|
10430
10538
|
const agentDir = resolve18(account.accountDir, "agents", slug);
|
|
10431
|
-
if (!
|
|
10539
|
+
if (!existsSync19(agentDir)) {
|
|
10432
10540
|
return c.json({ error: "Agent not found" }, 404);
|
|
10433
10541
|
}
|
|
10434
10542
|
try {
|
|
@@ -10439,7 +10547,7 @@ app14.delete("/:slug", async (c) => {
|
|
|
10439
10547
|
return c.json({ error: `Graph cleanup failed: ${msg}` }, 500);
|
|
10440
10548
|
}
|
|
10441
10549
|
try {
|
|
10442
|
-
|
|
10550
|
+
rmSync2(agentDir, { recursive: true, force: true });
|
|
10443
10551
|
console.log(`[admin/agents] deleted agent "${slug}"`);
|
|
10444
10552
|
return c.json({ ok: true });
|
|
10445
10553
|
} catch (err) {
|
|
@@ -10447,7 +10555,7 @@ app14.delete("/:slug", async (c) => {
|
|
|
10447
10555
|
return c.json({ error: "Failed to delete agent" }, 500);
|
|
10448
10556
|
}
|
|
10449
10557
|
});
|
|
10450
|
-
|
|
10558
|
+
app15.post("/:slug/project", async (c) => {
|
|
10451
10559
|
const slug = c.req.param("slug");
|
|
10452
10560
|
const account = resolveAccount();
|
|
10453
10561
|
if (!account) return c.json({ error: "No account resolved" }, 400);
|
|
@@ -10458,7 +10566,7 @@ app14.post("/:slug/project", async (c) => {
|
|
|
10458
10566
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
10459
10567
|
}
|
|
10460
10568
|
const agentDir = resolve18(account.accountDir, "agents", slug);
|
|
10461
|
-
if (!
|
|
10569
|
+
if (!existsSync19(agentDir)) {
|
|
10462
10570
|
return c.json({ error: "Agent not found on disk" }, 404);
|
|
10463
10571
|
}
|
|
10464
10572
|
try {
|
|
@@ -10469,12 +10577,12 @@ app14.post("/:slug/project", async (c) => {
|
|
|
10469
10577
|
return c.json({ error: `Projection failed: ${msg}` }, 500);
|
|
10470
10578
|
}
|
|
10471
10579
|
});
|
|
10472
|
-
var agents_default =
|
|
10580
|
+
var agents_default = app15;
|
|
10473
10581
|
|
|
10474
10582
|
// server/routes/admin/sessions.ts
|
|
10475
10583
|
import crypto2 from "crypto";
|
|
10476
10584
|
import { resolve as resolvePath } from "path";
|
|
10477
|
-
import { existsSync as
|
|
10585
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync5, createWriteStream } from "fs";
|
|
10478
10586
|
|
|
10479
10587
|
// ../lib/admin-conversation-purge/src/index.ts
|
|
10480
10588
|
async function purgeAdminConversationJsonls(args) {
|
|
@@ -10621,7 +10729,7 @@ var pickComponentBytes = (..._args) => null;
|
|
|
10621
10729
|
function openResumeStreamLog(accountId, sessionId) {
|
|
10622
10730
|
const dir = resolvePath(ACCOUNTS_DIR, accountId, "resume-logs");
|
|
10623
10731
|
try {
|
|
10624
|
-
|
|
10732
|
+
mkdirSync5(dir, { recursive: true });
|
|
10625
10733
|
} catch {
|
|
10626
10734
|
}
|
|
10627
10735
|
return createWriteStream(resolvePath(dir, `${sessionId}.log`), { flags: "a" });
|
|
@@ -10634,7 +10742,7 @@ function validateAndShapeAttachments(raws, conversationAccountId, sessionId, mes
|
|
|
10634
10742
|
let reason = null;
|
|
10635
10743
|
if (!a.attachmentId || !a.filename || !a.mimeType || !a.storagePath) reason = "schema-fail";
|
|
10636
10744
|
else if (a.accountId !== conversationAccountId) reason = "account-mismatch";
|
|
10637
|
-
else if (!
|
|
10745
|
+
else if (!existsSync20(a.storagePath)) reason = "missing-file";
|
|
10638
10746
|
if (reason) {
|
|
10639
10747
|
invalid++;
|
|
10640
10748
|
try {
|
|
@@ -10741,8 +10849,8 @@ function formatAge(updatedAtStr) {
|
|
|
10741
10849
|
return "unknown";
|
|
10742
10850
|
}
|
|
10743
10851
|
}
|
|
10744
|
-
var
|
|
10745
|
-
|
|
10852
|
+
var app16 = new Hono();
|
|
10853
|
+
app16.get("/", requireAdminSession, async (c) => {
|
|
10746
10854
|
const cacheKey = c.var.cacheKey;
|
|
10747
10855
|
const accountId = getAccountIdForSession(cacheKey);
|
|
10748
10856
|
if (!accountId) return c.json({ error: "Account not found for session" }, 401);
|
|
@@ -10772,7 +10880,7 @@ app15.get("/", requireAdminSession, async (c) => {
|
|
|
10772
10880
|
return c.json({ error: "Failed to fetch sessions" }, 500);
|
|
10773
10881
|
}
|
|
10774
10882
|
});
|
|
10775
|
-
|
|
10883
|
+
app16.post("/new", requireAdminSession, async (c) => {
|
|
10776
10884
|
const oldCacheKey = c.var.cacheKey;
|
|
10777
10885
|
console.log(`[admin-chat] new-conversation outcome=ingress cacheKey=${oldCacheKey.slice(0, 8)}`);
|
|
10778
10886
|
const accountId = getAccountIdForSession(oldCacheKey);
|
|
@@ -10789,7 +10897,7 @@ app15.post("/new", requireAdminSession, async (c) => {
|
|
|
10789
10897
|
console.log(`[admin-chat] new-conversation outcome=ok oldKey=${oldCacheKey.slice(0, 8)} newKey=${newCacheKey.slice(0, 8)}`);
|
|
10790
10898
|
return c.json({ session_key: newSignedSessionToken, sessionId: null });
|
|
10791
10899
|
});
|
|
10792
|
-
|
|
10900
|
+
app16.post("/switch", requireAdminSession, async (c) => {
|
|
10793
10901
|
const cacheKey = c.var.cacheKey;
|
|
10794
10902
|
const accountId = getAccountIdForSession(cacheKey);
|
|
10795
10903
|
const userId = getUserIdForSession(cacheKey);
|
|
@@ -10817,7 +10925,7 @@ app15.post("/switch", requireAdminSession, async (c) => {
|
|
|
10817
10925
|
console.log(`[session-switch] from=${cacheKey.slice(0, 8)} to=${targetCacheKey.slice(0, 8)} targetConvId=${targetSessionId?.slice(0, 8) ?? "none"} accountId=${accountId.slice(0, 8)}`);
|
|
10818
10926
|
return c.json({ session_key: targetSignedSessionToken, sessionId: targetSessionId });
|
|
10819
10927
|
});
|
|
10820
|
-
|
|
10928
|
+
app16.delete("/:id", requireAdminSession, async (c) => {
|
|
10821
10929
|
const sessionId = c.req.param("id");
|
|
10822
10930
|
const cacheKey = c.var.cacheKey;
|
|
10823
10931
|
const accountId = getAccountIdForSession(cacheKey);
|
|
@@ -10862,7 +10970,7 @@ app15.delete("/:id", requireAdminSession, async (c) => {
|
|
|
10862
10970
|
500
|
|
10863
10971
|
);
|
|
10864
10972
|
});
|
|
10865
|
-
|
|
10973
|
+
app16.post("/:id/resume", async (c) => {
|
|
10866
10974
|
const sessionId = c.req.param("id");
|
|
10867
10975
|
const t0 = Date.now();
|
|
10868
10976
|
const signedSessionToken = c.req.query("session_key") ?? "";
|
|
@@ -11131,7 +11239,7 @@ app15.post("/:id/resume", async (c) => {
|
|
|
11131
11239
|
}
|
|
11132
11240
|
});
|
|
11133
11241
|
});
|
|
11134
|
-
|
|
11242
|
+
app16.put("/:id/label", requireAdminSession, async (c) => {
|
|
11135
11243
|
const sessionId = c.req.param("id");
|
|
11136
11244
|
const cacheKey = c.var.cacheKey;
|
|
11137
11245
|
let body;
|
|
@@ -11157,11 +11265,11 @@ app15.put("/:id/label", requireAdminSession, async (c) => {
|
|
|
11157
11265
|
return c.json({ error: "Failed to rename session" }, 500);
|
|
11158
11266
|
}
|
|
11159
11267
|
});
|
|
11160
|
-
var sessions_default =
|
|
11268
|
+
var sessions_default = app16;
|
|
11161
11269
|
|
|
11162
11270
|
// app/lib/claude-agent/spawn-context.ts
|
|
11163
|
-
import { existsSync as
|
|
11164
|
-
import { dirname as dirname5, resolve as resolve19, join as
|
|
11271
|
+
import { existsSync as existsSync21, readFileSync as readFileSync22, readdirSync as readdirSync13, statSync as statSync10 } from "fs";
|
|
11272
|
+
import { dirname as dirname5, resolve as resolve19, join as join21 } from "path";
|
|
11165
11273
|
async function resolveOwnerProfileBlock(accountId, userId) {
|
|
11166
11274
|
if (!userId) return { ok: false, reason: "missing-user-id" };
|
|
11167
11275
|
try {
|
|
@@ -11202,14 +11310,14 @@ function frontmatterField(manifest, field2) {
|
|
|
11202
11310
|
function extractPluginToolDescriptions(pluginDir) {
|
|
11203
11311
|
const out = /* @__PURE__ */ new Map();
|
|
11204
11312
|
const candidates = [
|
|
11205
|
-
|
|
11206
|
-
|
|
11313
|
+
join21(pluginDir, "mcp/dist/index.js"),
|
|
11314
|
+
join21(pluginDir, "mcp/src/index.ts")
|
|
11207
11315
|
];
|
|
11208
11316
|
let raw = null;
|
|
11209
11317
|
for (const path2 of candidates) {
|
|
11210
|
-
if (!
|
|
11318
|
+
if (!existsSync21(path2)) continue;
|
|
11211
11319
|
try {
|
|
11212
|
-
raw =
|
|
11320
|
+
raw = readFileSync22(path2, "utf-8");
|
|
11213
11321
|
break;
|
|
11214
11322
|
} catch {
|
|
11215
11323
|
}
|
|
@@ -11259,9 +11367,9 @@ function parseSkillPathsFromFrontmatter(fm) {
|
|
|
11259
11367
|
function listPluginDirs() {
|
|
11260
11368
|
const out = /* @__PURE__ */ new Map();
|
|
11261
11369
|
const platformPlugins = resolve19(PLATFORM_ROOT, "plugins");
|
|
11262
|
-
if (
|
|
11370
|
+
if (existsSync21(platformPlugins)) {
|
|
11263
11371
|
for (const name of readdirSync13(platformPlugins)) {
|
|
11264
|
-
const dir =
|
|
11372
|
+
const dir = join21(platformPlugins, name);
|
|
11265
11373
|
try {
|
|
11266
11374
|
if (statSync10(dir).isDirectory()) out.set(name, dir);
|
|
11267
11375
|
} catch {
|
|
@@ -11269,13 +11377,13 @@ function listPluginDirs() {
|
|
|
11269
11377
|
}
|
|
11270
11378
|
}
|
|
11271
11379
|
const premiumRoot = resolve19(dirname5(PLATFORM_ROOT), "premium-plugins");
|
|
11272
|
-
if (
|
|
11380
|
+
if (existsSync21(premiumRoot)) {
|
|
11273
11381
|
for (const bundle of readdirSync13(premiumRoot)) {
|
|
11274
|
-
const bundlePlugins =
|
|
11275
|
-
if (!
|
|
11382
|
+
const bundlePlugins = join21(premiumRoot, bundle, "plugins");
|
|
11383
|
+
if (!existsSync21(bundlePlugins)) continue;
|
|
11276
11384
|
try {
|
|
11277
11385
|
for (const name of readdirSync13(bundlePlugins)) {
|
|
11278
|
-
const dir =
|
|
11386
|
+
const dir = join21(bundlePlugins, name);
|
|
11279
11387
|
try {
|
|
11280
11388
|
if (statSync10(dir).isDirectory()) out.set(name, dir);
|
|
11281
11389
|
} catch {
|
|
@@ -11289,9 +11397,9 @@ function listPluginDirs() {
|
|
|
11289
11397
|
}
|
|
11290
11398
|
function readEnabledPlugins(accountId) {
|
|
11291
11399
|
const accountFile = resolve19(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
11292
|
-
if (!
|
|
11400
|
+
if (!existsSync21(accountFile)) return /* @__PURE__ */ new Set();
|
|
11293
11401
|
try {
|
|
11294
|
-
const parsed = JSON.parse(
|
|
11402
|
+
const parsed = JSON.parse(readFileSync22(accountFile, "utf-8"));
|
|
11295
11403
|
return new Set(
|
|
11296
11404
|
Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
|
|
11297
11405
|
);
|
|
@@ -11300,10 +11408,10 @@ function readEnabledPlugins(accountId) {
|
|
|
11300
11408
|
}
|
|
11301
11409
|
}
|
|
11302
11410
|
function readFrontmatter(path2) {
|
|
11303
|
-
if (!
|
|
11411
|
+
if (!existsSync21(path2)) return null;
|
|
11304
11412
|
let raw;
|
|
11305
11413
|
try {
|
|
11306
|
-
raw =
|
|
11414
|
+
raw = readFileSync22(path2, "utf-8");
|
|
11307
11415
|
} catch {
|
|
11308
11416
|
return null;
|
|
11309
11417
|
}
|
|
@@ -11318,7 +11426,7 @@ function computeActivePlugins(accountId) {
|
|
|
11318
11426
|
for (const name of Array.from(enabled).sort()) {
|
|
11319
11427
|
const dir = pluginDirs.get(name);
|
|
11320
11428
|
if (!dir) continue;
|
|
11321
|
-
const fm = readFrontmatter(
|
|
11429
|
+
const fm = readFrontmatter(join21(dir, "PLUGIN.md"));
|
|
11322
11430
|
if (!fm) continue;
|
|
11323
11431
|
const description = frontmatterField(`---
|
|
11324
11432
|
${fm}
|
|
@@ -11335,7 +11443,7 @@ ${fm}
|
|
|
11335
11443
|
`plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
|
|
11336
11444
|
);
|
|
11337
11445
|
if (toolNames.length > 0 && descMap.size === 0) {
|
|
11338
|
-
const hasSource =
|
|
11446
|
+
const hasSource = existsSync21(join21(dir, "mcp/dist/index.js")) || existsSync21(join21(dir, "mcp/src/index.ts"));
|
|
11339
11447
|
if (hasSource) {
|
|
11340
11448
|
console.warn(
|
|
11341
11449
|
`[spawn-context] WARN plugin=${name} mcp source present but tool-description regex matched zero entries \u2014 SDK upgrade may have changed the registration shape`
|
|
@@ -11345,7 +11453,7 @@ ${fm}
|
|
|
11345
11453
|
const skillPaths = parseSkillPathsFromFrontmatter(fm);
|
|
11346
11454
|
const skills = [];
|
|
11347
11455
|
for (const relPath of skillPaths) {
|
|
11348
|
-
const skillPath =
|
|
11456
|
+
const skillPath = join21(dir, relPath);
|
|
11349
11457
|
const skillFm = readFrontmatter(skillPath);
|
|
11350
11458
|
if (!skillFm) continue;
|
|
11351
11459
|
const skillName = frontmatterField(`---
|
|
@@ -11362,7 +11470,7 @@ ${skillFm}
|
|
|
11362
11470
|
}
|
|
11363
11471
|
function computeSpecialistDomains(accountId) {
|
|
11364
11472
|
const specialistsDir = resolve19(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
|
|
11365
|
-
if (!
|
|
11473
|
+
if (!existsSync21(specialistsDir)) return [];
|
|
11366
11474
|
let entries;
|
|
11367
11475
|
try {
|
|
11368
11476
|
entries = readdirSync13(specialistsDir);
|
|
@@ -11389,7 +11497,7 @@ function computeSpecialistDomains(accountId) {
|
|
|
11389
11497
|
const out = [];
|
|
11390
11498
|
for (const file of entries.sort()) {
|
|
11391
11499
|
if (!file.endsWith(".md")) continue;
|
|
11392
|
-
const fm = readFrontmatter(
|
|
11500
|
+
const fm = readFrontmatter(join21(specialistsDir, file));
|
|
11393
11501
|
if (!fm) continue;
|
|
11394
11502
|
const wrapped = `---
|
|
11395
11503
|
${fm}
|
|
@@ -11408,10 +11516,10 @@ ${fm}
|
|
|
11408
11516
|
}
|
|
11409
11517
|
function computeDormantPlugins(accountId) {
|
|
11410
11518
|
const accountFile = resolve19(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
11411
|
-
if (!
|
|
11519
|
+
if (!existsSync21(accountFile)) return [];
|
|
11412
11520
|
let enabled;
|
|
11413
11521
|
try {
|
|
11414
|
-
const raw =
|
|
11522
|
+
const raw = readFileSync22(accountFile, "utf-8");
|
|
11415
11523
|
const parsed = JSON.parse(raw);
|
|
11416
11524
|
enabled = new Set(
|
|
11417
11525
|
Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
|
|
@@ -11423,7 +11531,7 @@ function computeDormantPlugins(accountId) {
|
|
|
11423
11531
|
return [];
|
|
11424
11532
|
}
|
|
11425
11533
|
const pluginsDir = resolve19(PLATFORM_ROOT, "plugins");
|
|
11426
|
-
if (!
|
|
11534
|
+
if (!existsSync21(pluginsDir)) return [];
|
|
11427
11535
|
let entries;
|
|
11428
11536
|
try {
|
|
11429
11537
|
entries = readdirSync13(pluginsDir);
|
|
@@ -11434,10 +11542,10 @@ function computeDormantPlugins(accountId) {
|
|
|
11434
11542
|
for (const name of entries) {
|
|
11435
11543
|
if (enabled.has(name)) continue;
|
|
11436
11544
|
const manifestPath = resolve19(pluginsDir, name, "PLUGIN.md");
|
|
11437
|
-
if (!
|
|
11545
|
+
if (!existsSync21(manifestPath)) continue;
|
|
11438
11546
|
let manifest;
|
|
11439
11547
|
try {
|
|
11440
|
-
manifest =
|
|
11548
|
+
manifest = readFileSync22(manifestPath, "utf-8");
|
|
11441
11549
|
} catch {
|
|
11442
11550
|
continue;
|
|
11443
11551
|
}
|
|
@@ -11451,13 +11559,13 @@ function computeDormantPlugins(accountId) {
|
|
|
11451
11559
|
}
|
|
11452
11560
|
|
|
11453
11561
|
// server/routes/admin/claude-sessions.ts
|
|
11454
|
-
import { existsSync as
|
|
11562
|
+
import { existsSync as existsSync22, readFileSync as readFileSync23 } from "fs";
|
|
11455
11563
|
import { resolve as resolve20 } from "path";
|
|
11456
11564
|
function readTunnelState(brandConfigDir) {
|
|
11457
11565
|
const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
|
|
11458
|
-
if (!
|
|
11566
|
+
if (!existsSync22(statePath)) return null;
|
|
11459
11567
|
try {
|
|
11460
|
-
const parsed = JSON.parse(
|
|
11568
|
+
const parsed = JSON.parse(readFileSync23(statePath, "utf-8"));
|
|
11461
11569
|
const tunnelId = typeof parsed.tunnelId === "string" ? parsed.tunnelId : null;
|
|
11462
11570
|
const tunnelName = typeof parsed.tunnelName === "string" ? parsed.tunnelName : null;
|
|
11463
11571
|
const domain = typeof parsed.domain === "string" ? parsed.domain : null;
|
|
@@ -11471,7 +11579,7 @@ function resolveTunnelUrl() {
|
|
|
11471
11579
|
const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve20(process.cwd(), "..");
|
|
11472
11580
|
let brand;
|
|
11473
11581
|
try {
|
|
11474
|
-
brand = JSON.parse(
|
|
11582
|
+
brand = JSON.parse(readFileSync23(resolve20(platformRoot2, "config", "brand.json"), "utf-8"));
|
|
11475
11583
|
} catch {
|
|
11476
11584
|
return null;
|
|
11477
11585
|
}
|
|
@@ -11482,7 +11590,7 @@ function resolveTunnelUrl() {
|
|
|
11482
11590
|
if (!state) return null;
|
|
11483
11591
|
return `https://${hostname2}.${state.domain}`;
|
|
11484
11592
|
}
|
|
11485
|
-
var
|
|
11593
|
+
var TAG25 = "[claude-session-manager:wrapper]";
|
|
11486
11594
|
async function refuseIfClaudeAuthDead(c, route, sessionId) {
|
|
11487
11595
|
const auth = await ensureAuth();
|
|
11488
11596
|
if (auth.status !== "dead" && auth.status !== "missing") return null;
|
|
@@ -11494,18 +11602,18 @@ async function refuseIfClaudeAuthDead(c, route, sessionId) {
|
|
|
11494
11602
|
503
|
|
11495
11603
|
);
|
|
11496
11604
|
}
|
|
11497
|
-
var
|
|
11605
|
+
var app17 = new Hono();
|
|
11498
11606
|
async function performSpawnWithInitialMessage(args) {
|
|
11499
11607
|
const ownerStart = Date.now();
|
|
11500
11608
|
const aboutOwner = await resolveOwnerProfileBlock(args.senderId, args.userId);
|
|
11501
11609
|
const ownerMs = Date.now() - ownerStart;
|
|
11502
11610
|
const aboutOwnerStatus = aboutOwner == null ? "absent" : "ok" in aboutOwner && aboutOwner.ok === false ? `unresolved:${aboutOwner.reason}` : "ok";
|
|
11503
|
-
console.log(`${
|
|
11611
|
+
console.log(`${TAG25} about-owner-resolved status=${aboutOwnerStatus} ms=${ownerMs}`);
|
|
11504
11612
|
const dormantPlugins = computeDormantPlugins(args.senderId);
|
|
11505
11613
|
const activePlugins = computeActivePlugins(args.senderId);
|
|
11506
11614
|
const specialistDomains = computeSpecialistDomains(args.senderId);
|
|
11507
11615
|
const tunnelUrl = resolveTunnelUrl();
|
|
11508
|
-
console.log(`${
|
|
11616
|
+
console.log(`${TAG25} tunnel-url-resolved value=${tunnelUrl ?? "null"}`);
|
|
11509
11617
|
const upstreamPayload = JSON.stringify({
|
|
11510
11618
|
senderId: args.senderId,
|
|
11511
11619
|
// Task 205 — pass userId through to the manager so it lands as
|
|
@@ -11532,24 +11640,24 @@ async function performSpawnWithInitialMessage(args) {
|
|
|
11532
11640
|
// unshapely values.
|
|
11533
11641
|
conversationNodeId: args.conversationNodeId
|
|
11534
11642
|
});
|
|
11535
|
-
console.log(`${
|
|
11643
|
+
console.log(`${TAG25} forward-spawn-start managerBase=${managerBase("claude-session-manager:wrapper")} bytes=${upstreamPayload.length} hidden=${args.hidden} specialist=${args.specialist ?? "none"}`);
|
|
11536
11644
|
const forwardStart = Date.now();
|
|
11537
11645
|
const upstream = await fetch(`${managerBase("claude-session-manager:wrapper")}/public-spawn`, {
|
|
11538
11646
|
method: "POST",
|
|
11539
11647
|
headers: { "content-type": "application/json" },
|
|
11540
11648
|
body: upstreamPayload
|
|
11541
11649
|
}).catch((err) => {
|
|
11542
|
-
console.error(`${
|
|
11650
|
+
console.error(`${TAG25} fetch-failed op=spawn message=${err instanceof Error ? err.message : String(err)} ms=${Date.now() - forwardStart}`);
|
|
11543
11651
|
return null;
|
|
11544
11652
|
});
|
|
11545
11653
|
if (!upstream) return {
|
|
11546
11654
|
response: new Response(JSON.stringify({ error: "manager-unreachable" }), { status: 503, headers: { "content-type": "application/json" } }),
|
|
11547
11655
|
claudeSessionId: null
|
|
11548
11656
|
};
|
|
11549
|
-
console.log(`${
|
|
11657
|
+
console.log(`${TAG25} forward-spawn-done status=${upstream.status} ms=${Date.now() - forwardStart}`);
|
|
11550
11658
|
if (args.initialMessage) {
|
|
11551
11659
|
const inputBytes = Buffer.byteLength(args.initialMessage, "utf8");
|
|
11552
|
-
console.log(`${
|
|
11660
|
+
console.log(`${TAG25} initial-message-inlined bytes=${inputBytes}`);
|
|
11553
11661
|
}
|
|
11554
11662
|
const bodyText = await upstream.text().catch(() => "");
|
|
11555
11663
|
let claudeSessionId = null;
|
|
@@ -11571,8 +11679,8 @@ function mintTranscriptEdge(sessionId, claudeSessionId, accountId) {
|
|
|
11571
11679
|
if (!sessionId || !claudeSessionId) return;
|
|
11572
11680
|
void linkConversationTranscript(sessionId, claudeSessionId, accountId);
|
|
11573
11681
|
}
|
|
11574
|
-
|
|
11575
|
-
|
|
11682
|
+
app17.use("*", requireAdminSession);
|
|
11683
|
+
app17.post("/", async (c) => {
|
|
11576
11684
|
const routeStart = Date.now();
|
|
11577
11685
|
const cacheKey = c.get("cacheKey") ?? "";
|
|
11578
11686
|
let body = {};
|
|
@@ -11584,7 +11692,7 @@ app16.post("/", async (c) => {
|
|
|
11584
11692
|
if (refusal) return refusal;
|
|
11585
11693
|
const senderId = getAccountIdForSession(cacheKey) ?? "";
|
|
11586
11694
|
if (!senderId) {
|
|
11587
|
-
console.error(`${
|
|
11695
|
+
console.error(`${TAG25} reject reason=no-account-id cacheKey-prefix=${cacheKey.slice(0, 8)}`);
|
|
11588
11696
|
return c.json({ error: "admin-account-not-resolved" }, 500);
|
|
11589
11697
|
}
|
|
11590
11698
|
const userId = getUserIdForSession(cacheKey) ?? void 0;
|
|
@@ -11593,7 +11701,7 @@ app16.post("/", async (c) => {
|
|
|
11593
11701
|
const permissionMode = typeof body.permissionMode === "string" ? body.permissionMode : void 0;
|
|
11594
11702
|
const specialist = typeof body.specialist === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(body.specialist) ? body.specialist : void 0;
|
|
11595
11703
|
const model = typeof body.model === "string" && /^[A-Za-z0-9._-]{1,64}$/.test(body.model) ? body.model : void 0;
|
|
11596
|
-
console.log(`${
|
|
11704
|
+
console.log(`${TAG25} spawn-request-in surface=cookie accountId=${senderId.slice(0, 8)} userId=${userId ? userId.slice(0, 8) : "absent"} channel=${channel} permissionMode=${permissionMode ?? "default"} specialist=${specialist ?? "none"} model=${model ?? "default"} initialMessage=${initialMessage ? "yes" : "no"}`);
|
|
11597
11705
|
const conversationNodeId = cacheKey ? getSessionIdForSession(cacheKey) : void 0;
|
|
11598
11706
|
const { response, claudeSessionId } = await performSpawnWithInitialMessage({
|
|
11599
11707
|
senderId,
|
|
@@ -11612,24 +11720,24 @@ app16.post("/", async (c) => {
|
|
|
11612
11720
|
claudeSessionId,
|
|
11613
11721
|
senderId
|
|
11614
11722
|
);
|
|
11615
|
-
console.log(`${
|
|
11723
|
+
console.log(`${TAG25} route-done surface=cookie status=${response.status} route-ms=${Date.now() - routeStart}`);
|
|
11616
11724
|
return response;
|
|
11617
11725
|
});
|
|
11618
|
-
var claude_sessions_default =
|
|
11726
|
+
var claude_sessions_default = app17;
|
|
11619
11727
|
|
|
11620
11728
|
// server/routes/admin/log-ingest.ts
|
|
11621
|
-
var
|
|
11729
|
+
var TAG26 = "[log-ingest]";
|
|
11622
11730
|
var TAG_PATTERN = /^[A-Za-z0-9_:-]{1,32}$/;
|
|
11623
11731
|
var LEVELS = /* @__PURE__ */ new Set(["debug", "info", "warn", "error"]);
|
|
11624
11732
|
var MAX_LINE_BYTES = 4096;
|
|
11625
|
-
var
|
|
11733
|
+
var app18 = new Hono();
|
|
11626
11734
|
function isLoopbackAddr(addr) {
|
|
11627
11735
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
11628
11736
|
}
|
|
11629
|
-
|
|
11737
|
+
app18.post("/", async (c) => {
|
|
11630
11738
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
11631
11739
|
if (!isLoopbackAddr(remoteAddr)) {
|
|
11632
|
-
console.error(`${
|
|
11740
|
+
console.error(`${TAG26} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
11633
11741
|
return c.json({ error: "log-ingest-loopback-only" }, 403);
|
|
11634
11742
|
}
|
|
11635
11743
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -11638,7 +11746,7 @@ app17.post("/", async (c) => {
|
|
|
11638
11746
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
11639
11747
|
const offender = tokens.find((t) => !isLoopbackAddr(t));
|
|
11640
11748
|
if (offender !== void 0) {
|
|
11641
|
-
console.error(`${
|
|
11749
|
+
console.error(`${TAG26} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
11642
11750
|
return c.json({ error: "log-ingest-loopback-only" }, 403);
|
|
11643
11751
|
}
|
|
11644
11752
|
}
|
|
@@ -11669,7 +11777,7 @@ app17.post("/", async (c) => {
|
|
|
11669
11777
|
else console.log(formatted);
|
|
11670
11778
|
return c.json({ ok: true }, 200);
|
|
11671
11779
|
});
|
|
11672
|
-
var log_ingest_default =
|
|
11780
|
+
var log_ingest_default = app18;
|
|
11673
11781
|
|
|
11674
11782
|
// server/routes/admin/events.ts
|
|
11675
11783
|
var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
@@ -11678,20 +11786,20 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
|
11678
11786
|
"device-url:vnc-surface-shown",
|
|
11679
11787
|
"device-url:malformed"
|
|
11680
11788
|
]);
|
|
11681
|
-
var
|
|
11682
|
-
|
|
11683
|
-
const
|
|
11789
|
+
var app19 = new Hono();
|
|
11790
|
+
app19.post("/", async (c) => {
|
|
11791
|
+
const TAG35 = "[admin:events]";
|
|
11684
11792
|
let body;
|
|
11685
11793
|
try {
|
|
11686
11794
|
body = await c.req.json();
|
|
11687
11795
|
} catch (err) {
|
|
11688
11796
|
const detail = err instanceof Error ? err.message : String(err);
|
|
11689
|
-
console.error(`${
|
|
11797
|
+
console.error(`${TAG35} reject reason=body-not-json detail=${detail}`);
|
|
11690
11798
|
return c.json({ ok: false, detail: "Request body was not valid JSON" }, 400);
|
|
11691
11799
|
}
|
|
11692
11800
|
const event = typeof body.event === "string" ? body.event : "";
|
|
11693
11801
|
if (!ALLOWED_EVENTS.has(event)) {
|
|
11694
|
-
console.error(`${
|
|
11802
|
+
console.error(`${TAG35} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
|
|
11695
11803
|
return c.json({ ok: false, detail: `Event "${event}" is not allowed` }, 400);
|
|
11696
11804
|
}
|
|
11697
11805
|
const rawFields = body.fields && typeof body.fields === "object" ? body.fields : {};
|
|
@@ -11710,14 +11818,14 @@ app18.post("/", async (c) => {
|
|
|
11710
11818
|
console.error(`[${event}] ${formatted}`);
|
|
11711
11819
|
return c.json({ ok: true });
|
|
11712
11820
|
});
|
|
11713
|
-
var events_default =
|
|
11821
|
+
var events_default = app19;
|
|
11714
11822
|
|
|
11715
11823
|
// server/routes/admin/files.ts
|
|
11716
|
-
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as
|
|
11824
|
+
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as existsSync23 } from "fs";
|
|
11717
11825
|
import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, unlink as unlink2, rename } from "fs/promises";
|
|
11718
11826
|
import { realpathSync as realpathSync4 } from "fs";
|
|
11719
11827
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
11720
|
-
import { basename as basename7, dirname as dirname6, join as
|
|
11828
|
+
import { basename as basename7, dirname as dirname6, join as join23, resolve as resolve22, sep as sep6 } from "path";
|
|
11721
11829
|
import { Readable as Readable2 } from "stream";
|
|
11722
11830
|
|
|
11723
11831
|
// ../lib/graph-trash/src/index.ts
|
|
@@ -12035,7 +12143,7 @@ async function cascadeDeleteDocument(params) {
|
|
|
12035
12143
|
|
|
12036
12144
|
// app/lib/file-index.ts
|
|
12037
12145
|
import * as fsp from "fs/promises";
|
|
12038
|
-
import { resolve as resolve21, relative as relative2, join as
|
|
12146
|
+
import { resolve as resolve21, relative as relative2, join as join22, basename as basename6, extname as extname2, sep as sep5 } from "path";
|
|
12039
12147
|
import { tmpdir as tmpdir2 } from "os";
|
|
12040
12148
|
import { execFile as execFile2 } from "child_process";
|
|
12041
12149
|
import { promisify as promisify2 } from "util";
|
|
@@ -12117,7 +12225,7 @@ async function extractPdf(absolute) {
|
|
|
12117
12225
|
return stdout.trim();
|
|
12118
12226
|
}
|
|
12119
12227
|
async function ocrPdf(absolute) {
|
|
12120
|
-
const outPdf =
|
|
12228
|
+
const outPdf = join22(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
|
|
12121
12229
|
try {
|
|
12122
12230
|
await execFileAsync2(
|
|
12123
12231
|
"ocrmypdf",
|
|
@@ -12179,7 +12287,7 @@ async function readDisplayName(absolute) {
|
|
|
12179
12287
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
12180
12288
|
if (base === `${stem}.meta.json`) return null;
|
|
12181
12289
|
try {
|
|
12182
|
-
const raw = await fsp.readFile(
|
|
12290
|
+
const raw = await fsp.readFile(join22(dir, `${stem}.meta.json`), "utf-8");
|
|
12183
12291
|
const meta = JSON.parse(raw);
|
|
12184
12292
|
const dn = meta.displayName ?? meta.filename;
|
|
12185
12293
|
return typeof dn === "string" && dn.length > 0 ? dn : null;
|
|
@@ -12200,7 +12308,7 @@ async function walkSubtree(root, dataRoot, out) {
|
|
|
12200
12308
|
for (const entry of entries) {
|
|
12201
12309
|
if (entry.isSymbolicLink()) continue;
|
|
12202
12310
|
if (entry.isDirectory() && entry.name === ".uploads-tmp") continue;
|
|
12203
|
-
const abs =
|
|
12311
|
+
const abs = join22(root, entry.name);
|
|
12204
12312
|
if (entry.isDirectory()) {
|
|
12205
12313
|
const sub = await walkSubtree(abs, dataRoot, out);
|
|
12206
12314
|
if (!sub.clean) clean = false;
|
|
@@ -12473,7 +12581,7 @@ var UPLOAD_TMP_DIR = ".uploads-tmp";
|
|
|
12473
12581
|
var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
12474
12582
|
async function readMeta(absDir, baseName) {
|
|
12475
12583
|
try {
|
|
12476
|
-
const raw = await readFile4(
|
|
12584
|
+
const raw = await readFile4(join23(absDir, `${baseName}.meta.json`), "utf8");
|
|
12477
12585
|
const parsed = JSON.parse(raw);
|
|
12478
12586
|
if (typeof parsed?.filename === "string") {
|
|
12479
12587
|
return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
|
|
@@ -12511,7 +12619,7 @@ async function readAccountNames() {
|
|
|
12511
12619
|
}
|
|
12512
12620
|
async function enrich(absolute, entry, accountNames) {
|
|
12513
12621
|
if (entry.kind === "directory" && UUID_RE3.test(entry.name)) {
|
|
12514
|
-
const meta = await readMeta(
|
|
12622
|
+
const meta = await readMeta(join23(absolute, entry.name), entry.name);
|
|
12515
12623
|
if (meta?.filename) {
|
|
12516
12624
|
entry.displayName = meta.filename;
|
|
12517
12625
|
entry.mimeType = meta.mimeType;
|
|
@@ -12635,8 +12743,8 @@ async function knowledgeDocOwnedByAccount(accountId, attachmentId) {
|
|
|
12635
12743
|
await session.close();
|
|
12636
12744
|
}
|
|
12637
12745
|
}
|
|
12638
|
-
var
|
|
12639
|
-
|
|
12746
|
+
var app20 = new Hono();
|
|
12747
|
+
app20.get("/", requireAdminSession, async (c) => {
|
|
12640
12748
|
const cacheKey = c.var.cacheKey;
|
|
12641
12749
|
const accountId = getAccountIdForSession(cacheKey);
|
|
12642
12750
|
if (!accountId) {
|
|
@@ -12675,7 +12783,7 @@ app19.get("/", requireAdminSession, async (c) => {
|
|
|
12675
12783
|
const childRel = relPath === "" || relPath === "." ? name : `${relPath}/${name}`;
|
|
12676
12784
|
const protectedEntry = isProtectedFromDeletion(childRel).protected;
|
|
12677
12785
|
try {
|
|
12678
|
-
const entryPath =
|
|
12786
|
+
const entryPath = join23(absolute, name);
|
|
12679
12787
|
const s = await stat4(entryPath);
|
|
12680
12788
|
entries.push({
|
|
12681
12789
|
name,
|
|
@@ -12705,7 +12813,7 @@ app19.get("/", requireAdminSession, async (c) => {
|
|
|
12705
12813
|
return c.json({ error: message }, 500);
|
|
12706
12814
|
}
|
|
12707
12815
|
});
|
|
12708
|
-
|
|
12816
|
+
app20.get("/download", requireAdminSession, async (c) => {
|
|
12709
12817
|
const cacheKey = c.var.cacheKey;
|
|
12710
12818
|
const accountId = getAccountIdForSession(cacheKey);
|
|
12711
12819
|
if (!accountId) {
|
|
@@ -12773,7 +12881,7 @@ function dataUploadCeiling() {
|
|
|
12773
12881
|
const override = Number(process.env.MAXY_DATA_UPLOAD_MAX_BYTES);
|
|
12774
12882
|
return Number.isFinite(override) && override > 0 ? override : MAX_DATA_UPLOAD_BYTES;
|
|
12775
12883
|
}
|
|
12776
|
-
|
|
12884
|
+
app20.post("/upload", requireAdminSession, async (c) => {
|
|
12777
12885
|
const cacheKey = c.var.cacheKey;
|
|
12778
12886
|
const accountId = getAccountIdForSession(cacheKey);
|
|
12779
12887
|
if (!accountId) {
|
|
@@ -12800,7 +12908,7 @@ app19.post("/upload", requireAdminSession, async (c) => {
|
|
|
12800
12908
|
const base = resolveOwnAccountWrite(rawDir, accountId, "POST /api/admin/files/upload");
|
|
12801
12909
|
if (!base.ok) return c.json({ error: base.error }, base.status);
|
|
12802
12910
|
const relDir = relpath ? dirname6(relpath) : ".";
|
|
12803
|
-
const destRel = relDir === "." ? base.relative :
|
|
12911
|
+
const destRel = relDir === "." ? base.relative : join23(base.relative, relDir);
|
|
12804
12912
|
if (crossesForeignAccountPartition(destRel, accountId)) {
|
|
12805
12913
|
console.error(`[data] account-scope-blocked endpoint="POST /api/admin/files/upload" path="${destRel}" account=${accountId.slice(0, 8)}\u2026`);
|
|
12806
12914
|
return c.json({ error: "Not found" }, 404);
|
|
@@ -12848,7 +12956,7 @@ app19.post("/upload", requireAdminSession, async (c) => {
|
|
|
12848
12956
|
});
|
|
12849
12957
|
await unlink2(tmpPath).catch(() => {
|
|
12850
12958
|
});
|
|
12851
|
-
const tempRemoved = !
|
|
12959
|
+
const tempRemoved = !existsSync23(tmpPath);
|
|
12852
12960
|
console.error(`[data-upload] op=cleanup uid=${uid} tempRemoved=${tempRemoved}`);
|
|
12853
12961
|
};
|
|
12854
12962
|
const reader = body.getReader();
|
|
@@ -12940,7 +13048,7 @@ async function sweepStaleUploadTemps() {
|
|
|
12940
13048
|
if (removed > 0) console.error(`[data-upload] op=sweep removed=${removed}`);
|
|
12941
13049
|
return removed;
|
|
12942
13050
|
}
|
|
12943
|
-
|
|
13051
|
+
app20.delete("/", requireAdminSession, async (c) => {
|
|
12944
13052
|
const cacheKey = c.var.cacheKey;
|
|
12945
13053
|
const accountId = getAccountIdForSession(cacheKey);
|
|
12946
13054
|
if (!accountId) {
|
|
@@ -12977,7 +13085,7 @@ app19.delete("/", requireAdminSession, async (c) => {
|
|
|
12977
13085
|
}
|
|
12978
13086
|
const dot = base.lastIndexOf(".");
|
|
12979
13087
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
12980
|
-
const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ?
|
|
13088
|
+
const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join23(dirname6(absolute), `${stem}.meta.json`) : null;
|
|
12981
13089
|
await unlink2(absolute);
|
|
12982
13090
|
if (sidecarPath) {
|
|
12983
13091
|
try {
|
|
@@ -13016,7 +13124,7 @@ app19.delete("/", requireAdminSession, async (c) => {
|
|
|
13016
13124
|
return c.json({ error: message }, 500);
|
|
13017
13125
|
}
|
|
13018
13126
|
});
|
|
13019
|
-
|
|
13127
|
+
app20.post("/folder", requireAdminSession, async (c) => {
|
|
13020
13128
|
const cacheKey = c.var.cacheKey;
|
|
13021
13129
|
const accountId = getAccountIdForSession(cacheKey);
|
|
13022
13130
|
if (!accountId) {
|
|
@@ -13051,7 +13159,7 @@ app19.post("/folder", requireAdminSession, async (c) => {
|
|
|
13051
13159
|
console.error(`[data] folder-create path="${newRel}"`);
|
|
13052
13160
|
return c.json({ path: newRel });
|
|
13053
13161
|
});
|
|
13054
|
-
|
|
13162
|
+
app20.post("/rename", requireAdminSession, async (c) => {
|
|
13055
13163
|
const cacheKey = c.var.cacheKey;
|
|
13056
13164
|
const accountId = getAccountIdForSession(cacheKey);
|
|
13057
13165
|
if (!accountId) {
|
|
@@ -13101,7 +13209,7 @@ app19.post("/rename", requireAdminSession, async (c) => {
|
|
|
13101
13209
|
});
|
|
13102
13210
|
return c.json({ path: newRel });
|
|
13103
13211
|
});
|
|
13104
|
-
var files_default =
|
|
13212
|
+
var files_default = app20;
|
|
13105
13213
|
|
|
13106
13214
|
// ../lib/graph-search/src/index.ts
|
|
13107
13215
|
var import_dist = __toESM(require_dist());
|
|
@@ -13866,8 +13974,8 @@ var DEFAULT_LIMIT = 20;
|
|
|
13866
13974
|
var MAX_LIMIT = 2e3;
|
|
13867
13975
|
var MESSAGE_FAMILY_LABELS = ["Message", "UserMessage", "AssistantMessage", "WhatsAppMessage"];
|
|
13868
13976
|
var CONVERSATION_PARENT_LABELS = /* @__PURE__ */ new Set(["AdminConversation", "PublicConversation"]);
|
|
13869
|
-
var
|
|
13870
|
-
|
|
13977
|
+
var app21 = new Hono();
|
|
13978
|
+
app21.get("/", requireAdminSession, async (c) => {
|
|
13871
13979
|
const cacheKey = c.var.cacheKey;
|
|
13872
13980
|
const q = (c.req.query("q") ?? "").trim();
|
|
13873
13981
|
const rawLimit = c.req.query("limit");
|
|
@@ -14003,7 +14111,7 @@ app20.get("/", requireAdminSession, async (c) => {
|
|
|
14003
14111
|
await session.close();
|
|
14004
14112
|
}
|
|
14005
14113
|
});
|
|
14006
|
-
var graph_search_default =
|
|
14114
|
+
var graph_search_default = app21;
|
|
14007
14115
|
|
|
14008
14116
|
// server/routes/admin/graph-subgraph.ts
|
|
14009
14117
|
import neo4j2 from "neo4j-driver";
|
|
@@ -14087,8 +14195,8 @@ var STRIPPED_PROPERTIES = /* @__PURE__ */ new Set([
|
|
|
14087
14195
|
"otpCode",
|
|
14088
14196
|
"cacheKey"
|
|
14089
14197
|
]);
|
|
14090
|
-
var
|
|
14091
|
-
|
|
14198
|
+
var app22 = new Hono();
|
|
14199
|
+
app22.get("/", requireAdminSession, async (c) => {
|
|
14092
14200
|
const cacheKey = c.var.cacheKey;
|
|
14093
14201
|
const accountId = getAccountIdForSession(cacheKey);
|
|
14094
14202
|
if (!accountId) {
|
|
@@ -14671,12 +14779,12 @@ function pruneNode(node, warnedClasses, conversationWarnings) {
|
|
|
14671
14779
|
}
|
|
14672
14780
|
return trashed ? { id: node.id, labels, properties, trashed: true } : { id: node.id, labels, properties };
|
|
14673
14781
|
}
|
|
14674
|
-
var graph_subgraph_default =
|
|
14782
|
+
var graph_subgraph_default = app22;
|
|
14675
14783
|
|
|
14676
14784
|
// server/routes/admin/graph-delete.ts
|
|
14677
14785
|
var ALLOWED_BY = ["graph-page", "graph-drag-trash", "graph-side-panel-trash"];
|
|
14678
|
-
var
|
|
14679
|
-
|
|
14786
|
+
var app23 = new Hono();
|
|
14787
|
+
app23.post("/", requireAdminSession, async (c) => {
|
|
14680
14788
|
const cacheKey = c.var.cacheKey;
|
|
14681
14789
|
const accountId = getAccountIdForSession(cacheKey);
|
|
14682
14790
|
if (!accountId) {
|
|
@@ -14838,11 +14946,11 @@ app22.post("/", requireAdminSession, async (c) => {
|
|
|
14838
14946
|
}
|
|
14839
14947
|
}
|
|
14840
14948
|
});
|
|
14841
|
-
var graph_delete_default =
|
|
14949
|
+
var graph_delete_default = app23;
|
|
14842
14950
|
|
|
14843
14951
|
// server/routes/admin/graph-restore.ts
|
|
14844
|
-
var
|
|
14845
|
-
|
|
14952
|
+
var app24 = new Hono();
|
|
14953
|
+
app24.post("/", requireAdminSession, async (c) => {
|
|
14846
14954
|
const cacheKey = c.var.cacheKey;
|
|
14847
14955
|
const accountId = getAccountIdForSession(cacheKey);
|
|
14848
14956
|
if (!accountId) {
|
|
@@ -14906,11 +15014,11 @@ app23.post("/", requireAdminSession, async (c) => {
|
|
|
14906
15014
|
}
|
|
14907
15015
|
}
|
|
14908
15016
|
});
|
|
14909
|
-
var graph_restore_default =
|
|
15017
|
+
var graph_restore_default = app24;
|
|
14910
15018
|
|
|
14911
15019
|
// server/routes/admin/graph-labels-in-graph.ts
|
|
14912
|
-
var
|
|
14913
|
-
|
|
15020
|
+
var app25 = new Hono();
|
|
15021
|
+
app25.get("/", requireAdminSession, async (c) => {
|
|
14914
15022
|
const cacheKey = c.var.cacheKey;
|
|
14915
15023
|
const accountId = getAccountIdForSession(cacheKey);
|
|
14916
15024
|
if (!accountId) {
|
|
@@ -14976,11 +15084,11 @@ var LABELS_IN_GRAPH_CYPHER = `
|
|
|
14976
15084
|
sum(halfEdges) AS relDegree
|
|
14977
15085
|
RETURN label, nodeCount, relDegree
|
|
14978
15086
|
`;
|
|
14979
|
-
var graph_labels_in_graph_default =
|
|
15087
|
+
var graph_labels_in_graph_default = app25;
|
|
14980
15088
|
|
|
14981
15089
|
// server/routes/admin/graph-default-view.ts
|
|
14982
|
-
var
|
|
14983
|
-
|
|
15090
|
+
var app26 = new Hono();
|
|
15091
|
+
app26.get("/", requireAdminSession, async (c) => {
|
|
14984
15092
|
const cacheKey = c.var.cacheKey;
|
|
14985
15093
|
const accountId = getAccountIdForSession(cacheKey);
|
|
14986
15094
|
const userId = getUserIdForSession(cacheKey);
|
|
@@ -15018,7 +15126,7 @@ app25.get("/", requireAdminSession, async (c) => {
|
|
|
15018
15126
|
}
|
|
15019
15127
|
}
|
|
15020
15128
|
});
|
|
15021
|
-
|
|
15129
|
+
app26.put("/", requireAdminSession, async (c) => {
|
|
15022
15130
|
const cacheKey = c.var.cacheKey;
|
|
15023
15131
|
const accountId = getAccountIdForSession(cacheKey);
|
|
15024
15132
|
const userId = getUserIdForSession(cacheKey);
|
|
@@ -15107,20 +15215,20 @@ var WRITE_CYPHER = `
|
|
|
15107
15215
|
p.updatedAt = $updatedAt
|
|
15108
15216
|
RETURN p.labels AS labels
|
|
15109
15217
|
`;
|
|
15110
|
-
var graph_default_view_default =
|
|
15218
|
+
var graph_default_view_default = app26;
|
|
15111
15219
|
|
|
15112
15220
|
// server/routes/admin/sidebar-artefacts.ts
|
|
15113
15221
|
import { readdir as readdir4, stat as stat5 } from "fs/promises";
|
|
15114
15222
|
import { resolve as resolve23, relative as relative3, isAbsolute, sep as sep7, basename as basename8 } from "path";
|
|
15115
|
-
import { existsSync as
|
|
15223
|
+
import { existsSync as existsSync24 } from "fs";
|
|
15116
15224
|
var LIMIT = 50;
|
|
15117
15225
|
var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
|
|
15118
15226
|
function toDataRootRelPath(absPath) {
|
|
15119
15227
|
if (absPath !== DATA_ROOT && !absPath.startsWith(DATA_ROOT + sep7)) return null;
|
|
15120
15228
|
return relative3(DATA_ROOT, absPath);
|
|
15121
15229
|
}
|
|
15122
|
-
var
|
|
15123
|
-
|
|
15230
|
+
var app27 = new Hono();
|
|
15231
|
+
app27.get("/", requireAdminSession, async (c) => {
|
|
15124
15232
|
const cacheKey = c.var.cacheKey;
|
|
15125
15233
|
const accountId = getAccountIdForSession(cacheKey);
|
|
15126
15234
|
if (!accountId) {
|
|
@@ -15219,7 +15327,7 @@ async function fetchAgentTemplateRows(accountDir) {
|
|
|
15219
15327
|
async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
15220
15328
|
const names = /* @__PURE__ */ new Set();
|
|
15221
15329
|
for (const dir of [overrideDir, bundledDir]) {
|
|
15222
|
-
if (!
|
|
15330
|
+
if (!existsSync24(dir)) continue;
|
|
15223
15331
|
try {
|
|
15224
15332
|
const entries = await readdir4(dir);
|
|
15225
15333
|
for (const entry of entries) {
|
|
@@ -15234,7 +15342,7 @@ async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
|
15234
15342
|
}
|
|
15235
15343
|
async function readAgentTemplateRow(inp) {
|
|
15236
15344
|
let chosenPath = null;
|
|
15237
|
-
if (
|
|
15345
|
+
if (existsSync24(inp.overridePath)) {
|
|
15238
15346
|
try {
|
|
15239
15347
|
validateFilePathInAccount(inp.overridePath, inp.overrideRoot);
|
|
15240
15348
|
chosenPath = inp.overridePath;
|
|
@@ -15245,7 +15353,7 @@ async function readAgentTemplateRow(inp) {
|
|
|
15245
15353
|
);
|
|
15246
15354
|
return null;
|
|
15247
15355
|
}
|
|
15248
|
-
} else if (
|
|
15356
|
+
} else if (existsSync24(inp.bundledPath)) {
|
|
15249
15357
|
if (!isWithin(inp.bundledPath, inp.bundledRoot)) {
|
|
15250
15358
|
console.error(
|
|
15251
15359
|
`[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="bundled path outside PLATFORM_ROOT"`
|
|
@@ -15284,11 +15392,11 @@ function isWithin(target, root) {
|
|
|
15284
15392
|
const rel = relative3(root, target);
|
|
15285
15393
|
return !rel.startsWith("..") && !isAbsolute(rel);
|
|
15286
15394
|
}
|
|
15287
|
-
var sidebar_artefacts_default =
|
|
15395
|
+
var sidebar_artefacts_default = app27;
|
|
15288
15396
|
|
|
15289
15397
|
// server/routes/admin/session-delete.ts
|
|
15290
|
-
var
|
|
15291
|
-
|
|
15398
|
+
var app28 = new Hono();
|
|
15399
|
+
app28.post("/", requireAdminSession, async (c) => {
|
|
15292
15400
|
let body;
|
|
15293
15401
|
try {
|
|
15294
15402
|
body = await c.req.json();
|
|
@@ -15326,11 +15434,11 @@ app27.post("/", requireAdminSession, async (c) => {
|
|
|
15326
15434
|
console.error(`[session-delete] sessionId=${sessionId} delete-status=${del.status}`);
|
|
15327
15435
|
return c.json({ error: `manager-status-${del.status}` }, 502);
|
|
15328
15436
|
});
|
|
15329
|
-
var session_delete_default =
|
|
15437
|
+
var session_delete_default = app28;
|
|
15330
15438
|
|
|
15331
15439
|
// server/routes/admin/session-stop.ts
|
|
15332
|
-
var
|
|
15333
|
-
|
|
15440
|
+
var app29 = new Hono();
|
|
15441
|
+
app29.post("/", requireAdminSession, async (c) => {
|
|
15334
15442
|
let body;
|
|
15335
15443
|
try {
|
|
15336
15444
|
body = await c.req.json();
|
|
@@ -15355,11 +15463,11 @@ app28.post("/", requireAdminSession, async (c) => {
|
|
|
15355
15463
|
console.error(`[session-stop] sessionId=${sessionId} manager-status=${res.status}`);
|
|
15356
15464
|
return c.json({ error: `manager-status-${res.status}` }, 502);
|
|
15357
15465
|
});
|
|
15358
|
-
var session_stop_default =
|
|
15466
|
+
var session_stop_default = app29;
|
|
15359
15467
|
|
|
15360
15468
|
// server/routes/admin/session-archive.ts
|
|
15361
|
-
var
|
|
15362
|
-
|
|
15469
|
+
var app30 = new Hono();
|
|
15470
|
+
app30.post("/", requireAdminSession, async (c) => {
|
|
15363
15471
|
let body;
|
|
15364
15472
|
try {
|
|
15365
15473
|
body = await c.req.json();
|
|
@@ -15407,11 +15515,11 @@ app29.post("/", requireAdminSession, async (c) => {
|
|
|
15407
15515
|
console.error(`[session-archive] sessionId=${sessionId.slice(0, 8)} manager-status=${res.status}`);
|
|
15408
15516
|
return c.json({ error: `manager-status-${res.status}` }, 502);
|
|
15409
15517
|
});
|
|
15410
|
-
var session_archive_default =
|
|
15518
|
+
var session_archive_default = app30;
|
|
15411
15519
|
|
|
15412
15520
|
// server/routes/admin/session-rename.ts
|
|
15413
|
-
var
|
|
15414
|
-
|
|
15521
|
+
var app31 = new Hono();
|
|
15522
|
+
app31.post("/", requireAdminSession, async (c) => {
|
|
15415
15523
|
let body;
|
|
15416
15524
|
try {
|
|
15417
15525
|
body = await c.req.json();
|
|
@@ -15450,7 +15558,7 @@ app30.post("/", requireAdminSession, async (c) => {
|
|
|
15450
15558
|
console.error(`[session-rename] sessionId=${sessionId.slice(0, 8)} manager-status=${res.status}`);
|
|
15451
15559
|
return c.json({ error: `manager-status-${res.status}` }, 502);
|
|
15452
15560
|
});
|
|
15453
|
-
var session_rename_default =
|
|
15561
|
+
var session_rename_default = app31;
|
|
15454
15562
|
|
|
15455
15563
|
// server/routes/admin/session-rc-spawn.ts
|
|
15456
15564
|
import { randomUUID as randomUUID11 } from "crypto";
|
|
@@ -15487,8 +15595,8 @@ function shapeWebchatResponse(sessionId, manager) {
|
|
|
15487
15595
|
const landed = redirected ? manager.sessionId : sessionId;
|
|
15488
15596
|
return { sessionId: landed, outcome, target: `/chat?session=${landed}` };
|
|
15489
15597
|
}
|
|
15490
|
-
var
|
|
15491
|
-
|
|
15598
|
+
var app32 = new Hono();
|
|
15599
|
+
app32.post("/", requireAdminSession, async (c) => {
|
|
15492
15600
|
let body;
|
|
15493
15601
|
try {
|
|
15494
15602
|
body = await c.req.json();
|
|
@@ -15543,7 +15651,7 @@ app31.post("/", requireAdminSession, async (c) => {
|
|
|
15543
15651
|
}
|
|
15544
15652
|
return c.json(parsed ?? {});
|
|
15545
15653
|
});
|
|
15546
|
-
var session_rc_spawn_default =
|
|
15654
|
+
var session_rc_spawn_default = app32;
|
|
15547
15655
|
|
|
15548
15656
|
// server/routes/admin/session-reseat.ts
|
|
15549
15657
|
import { randomUUID as randomUUID12 } from "crypto";
|
|
@@ -15585,9 +15693,9 @@ function resolveReseatPlan(body, mintId = randomUUID12, adminUserId, authenticat
|
|
|
15585
15693
|
if (authenticatedName) payload.authenticatedName = authenticatedName;
|
|
15586
15694
|
return { sessionId, payload };
|
|
15587
15695
|
}
|
|
15588
|
-
var
|
|
15696
|
+
var app33 = new Hono();
|
|
15589
15697
|
var reseatsInFlight = /* @__PURE__ */ new Set();
|
|
15590
|
-
|
|
15698
|
+
app33.post("/", requireAdminSession, async (c) => {
|
|
15591
15699
|
let body;
|
|
15592
15700
|
try {
|
|
15593
15701
|
body = await c.req.json();
|
|
@@ -15658,7 +15766,7 @@ app32.post("/", requireAdminSession, async (c) => {
|
|
|
15658
15766
|
reseatsInFlight.delete(fromSessionId);
|
|
15659
15767
|
}
|
|
15660
15768
|
});
|
|
15661
|
-
var session_reseat_default =
|
|
15769
|
+
var session_reseat_default = app33;
|
|
15662
15770
|
|
|
15663
15771
|
// server/routes/admin/system-stats.ts
|
|
15664
15772
|
import { readFile as readFile5 } from "fs/promises";
|
|
@@ -15755,8 +15863,8 @@ async function sample() {
|
|
|
15755
15863
|
if (process.platform === "linux") return sampleLinux();
|
|
15756
15864
|
return sampleOsFallback();
|
|
15757
15865
|
}
|
|
15758
|
-
var
|
|
15759
|
-
|
|
15866
|
+
var app34 = new Hono();
|
|
15867
|
+
app34.get("/", async (c) => {
|
|
15760
15868
|
const started = Date.now();
|
|
15761
15869
|
if (!inflight) {
|
|
15762
15870
|
inflight = sample().finally(() => {
|
|
@@ -15779,17 +15887,17 @@ app33.get("/", async (c) => {
|
|
|
15779
15887
|
return c.json({ degraded: true, reason, sampledAtMs: Date.now() });
|
|
15780
15888
|
}
|
|
15781
15889
|
});
|
|
15782
|
-
var system_stats_default =
|
|
15890
|
+
var system_stats_default = app34;
|
|
15783
15891
|
|
|
15784
15892
|
// server/routes/admin/health.ts
|
|
15785
|
-
import { existsSync as
|
|
15786
|
-
import { resolve as resolve24, join as
|
|
15893
|
+
import { existsSync as existsSync25, readFileSync as readFileSync24 } from "fs";
|
|
15894
|
+
import { resolve as resolve24, join as join24 } from "path";
|
|
15787
15895
|
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve24(process.cwd(), "..");
|
|
15788
15896
|
var brandHostname = "maxy";
|
|
15789
|
-
var brandJsonPath =
|
|
15790
|
-
if (
|
|
15897
|
+
var brandJsonPath = join24(PLATFORM_ROOT6, "config", "brand.json");
|
|
15898
|
+
if (existsSync25(brandJsonPath)) {
|
|
15791
15899
|
try {
|
|
15792
|
-
const brand = JSON.parse(
|
|
15900
|
+
const brand = JSON.parse(readFileSync24(brandJsonPath, "utf-8"));
|
|
15793
15901
|
if (brand.hostname) brandHostname = brand.hostname;
|
|
15794
15902
|
} catch {
|
|
15795
15903
|
}
|
|
@@ -15798,8 +15906,8 @@ var VERSION_FILE = resolve24(PLATFORM_ROOT6, `config/.${brandHostname}-version`)
|
|
|
15798
15906
|
var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
15799
15907
|
var PROBE_TIMEOUT_MS = 1e3;
|
|
15800
15908
|
function readVersion() {
|
|
15801
|
-
if (!
|
|
15802
|
-
return
|
|
15909
|
+
if (!existsSync25(VERSION_FILE)) return "unknown";
|
|
15910
|
+
return readFileSync24(VERSION_FILE, "utf-8").trim() || "unknown";
|
|
15803
15911
|
}
|
|
15804
15912
|
async function probeConversationDb() {
|
|
15805
15913
|
let session;
|
|
@@ -15824,8 +15932,8 @@ async function probeConversationDb() {
|
|
|
15824
15932
|
});
|
|
15825
15933
|
}
|
|
15826
15934
|
}
|
|
15827
|
-
var
|
|
15828
|
-
|
|
15935
|
+
var app35 = new Hono();
|
|
15936
|
+
app35.get("/", async (c) => {
|
|
15829
15937
|
const version = readVersion();
|
|
15830
15938
|
const probe = await probeConversationDb();
|
|
15831
15939
|
const uptimeMs = Date.now() - new Date(PROCESS_STARTED_AT).getTime();
|
|
@@ -15847,11 +15955,11 @@ app34.get("/", async (c) => {
|
|
|
15847
15955
|
uptimeMs
|
|
15848
15956
|
});
|
|
15849
15957
|
});
|
|
15850
|
-
var health_default2 =
|
|
15958
|
+
var health_default2 = app35;
|
|
15851
15959
|
|
|
15852
15960
|
// server/routes/admin/linkedin-ingest.ts
|
|
15853
15961
|
import { randomUUID as randomUUID13 } from "crypto";
|
|
15854
|
-
var
|
|
15962
|
+
var TAG27 = "[linkedin-ingest-route]";
|
|
15855
15963
|
var UUID2 = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
15856
15964
|
var ISO = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
15857
15965
|
var LINKEDIN_URL = /^https:\/\/www\.linkedin\.com\//;
|
|
@@ -15949,35 +16057,35 @@ function buildInitialMessage(env) {
|
|
|
15949
16057
|
}
|
|
15950
16058
|
return header;
|
|
15951
16059
|
}
|
|
15952
|
-
var
|
|
15953
|
-
|
|
16060
|
+
var app36 = new Hono();
|
|
16061
|
+
app36.post("/", requireAdminSession, async (c) => {
|
|
15954
16062
|
let body;
|
|
15955
16063
|
try {
|
|
15956
16064
|
body = await c.req.json();
|
|
15957
16065
|
} catch {
|
|
15958
|
-
console.error(
|
|
16066
|
+
console.error(TAG27 + " rejected status=400 reason=schema:body-not-json");
|
|
15959
16067
|
return c.json({ ok: false, error: "schema", reason: "body-not-json" }, 400);
|
|
15960
16068
|
}
|
|
15961
16069
|
const v = validate(body);
|
|
15962
16070
|
if (!v.ok) {
|
|
15963
|
-
console.error(
|
|
16071
|
+
console.error(TAG27 + " rejected status=" + v.status + " reason=" + v.reason + " missing=" + v.missing.join(","));
|
|
15964
16072
|
return c.json({ ok: false, error: v.error, reason: v.reason, missing: v.missing }, v.status);
|
|
15965
16073
|
}
|
|
15966
16074
|
const envelope = v.envelope;
|
|
15967
16075
|
const cacheKey = c.var.cacheKey ?? "";
|
|
15968
16076
|
const senderId = getAccountIdForSession(cacheKey) ?? "";
|
|
15969
16077
|
if (!senderId) {
|
|
15970
|
-
console.error(
|
|
16078
|
+
console.error(TAG27 + " rejected status=500 reason=admin-account-not-resolved");
|
|
15971
16079
|
return c.json({ ok: false, error: "admin-account-not-resolved" }, 500);
|
|
15972
16080
|
}
|
|
15973
16081
|
const payloadBytes = JSON.stringify(envelope).length;
|
|
15974
16082
|
console.log(
|
|
15975
|
-
|
|
16083
|
+
TAG27 + " received kind=" + envelope.kind + " account=" + senderId.slice(0, 8) + " pageUrl=" + envelope.pageUrl + " dispatchId=" + envelope.dispatchId + " payloadBytes=" + payloadBytes
|
|
15976
16084
|
);
|
|
15977
16085
|
const initialMessage = buildInitialMessage(envelope);
|
|
15978
16086
|
const spawnStart = Date.now();
|
|
15979
16087
|
const sessionId = randomUUID13();
|
|
15980
|
-
console.log(
|
|
16088
|
+
console.log(TAG27 + " route target=rc-spawn dispatchId=" + envelope.dispatchId + " sessionId=" + sessionId.slice(0, 8));
|
|
15981
16089
|
const spawned = await managerRcSpawn({
|
|
15982
16090
|
sessionId,
|
|
15983
16091
|
initialMessage,
|
|
@@ -15986,20 +16094,20 @@ app35.post("/", requireAdminSession, async (c) => {
|
|
|
15986
16094
|
});
|
|
15987
16095
|
if ("error" in spawned) {
|
|
15988
16096
|
console.error(
|
|
15989
|
-
|
|
16097
|
+
TAG27 + " dispatch-failed dispatchId=" + envelope.dispatchId + " status=" + spawned.status + " ms=" + (Date.now() - spawnStart) + " message=" + spawned.error
|
|
15990
16098
|
);
|
|
15991
16099
|
return c.json({ ok: false, error: "dispatch-failed", upstreamStatus: spawned.status, detail: spawned.error }, 502);
|
|
15992
16100
|
}
|
|
15993
16101
|
console.log(
|
|
15994
|
-
|
|
16102
|
+
TAG27 + " dispatched dispatchId=" + envelope.dispatchId + " taskId=" + spawned.sessionId + " ms=" + (Date.now() - spawnStart)
|
|
15995
16103
|
);
|
|
15996
16104
|
return c.json({ ok: true, dispatchId: envelope.dispatchId, taskId: spawned.sessionId }, 202);
|
|
15997
16105
|
});
|
|
15998
|
-
var linkedin_ingest_default =
|
|
16106
|
+
var linkedin_ingest_default = app36;
|
|
15999
16107
|
|
|
16000
16108
|
// server/routes/admin/post-turn-context.ts
|
|
16001
16109
|
import neo4j3 from "neo4j-driver";
|
|
16002
|
-
var
|
|
16110
|
+
var TAG28 = "[post-turn-context]";
|
|
16003
16111
|
var STRIPPED_PROPERTIES2 = /* @__PURE__ */ new Set([
|
|
16004
16112
|
"embedding",
|
|
16005
16113
|
"passwordHash",
|
|
@@ -16037,11 +16145,11 @@ function pruneProperties(raw) {
|
|
|
16037
16145
|
}
|
|
16038
16146
|
return out;
|
|
16039
16147
|
}
|
|
16040
|
-
var
|
|
16041
|
-
|
|
16148
|
+
var app37 = new Hono();
|
|
16149
|
+
app37.get("/", async (c) => {
|
|
16042
16150
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
16043
16151
|
if (!isLoopbackAddr2(remoteAddr)) {
|
|
16044
|
-
console.error(`${
|
|
16152
|
+
console.error(`${TAG28} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
16045
16153
|
return c.json({ error: "post-turn-context-loopback-only" }, 403);
|
|
16046
16154
|
}
|
|
16047
16155
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -16050,7 +16158,7 @@ app36.get("/", async (c) => {
|
|
|
16050
16158
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
16051
16159
|
const offender = tokens.find((t) => !isLoopbackAddr2(t));
|
|
16052
16160
|
if (offender !== void 0) {
|
|
16053
|
-
console.error(`${
|
|
16161
|
+
console.error(`${TAG28} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
16054
16162
|
return c.json({ error: "post-turn-context-loopback-only" }, 403);
|
|
16055
16163
|
}
|
|
16056
16164
|
}
|
|
@@ -16082,7 +16190,7 @@ app36.get("/", async (c) => {
|
|
|
16082
16190
|
writes.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
|
|
16083
16191
|
const total = Date.now() - started;
|
|
16084
16192
|
console.log(
|
|
16085
|
-
`${
|
|
16193
|
+
`${TAG28} sessionId=${sessionId} accountId=${accountId} writes=${writes.length} ms=${total}`
|
|
16086
16194
|
);
|
|
16087
16195
|
return c.json({
|
|
16088
16196
|
writes: writes.map(({ elementId, labels, properties }) => ({ elementId, labels, properties }))
|
|
@@ -16091,18 +16199,18 @@ app36.get("/", async (c) => {
|
|
|
16091
16199
|
const elapsed = Date.now() - started;
|
|
16092
16200
|
const message = err instanceof Error ? err.message : String(err);
|
|
16093
16201
|
console.error(
|
|
16094
|
-
`${
|
|
16202
|
+
`${TAG28} neo4j-unreachable sessionId=${sessionId} ms=${elapsed} err="${message}"`
|
|
16095
16203
|
);
|
|
16096
16204
|
return c.json({ error: `post-turn-context unavailable: ${message}` }, 503);
|
|
16097
16205
|
} finally {
|
|
16098
16206
|
await session.close();
|
|
16099
16207
|
}
|
|
16100
16208
|
});
|
|
16101
|
-
var post_turn_context_default =
|
|
16209
|
+
var post_turn_context_default = app37;
|
|
16102
16210
|
|
|
16103
16211
|
// server/routes/admin/public-session-context.ts
|
|
16104
16212
|
import neo4j4 from "neo4j-driver";
|
|
16105
|
-
var
|
|
16213
|
+
var TAG29 = "[public-session-context]";
|
|
16106
16214
|
var STRIPPED_PROPERTIES3 = /* @__PURE__ */ new Set([
|
|
16107
16215
|
"embedding",
|
|
16108
16216
|
"passwordHash",
|
|
@@ -16140,11 +16248,11 @@ function pruneProperties2(raw) {
|
|
|
16140
16248
|
}
|
|
16141
16249
|
return out;
|
|
16142
16250
|
}
|
|
16143
|
-
var
|
|
16144
|
-
|
|
16251
|
+
var app38 = new Hono();
|
|
16252
|
+
app38.get("/", async (c) => {
|
|
16145
16253
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
16146
16254
|
if (!isLoopbackAddr3(remoteAddr)) {
|
|
16147
|
-
console.error(`${
|
|
16255
|
+
console.error(`${TAG29} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
16148
16256
|
return c.json({ error: "public-session-context-loopback-only" }, 403);
|
|
16149
16257
|
}
|
|
16150
16258
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -16153,7 +16261,7 @@ app37.get("/", async (c) => {
|
|
|
16153
16261
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
16154
16262
|
const offender = tokens.find((t) => !isLoopbackAddr3(t));
|
|
16155
16263
|
if (offender !== void 0) {
|
|
16156
|
-
console.error(`${
|
|
16264
|
+
console.error(`${TAG29} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
16157
16265
|
return c.json({ error: "public-session-context-loopback-only" }, 403);
|
|
16158
16266
|
}
|
|
16159
16267
|
}
|
|
@@ -16184,7 +16292,7 @@ app37.get("/", async (c) => {
|
|
|
16184
16292
|
writes.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
|
|
16185
16293
|
const total = Date.now() - started;
|
|
16186
16294
|
console.log(
|
|
16187
|
-
`${
|
|
16295
|
+
`${TAG29} sliceToken=${sliceToken.slice(0, 8)} writes=${writes.length} ms=${total}`
|
|
16188
16296
|
);
|
|
16189
16297
|
return c.json({
|
|
16190
16298
|
writes: writes.map(({ elementId, labels, properties }) => ({ elementId, labels, properties }))
|
|
@@ -16193,25 +16301,25 @@ app37.get("/", async (c) => {
|
|
|
16193
16301
|
const elapsed = Date.now() - started;
|
|
16194
16302
|
const message = err instanceof Error ? err.message : String(err);
|
|
16195
16303
|
console.error(
|
|
16196
|
-
`${
|
|
16304
|
+
`${TAG29} neo4j-unreachable sliceToken=${sliceToken.slice(0, 8)} ms=${elapsed} err="${message}"`
|
|
16197
16305
|
);
|
|
16198
16306
|
return c.json({ error: `public-session-context unavailable: ${message}` }, 503);
|
|
16199
16307
|
} finally {
|
|
16200
16308
|
await session.close();
|
|
16201
16309
|
}
|
|
16202
16310
|
});
|
|
16203
|
-
var public_session_context_default =
|
|
16311
|
+
var public_session_context_default = app38;
|
|
16204
16312
|
|
|
16205
16313
|
// server/routes/admin/public-session-exit.ts
|
|
16206
|
-
var
|
|
16314
|
+
var TAG30 = "[public-session-exit-route]";
|
|
16207
16315
|
function isLoopbackAddr4(addr) {
|
|
16208
16316
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
16209
16317
|
}
|
|
16210
|
-
var
|
|
16211
|
-
|
|
16318
|
+
var app39 = new Hono();
|
|
16319
|
+
app39.post("/", async (c) => {
|
|
16212
16320
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
16213
16321
|
if (!isLoopbackAddr4(remoteAddr)) {
|
|
16214
|
-
console.error(`${
|
|
16322
|
+
console.error(`${TAG30} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
16215
16323
|
return c.json({ error: "public-session-exit-loopback-only" }, 403);
|
|
16216
16324
|
}
|
|
16217
16325
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -16220,7 +16328,7 @@ app38.post("/", async (c) => {
|
|
|
16220
16328
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
16221
16329
|
const offender = tokens.find((t) => !isLoopbackAddr4(t));
|
|
16222
16330
|
if (offender !== void 0) {
|
|
16223
|
-
console.error(`${
|
|
16331
|
+
console.error(`${TAG30} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
16224
16332
|
return c.json({ error: "public-session-exit-loopback-only" }, 403);
|
|
16225
16333
|
}
|
|
16226
16334
|
}
|
|
@@ -16235,18 +16343,18 @@ app38.post("/", async (c) => {
|
|
|
16235
16343
|
handlePublicSessionExit(sessionId);
|
|
16236
16344
|
return c.json({ ok: true });
|
|
16237
16345
|
});
|
|
16238
|
-
var public_session_exit_default =
|
|
16346
|
+
var public_session_exit_default = app39;
|
|
16239
16347
|
|
|
16240
16348
|
// server/routes/admin/access-session-evict.ts
|
|
16241
|
-
var
|
|
16349
|
+
var TAG31 = "[access-session-evict]";
|
|
16242
16350
|
function isLoopbackAddr5(addr) {
|
|
16243
16351
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
16244
16352
|
}
|
|
16245
|
-
var
|
|
16246
|
-
|
|
16353
|
+
var app40 = new Hono();
|
|
16354
|
+
app40.post("/", async (c) => {
|
|
16247
16355
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
16248
16356
|
if (!isLoopbackAddr5(remoteAddr)) {
|
|
16249
|
-
console.error(`${
|
|
16357
|
+
console.error(`${TAG31} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
16250
16358
|
return c.json({ error: "access-session-evict-loopback-only" }, 403);
|
|
16251
16359
|
}
|
|
16252
16360
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -16255,7 +16363,7 @@ app39.post("/", async (c) => {
|
|
|
16255
16363
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
16256
16364
|
const offender = tokens.find((t) => !isLoopbackAddr5(t));
|
|
16257
16365
|
if (offender !== void 0) {
|
|
16258
|
-
console.error(`${
|
|
16366
|
+
console.error(`${TAG31} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
16259
16367
|
return c.json({ error: "access-session-evict-loopback-only" }, 403);
|
|
16260
16368
|
}
|
|
16261
16369
|
}
|
|
@@ -16268,22 +16376,22 @@ app39.post("/", async (c) => {
|
|
|
16268
16376
|
const grantId = typeof body.grantId === "string" ? body.grantId.trim() : "";
|
|
16269
16377
|
if (!grantId) return c.json({ error: "grantId required" }, 400);
|
|
16270
16378
|
const dropped = evictAccessSessionsByGrant(grantId);
|
|
16271
|
-
console.log(`${
|
|
16379
|
+
console.log(`${TAG31} grantId=${grantId} dropped=${dropped}`);
|
|
16272
16380
|
return c.json({ ok: true, dropped });
|
|
16273
16381
|
});
|
|
16274
|
-
var access_session_evict_default =
|
|
16382
|
+
var access_session_evict_default = app40;
|
|
16275
16383
|
|
|
16276
16384
|
// server/routes/admin/enrol-person.ts
|
|
16277
|
-
var
|
|
16385
|
+
var TAG32 = "[enrol]";
|
|
16278
16386
|
function isLoopbackAddr6(addr) {
|
|
16279
16387
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
16280
16388
|
}
|
|
16281
16389
|
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
16282
|
-
var
|
|
16283
|
-
|
|
16390
|
+
var app41 = new Hono();
|
|
16391
|
+
app41.post("/", async (c) => {
|
|
16284
16392
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
16285
16393
|
if (!isLoopbackAddr6(remoteAddr)) {
|
|
16286
|
-
console.error(`${
|
|
16394
|
+
console.error(`${TAG32} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
16287
16395
|
return c.json({ error: "enrol-person-loopback-only" }, 403);
|
|
16288
16396
|
}
|
|
16289
16397
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -16292,7 +16400,7 @@ app40.post("/", async (c) => {
|
|
|
16292
16400
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
16293
16401
|
const offender = tokens.find((t) => !isLoopbackAddr6(t));
|
|
16294
16402
|
if (offender !== void 0) {
|
|
16295
|
-
console.error(`${
|
|
16403
|
+
console.error(`${TAG32} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
16296
16404
|
return c.json({ error: "enrol-person-loopback-only" }, 403);
|
|
16297
16405
|
}
|
|
16298
16406
|
}
|
|
@@ -16317,7 +16425,7 @@ app40.post("/", async (c) => {
|
|
|
16317
16425
|
}
|
|
16318
16426
|
const accountId = process.env.ACCOUNT_ID ?? "";
|
|
16319
16427
|
if (!accountId) {
|
|
16320
|
-
console.error(`${
|
|
16428
|
+
console.error(`${TAG32} op=person result=no-account-id`);
|
|
16321
16429
|
return c.json({ error: "no-account-id" }, 500);
|
|
16322
16430
|
}
|
|
16323
16431
|
let personId;
|
|
@@ -16325,7 +16433,7 @@ app40.post("/", async (c) => {
|
|
|
16325
16433
|
personId = await enrolPerson({ accountId, phone, email, agentSlug });
|
|
16326
16434
|
} catch (err) {
|
|
16327
16435
|
console.error(
|
|
16328
|
-
`${
|
|
16436
|
+
`${TAG32} op=person result=write-failed agentSlug=${agentSlug} contact=${maskContact(email)} err="${err instanceof Error ? err.message : String(err)}"`
|
|
16329
16437
|
);
|
|
16330
16438
|
return c.json({ error: "enrol-failed" }, 500);
|
|
16331
16439
|
}
|
|
@@ -16335,19 +16443,19 @@ app40.post("/", async (c) => {
|
|
|
16335
16443
|
if (g) grant = { grantId: g.grantId, status: g.status, contactValue: g.contactValue };
|
|
16336
16444
|
} catch (err) {
|
|
16337
16445
|
console.error(
|
|
16338
|
-
`${
|
|
16446
|
+
`${TAG32} op=person result=grant-lookup-failed contact=${maskContact(email)} err="${err instanceof Error ? err.message : String(err)}"`
|
|
16339
16447
|
);
|
|
16340
16448
|
}
|
|
16341
16449
|
console.log(
|
|
16342
|
-
`${
|
|
16450
|
+
`${TAG32} op=person personId=${personId} account=${accountId} agentSlug=${agentSlug} contact=${maskContact(email)}`
|
|
16343
16451
|
);
|
|
16344
16452
|
return c.json({ personId, grant }, 200);
|
|
16345
16453
|
});
|
|
16346
|
-
var enrol_person_default =
|
|
16454
|
+
var enrol_person_default = app41;
|
|
16347
16455
|
|
|
16348
16456
|
// server/routes/admin/browser.ts
|
|
16349
|
-
var
|
|
16350
|
-
|
|
16457
|
+
var app42 = new Hono();
|
|
16458
|
+
app42.post("/launch", requireAdminSession, async (c) => {
|
|
16351
16459
|
try {
|
|
16352
16460
|
const transport = resolveBrowserTransport(c.req.raw, c.env?.incoming?.socket?.remoteAddress);
|
|
16353
16461
|
console.error(`[admin/browser/launch] op=request transport=${transport}`);
|
|
@@ -16375,51 +16483,51 @@ app41.post("/launch", requireAdminSession, async (c) => {
|
|
|
16375
16483
|
);
|
|
16376
16484
|
}
|
|
16377
16485
|
});
|
|
16378
|
-
var browser_default =
|
|
16486
|
+
var browser_default = app42;
|
|
16379
16487
|
|
|
16380
16488
|
// server/routes/admin/index.ts
|
|
16381
|
-
var
|
|
16382
|
-
|
|
16383
|
-
|
|
16384
|
-
|
|
16385
|
-
|
|
16386
|
-
|
|
16387
|
-
|
|
16388
|
-
|
|
16389
|
-
|
|
16390
|
-
|
|
16391
|
-
|
|
16392
|
-
|
|
16393
|
-
|
|
16394
|
-
|
|
16395
|
-
|
|
16396
|
-
|
|
16397
|
-
|
|
16398
|
-
|
|
16399
|
-
|
|
16400
|
-
|
|
16401
|
-
|
|
16402
|
-
|
|
16403
|
-
|
|
16404
|
-
|
|
16405
|
-
|
|
16406
|
-
|
|
16407
|
-
|
|
16408
|
-
|
|
16409
|
-
|
|
16410
|
-
|
|
16411
|
-
|
|
16412
|
-
|
|
16413
|
-
|
|
16414
|
-
|
|
16415
|
-
var admin_default =
|
|
16489
|
+
var app43 = new Hono();
|
|
16490
|
+
app43.route("/session", session_default);
|
|
16491
|
+
app43.route("/logs", logs_default);
|
|
16492
|
+
app43.route("/claude-info", claude_info_default);
|
|
16493
|
+
app43.route("/attachment", attachment_default);
|
|
16494
|
+
app43.route("/agents", agents_default);
|
|
16495
|
+
app43.route("/sessions", sessions_default);
|
|
16496
|
+
app43.route("/claude-sessions", claude_sessions_default);
|
|
16497
|
+
app43.route("/log-ingest", log_ingest_default);
|
|
16498
|
+
app43.route("/events", events_default);
|
|
16499
|
+
app43.route("/files", files_default);
|
|
16500
|
+
app43.route("/graph-search", graph_search_default);
|
|
16501
|
+
app43.route("/graph-subgraph", graph_subgraph_default);
|
|
16502
|
+
app43.route("/graph-delete", graph_delete_default);
|
|
16503
|
+
app43.route("/graph-restore", graph_restore_default);
|
|
16504
|
+
app43.route("/graph-labels-in-graph", graph_labels_in_graph_default);
|
|
16505
|
+
app43.route("/graph-default-view", graph_default_view_default);
|
|
16506
|
+
app43.route("/sidebar-artefacts", sidebar_artefacts_default);
|
|
16507
|
+
app43.route("/sidebar-sessions", sidebar_sessions_default);
|
|
16508
|
+
app43.route("/session-delete", session_delete_default);
|
|
16509
|
+
app43.route("/session-stop", session_stop_default);
|
|
16510
|
+
app43.route("/session-archive", session_archive_default);
|
|
16511
|
+
app43.route("/session-rename", session_rename_default);
|
|
16512
|
+
app43.route("/browser", browser_default);
|
|
16513
|
+
app43.route("/session-rc-spawn", session_rc_spawn_default);
|
|
16514
|
+
app43.route("/session-reseat", session_reseat_default);
|
|
16515
|
+
app43.route("/system-stats", system_stats_default);
|
|
16516
|
+
app43.route("/health-brand", health_default2);
|
|
16517
|
+
app43.route("/linkedin-ingest", linkedin_ingest_default);
|
|
16518
|
+
app43.route("/post-turn-context", post_turn_context_default);
|
|
16519
|
+
app43.route("/public-session-context", public_session_context_default);
|
|
16520
|
+
app43.route("/public-session-exit", public_session_exit_default);
|
|
16521
|
+
app43.route("/access-session-evict", access_session_evict_default);
|
|
16522
|
+
app43.route("/enrol-person", enrol_person_default);
|
|
16523
|
+
var admin_default = app43;
|
|
16416
16524
|
|
|
16417
16525
|
// server/routes/access/verify-token.ts
|
|
16418
|
-
var
|
|
16526
|
+
var TAG33 = "[access-verify]";
|
|
16419
16527
|
var MINT_TAG = "[access-session-mint]";
|
|
16420
16528
|
var COOKIE_NAME = "__access_session";
|
|
16421
|
-
var
|
|
16422
|
-
|
|
16529
|
+
var app44 = new Hono();
|
|
16530
|
+
app44.post("/", async (c) => {
|
|
16423
16531
|
const ip = c.var.clientIp || "unknown";
|
|
16424
16532
|
let body;
|
|
16425
16533
|
try {
|
|
@@ -16434,39 +16542,39 @@ app43.post("/", async (c) => {
|
|
|
16434
16542
|
}
|
|
16435
16543
|
const rateMsg = checkAccessRateLimit(ip, agentSlug);
|
|
16436
16544
|
if (rateMsg) {
|
|
16437
|
-
console.error(`${
|
|
16545
|
+
console.error(`${TAG33} grantId=- agentSlug=${agentSlug} result=rate-limited ip=${ip}`);
|
|
16438
16546
|
return c.json({ error: rateMsg }, 429);
|
|
16439
16547
|
}
|
|
16440
16548
|
const grant = await findGrantByMagicToken(token);
|
|
16441
16549
|
if (!grant) {
|
|
16442
16550
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
16443
|
-
console.error(`${
|
|
16551
|
+
console.error(`${TAG33} grantId=- agentSlug=${agentSlug} result=notfound ip=${ip}`);
|
|
16444
16552
|
return c.json({ error: "invalid-or-expired-link" }, 401);
|
|
16445
16553
|
}
|
|
16446
16554
|
if (grant.agentSlug !== agentSlug) {
|
|
16447
16555
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
16448
16556
|
console.error(
|
|
16449
|
-
`${
|
|
16557
|
+
`${TAG33} grantId=${grant.grantId} agentSlug=${agentSlug} result=agent-mismatch grantAgent=${grant.agentSlug} ip=${ip}`
|
|
16450
16558
|
);
|
|
16451
16559
|
return c.json({ error: "invalid-or-expired-link" }, 401);
|
|
16452
16560
|
}
|
|
16453
16561
|
if (grant.status === "expired" || grant.status === "revoked") {
|
|
16454
16562
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
16455
16563
|
console.error(
|
|
16456
|
-
`${
|
|
16564
|
+
`${TAG33} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired status=${grant.status} ip=${ip}`
|
|
16457
16565
|
);
|
|
16458
16566
|
return c.json({ error: "access-no-longer-valid" }, 401);
|
|
16459
16567
|
}
|
|
16460
16568
|
if (grant.expiresAt !== null && grant.expiresAt < Date.now()) {
|
|
16461
16569
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
16462
16570
|
console.error(
|
|
16463
|
-
`${
|
|
16571
|
+
`${TAG33} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired reason=expiresAt-past ip=${ip}`
|
|
16464
16572
|
);
|
|
16465
16573
|
return c.json({ error: "access-no-longer-valid" }, 401);
|
|
16466
16574
|
}
|
|
16467
16575
|
if (!grant.sliceToken) {
|
|
16468
16576
|
console.error(
|
|
16469
|
-
`${
|
|
16577
|
+
`${TAG33} grantId=${grant.grantId} agentSlug=${agentSlug} result=no-slice-token reason=schema-violation`
|
|
16470
16578
|
);
|
|
16471
16579
|
return c.json({ error: "grant-misconfigured" }, 500);
|
|
16472
16580
|
}
|
|
@@ -16482,12 +16590,12 @@ app43.post("/", async (c) => {
|
|
|
16482
16590
|
await consumeMagicTokenAndActivate(grant.grantId);
|
|
16483
16591
|
} catch (err) {
|
|
16484
16592
|
console.error(
|
|
16485
|
-
`${
|
|
16593
|
+
`${TAG33} grantId=${grant.grantId} agentSlug=${agentSlug} result=consume-failed err="${err instanceof Error ? err.message : String(err)}"`
|
|
16486
16594
|
);
|
|
16487
16595
|
return c.json({ error: "verification-failed" }, 500);
|
|
16488
16596
|
}
|
|
16489
16597
|
clearAccessRateLimit(ip, agentSlug);
|
|
16490
|
-
console.log(`${
|
|
16598
|
+
console.log(`${TAG33} grantId=${grant.grantId} agentSlug=${agentSlug} result=ok ip=${ip}`);
|
|
16491
16599
|
console.log(
|
|
16492
16600
|
`${MINT_TAG} grantId=${grant.grantId} sliceToken=${grant.sliceToken.slice(0, 8)} agentSlug=${agentSlug} personId=${grant.personId ?? "none"}`
|
|
16493
16601
|
);
|
|
@@ -16501,7 +16609,7 @@ app43.post("/", async (c) => {
|
|
|
16501
16609
|
displayName: grant.displayName
|
|
16502
16610
|
});
|
|
16503
16611
|
});
|
|
16504
|
-
var verify_token_default =
|
|
16612
|
+
var verify_token_default = app44;
|
|
16505
16613
|
|
|
16506
16614
|
// app/lib/access-email.ts
|
|
16507
16615
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -16563,10 +16671,10 @@ async function sendMagicLinkEmail(payload) {
|
|
|
16563
16671
|
}
|
|
16564
16672
|
|
|
16565
16673
|
// server/routes/access/request-magic-link.ts
|
|
16566
|
-
var
|
|
16567
|
-
var
|
|
16674
|
+
var TAG34 = "[access-request-link]";
|
|
16675
|
+
var app45 = new Hono();
|
|
16568
16676
|
var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
|
|
16569
|
-
|
|
16677
|
+
app45.post("/", async (c) => {
|
|
16570
16678
|
let body;
|
|
16571
16679
|
try {
|
|
16572
16680
|
body = await c.req.json();
|
|
@@ -16580,18 +16688,18 @@ app44.post("/", async (c) => {
|
|
|
16580
16688
|
}
|
|
16581
16689
|
const rateMsg = checkRequestLinkRateLimit(contactValue);
|
|
16582
16690
|
if (rateMsg) {
|
|
16583
|
-
console.error(`${
|
|
16691
|
+
console.error(`${TAG34} contactValue=${maskContact(contactValue)} result=rate-limited`);
|
|
16584
16692
|
return c.json({ error: rateMsg }, 429);
|
|
16585
16693
|
}
|
|
16586
16694
|
recordRequestLinkAttempt(contactValue);
|
|
16587
16695
|
const accountId = process.env.ACCOUNT_ID ?? "";
|
|
16588
16696
|
if (!accountId) {
|
|
16589
|
-
console.error(`${
|
|
16697
|
+
console.error(`${TAG34} contactValue=${maskContact(contactValue)} result=no-account-id`);
|
|
16590
16698
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
16591
16699
|
}
|
|
16592
16700
|
const grant = await findActiveGrantByContact(contactValue, agentSlug, accountId);
|
|
16593
16701
|
if (!grant) {
|
|
16594
|
-
console.log(`${
|
|
16702
|
+
console.log(`${TAG34} contactValue=${maskContact(contactValue)} result=notfound`);
|
|
16595
16703
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
16596
16704
|
}
|
|
16597
16705
|
let token;
|
|
@@ -16599,7 +16707,7 @@ app44.post("/", async (c) => {
|
|
|
16599
16707
|
token = await generateNewMagicToken(grant.grantId);
|
|
16600
16708
|
} catch (err) {
|
|
16601
16709
|
console.error(
|
|
16602
|
-
`${
|
|
16710
|
+
`${TAG34} contactValue=${maskContact(contactValue)} result=mint-failed err="${err instanceof Error ? err.message : String(err)}"`
|
|
16603
16711
|
);
|
|
16604
16712
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
16605
16713
|
}
|
|
@@ -16631,25 +16739,25 @@ app44.post("/", async (c) => {
|
|
|
16631
16739
|
});
|
|
16632
16740
|
if (!sendResult.ok) {
|
|
16633
16741
|
console.error(
|
|
16634
|
-
`${
|
|
16742
|
+
`${TAG34} contactValue=${maskContact(contactValue)} result=send-failed err="${sendResult.error}"`
|
|
16635
16743
|
);
|
|
16636
16744
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
16637
16745
|
}
|
|
16638
16746
|
console.log(
|
|
16639
|
-
`${
|
|
16747
|
+
`${TAG34} contactValue=${maskContact(contactValue)} result=ok messageId=${sendResult.messageId}`
|
|
16640
16748
|
);
|
|
16641
16749
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
16642
16750
|
});
|
|
16643
|
-
var request_magic_link_default =
|
|
16751
|
+
var request_magic_link_default = app45;
|
|
16644
16752
|
|
|
16645
16753
|
// server/routes/access/index.ts
|
|
16646
|
-
var
|
|
16647
|
-
|
|
16648
|
-
|
|
16649
|
-
var access_default =
|
|
16754
|
+
var app46 = new Hono();
|
|
16755
|
+
app46.route("/verify-token", verify_token_default);
|
|
16756
|
+
app46.route("/request-magic-link", request_magic_link_default);
|
|
16757
|
+
var access_default = app46;
|
|
16650
16758
|
|
|
16651
16759
|
// server/routes/sites.ts
|
|
16652
|
-
import { existsSync as
|
|
16760
|
+
import { existsSync as existsSync26, readFileSync as readFileSync25, realpathSync as realpathSync5, statSync as statSync11 } from "fs";
|
|
16653
16761
|
import { resolve as resolve26 } from "path";
|
|
16654
16762
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
16655
16763
|
var MIME = {
|
|
@@ -16681,8 +16789,8 @@ function getExt(p) {
|
|
|
16681
16789
|
if (idx < p.lastIndexOf("/")) return "";
|
|
16682
16790
|
return p.slice(idx).toLowerCase();
|
|
16683
16791
|
}
|
|
16684
|
-
var
|
|
16685
|
-
|
|
16792
|
+
var app47 = new Hono();
|
|
16793
|
+
app47.get("/:rel{.*}", (c) => {
|
|
16686
16794
|
const reqPath = c.req.path;
|
|
16687
16795
|
const rawRel = c.req.param("rel") ?? "";
|
|
16688
16796
|
const trimmed = rawRel.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
@@ -16715,7 +16823,7 @@ app46.get("/:rel{.*}", (c) => {
|
|
|
16715
16823
|
}
|
|
16716
16824
|
let stat7;
|
|
16717
16825
|
try {
|
|
16718
|
-
stat7 =
|
|
16826
|
+
stat7 = existsSync26(filePath) ? statSync11(filePath) : null;
|
|
16719
16827
|
} catch {
|
|
16720
16828
|
stat7 = null;
|
|
16721
16829
|
}
|
|
@@ -16734,7 +16842,7 @@ app46.get("/:rel{.*}", (c) => {
|
|
|
16734
16842
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
16735
16843
|
return c.text("Forbidden", 403);
|
|
16736
16844
|
}
|
|
16737
|
-
if (!
|
|
16845
|
+
if (!existsSync26(filePath)) {
|
|
16738
16846
|
console.error(`[sites] not-found path=${reqPath} status=404`);
|
|
16739
16847
|
return c.text("Not found", 404);
|
|
16740
16848
|
}
|
|
@@ -16753,7 +16861,7 @@ app46.get("/:rel{.*}", (c) => {
|
|
|
16753
16861
|
}
|
|
16754
16862
|
let body;
|
|
16755
16863
|
try {
|
|
16756
|
-
body =
|
|
16864
|
+
body = readFileSync25(realPath);
|
|
16757
16865
|
} catch (err) {
|
|
16758
16866
|
const code = err?.code;
|
|
16759
16867
|
if (code === "EISDIR") {
|
|
@@ -16785,11 +16893,11 @@ app46.get("/:rel{.*}", (c) => {
|
|
|
16785
16893
|
"X-Content-Type-Options": "nosniff"
|
|
16786
16894
|
});
|
|
16787
16895
|
});
|
|
16788
|
-
var sites_default =
|
|
16896
|
+
var sites_default = app47;
|
|
16789
16897
|
|
|
16790
16898
|
// app/lib/visitor-token.ts
|
|
16791
16899
|
import { createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
16792
|
-
import { mkdirSync as
|
|
16900
|
+
import { mkdirSync as mkdirSync6, readFileSync as readFileSync26, writeFileSync as writeFileSync11 } from "fs";
|
|
16793
16901
|
import { dirname as dirname7 } from "path";
|
|
16794
16902
|
var TOKEN_PREFIX = "v1.";
|
|
16795
16903
|
var SECRET_BYTES = 32;
|
|
@@ -16798,7 +16906,7 @@ var cachedSecret = null;
|
|
|
16798
16906
|
function getSecret() {
|
|
16799
16907
|
if (cachedSecret) return cachedSecret;
|
|
16800
16908
|
try {
|
|
16801
|
-
const hex2 =
|
|
16909
|
+
const hex2 = readFileSync26(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
16802
16910
|
if (hex2.length === SECRET_BYTES * 2) {
|
|
16803
16911
|
cachedSecret = Buffer.from(hex2, "hex");
|
|
16804
16912
|
return cachedSecret;
|
|
@@ -16807,12 +16915,12 @@ function getSecret() {
|
|
|
16807
16915
|
}
|
|
16808
16916
|
const fresh = randomBytes(SECRET_BYTES).toString("hex");
|
|
16809
16917
|
try {
|
|
16810
|
-
|
|
16811
|
-
|
|
16918
|
+
mkdirSync6(dirname7(VISITOR_TOKEN_SECRET_FILE), { recursive: true, mode: 448 });
|
|
16919
|
+
writeFileSync11(VISITOR_TOKEN_SECRET_FILE, fresh, { mode: 384, flag: "wx" });
|
|
16812
16920
|
console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
|
|
16813
16921
|
} catch {
|
|
16814
16922
|
}
|
|
16815
|
-
const hex =
|
|
16923
|
+
const hex = readFileSync26(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
16816
16924
|
cachedSecret = Buffer.from(hex, "hex");
|
|
16817
16925
|
return cachedSecret;
|
|
16818
16926
|
}
|
|
@@ -16865,8 +16973,8 @@ var VISITOR_COOKIE_NAME = "mxy_v";
|
|
|
16865
16973
|
var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
|
|
16866
16974
|
|
|
16867
16975
|
// app/lib/brand-config.ts
|
|
16868
|
-
import { existsSync as
|
|
16869
|
-
import { join as
|
|
16976
|
+
import { existsSync as existsSync27, readFileSync as readFileSync27 } from "fs";
|
|
16977
|
+
import { join as join25 } from "path";
|
|
16870
16978
|
var cached2 = null;
|
|
16871
16979
|
var cachedAttempted = false;
|
|
16872
16980
|
function readBrandConfig() {
|
|
@@ -16874,10 +16982,10 @@ function readBrandConfig() {
|
|
|
16874
16982
|
cachedAttempted = true;
|
|
16875
16983
|
const platformRoot2 = process.env.MAXY_PLATFORM_ROOT;
|
|
16876
16984
|
if (!platformRoot2) return null;
|
|
16877
|
-
const brandPath =
|
|
16878
|
-
if (!
|
|
16985
|
+
const brandPath = join25(platformRoot2, "config", "brand.json");
|
|
16986
|
+
if (!existsSync27(brandPath)) return null;
|
|
16879
16987
|
try {
|
|
16880
|
-
cached2 = JSON.parse(
|
|
16988
|
+
cached2 = JSON.parse(readFileSync27(brandPath, "utf-8"));
|
|
16881
16989
|
return cached2;
|
|
16882
16990
|
} catch {
|
|
16883
16991
|
return null;
|
|
@@ -16885,7 +16993,7 @@ function readBrandConfig() {
|
|
|
16885
16993
|
}
|
|
16886
16994
|
|
|
16887
16995
|
// server/routes/visitor-consent.ts
|
|
16888
|
-
var
|
|
16996
|
+
var app48 = new Hono();
|
|
16889
16997
|
var CONSENT_COOKIE_NAME = "mxy_consent";
|
|
16890
16998
|
var CONSENT_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365;
|
|
16891
16999
|
var DEFAULT_CONSENT_COPY = {
|
|
@@ -16930,17 +17038,17 @@ function siteSlugFromReferer(referer) {
|
|
|
16930
17038
|
return "";
|
|
16931
17039
|
}
|
|
16932
17040
|
}
|
|
16933
|
-
|
|
17041
|
+
app48.options("/consent", (c) => {
|
|
16934
17042
|
const origin = getOrigin(c);
|
|
16935
17043
|
setCorsHeaders(c, origin);
|
|
16936
17044
|
return c.body(null, 204);
|
|
16937
17045
|
});
|
|
16938
|
-
|
|
17046
|
+
app48.options("/brand-config", (c) => {
|
|
16939
17047
|
const origin = getOrigin(c);
|
|
16940
17048
|
setCorsHeaders(c, origin);
|
|
16941
17049
|
return c.body(null, 204);
|
|
16942
17050
|
});
|
|
16943
|
-
|
|
17051
|
+
app48.post("/consent", async (c) => {
|
|
16944
17052
|
const origin = getOrigin(c);
|
|
16945
17053
|
setCorsHeaders(c, origin);
|
|
16946
17054
|
let raw;
|
|
@@ -16980,7 +17088,7 @@ app47.post("/consent", async (c) => {
|
|
|
16980
17088
|
console.log(`[consent] ${parsed.decision} site=${site} brand=${brandName} tokenBound=${tokenBound}`);
|
|
16981
17089
|
return c.body(null, 204);
|
|
16982
17090
|
});
|
|
16983
|
-
|
|
17091
|
+
app48.get("/brand-config", (c) => {
|
|
16984
17092
|
const origin = getOrigin(c);
|
|
16985
17093
|
setCorsHeaders(c, origin);
|
|
16986
17094
|
const brand = readBrandConfig();
|
|
@@ -16990,7 +17098,7 @@ app47.get("/brand-config", (c) => {
|
|
|
16990
17098
|
c.header("Cache-Control", "public, max-age=300");
|
|
16991
17099
|
return c.json({ consent: { copy, palette } });
|
|
16992
17100
|
});
|
|
16993
|
-
var visitor_consent_default =
|
|
17101
|
+
var visitor_consent_default = app48;
|
|
16994
17102
|
|
|
16995
17103
|
// server/routes/listings.ts
|
|
16996
17104
|
function getCookie(headerValue, name) {
|
|
@@ -17017,8 +17125,8 @@ function appendConsentParams(pageUrl, token) {
|
|
|
17017
17125
|
}
|
|
17018
17126
|
var SAFE_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,118}[a-z0-9])?$/;
|
|
17019
17127
|
var CHAT_SESSION_KEY_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{7,127}$/;
|
|
17020
|
-
var
|
|
17021
|
-
|
|
17128
|
+
var app49 = new Hono();
|
|
17129
|
+
app49.get("/:slug/click", async (c) => {
|
|
17022
17130
|
const slug = c.req.param("slug") ?? "";
|
|
17023
17131
|
const rawSession = c.req.query("session") ?? "";
|
|
17024
17132
|
const sessionKey = CHAT_SESSION_KEY_RE.test(rawSession) ? rawSession : "invalid";
|
|
@@ -17082,10 +17190,10 @@ app48.get("/:slug/click", async (c) => {
|
|
|
17082
17190
|
console.log(`[property-card-click] sessionKey=${sessionKey} listingSlug=${slug} consent=${consentCookie ?? "absent"} ts=${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
17083
17191
|
return c.redirect(redirectUrl, 302);
|
|
17084
17192
|
});
|
|
17085
|
-
var listings_default =
|
|
17193
|
+
var listings_default = app49;
|
|
17086
17194
|
|
|
17087
17195
|
// server/routes/visitor-event.ts
|
|
17088
|
-
var
|
|
17196
|
+
var app50 = new Hono();
|
|
17089
17197
|
var BOT_UA_RE = /\b(bot|crawl|spider|slurp|headlesschrome|phantomjs|googlebot|bingbot|yandex|baiduspider|ahrefsbot|semrushbot|mj12bot|dotbot|petalbot)\b/i;
|
|
17090
17198
|
var buckets = /* @__PURE__ */ new Map();
|
|
17091
17199
|
var RATE_LIMIT = 60;
|
|
@@ -17152,12 +17260,12 @@ function originAllowed(origin, allowlist) {
|
|
|
17152
17260
|
return false;
|
|
17153
17261
|
}
|
|
17154
17262
|
}
|
|
17155
|
-
|
|
17263
|
+
app50.options("/event", (c) => {
|
|
17156
17264
|
const origin = getOrigin2(c);
|
|
17157
17265
|
setCorsHeaders2(c, origin);
|
|
17158
17266
|
return c.body(null, 204);
|
|
17159
17267
|
});
|
|
17160
|
-
|
|
17268
|
+
app50.post("/event", async (c) => {
|
|
17161
17269
|
const origin = getOrigin2(c);
|
|
17162
17270
|
setCorsHeaders2(c, origin);
|
|
17163
17271
|
const ua = c.req.header("user-agent") ?? "";
|
|
@@ -17362,17 +17470,17 @@ async function writeEvent(opts) {
|
|
|
17362
17470
|
);
|
|
17363
17471
|
}
|
|
17364
17472
|
}
|
|
17365
|
-
var visitor_event_default =
|
|
17473
|
+
var visitor_event_default = app50;
|
|
17366
17474
|
|
|
17367
17475
|
// server/routes/session.ts
|
|
17368
17476
|
import { resolve as resolve27 } from "path";
|
|
17369
|
-
import { existsSync as
|
|
17477
|
+
import { existsSync as existsSync28, writeFileSync as writeFileSync12, mkdirSync as mkdirSync7 } from "fs";
|
|
17370
17478
|
var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
17371
17479
|
function writeBrandingCache(accountId, agentSlug, branding) {
|
|
17372
17480
|
try {
|
|
17373
17481
|
const cacheDir = resolve27(MAXY_DIR, "branding-cache", accountId);
|
|
17374
|
-
|
|
17375
|
-
|
|
17482
|
+
mkdirSync7(cacheDir, { recursive: true });
|
|
17483
|
+
writeFileSync12(resolve27(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
|
|
17376
17484
|
} catch (err) {
|
|
17377
17485
|
console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
17378
17486
|
}
|
|
@@ -17408,8 +17516,8 @@ function withVisitorCookie(response, visitorId) {
|
|
|
17408
17516
|
headers
|
|
17409
17517
|
});
|
|
17410
17518
|
}
|
|
17411
|
-
var
|
|
17412
|
-
|
|
17519
|
+
var app51 = new Hono();
|
|
17520
|
+
app51.post("/", async (c) => {
|
|
17413
17521
|
let body;
|
|
17414
17522
|
try {
|
|
17415
17523
|
body = await c.req.json();
|
|
@@ -17461,7 +17569,7 @@ app50.post("/", async (c) => {
|
|
|
17461
17569
|
let agentConfig = null;
|
|
17462
17570
|
if (account) {
|
|
17463
17571
|
const agentDir = resolve27(account.accountDir, "agents", agentSlug);
|
|
17464
|
-
if (!
|
|
17572
|
+
if (!existsSync28(agentDir) || !existsSync28(resolve27(agentDir, "config.json"))) {
|
|
17465
17573
|
return c.json({ error: "Agent not found" }, 404);
|
|
17466
17574
|
}
|
|
17467
17575
|
agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
|
|
@@ -17620,7 +17728,7 @@ app50.post("/", async (c) => {
|
|
|
17620
17728
|
newVisitorId
|
|
17621
17729
|
);
|
|
17622
17730
|
});
|
|
17623
|
-
var session_default2 =
|
|
17731
|
+
var session_default2 = app51;
|
|
17624
17732
|
|
|
17625
17733
|
// app/lib/graph-health.ts
|
|
17626
17734
|
var import_dist4 = __toESM(require_dist3(), 1);
|
|
@@ -17967,8 +18075,8 @@ async function migrateUploads(opts = {}) {
|
|
|
17967
18075
|
|
|
17968
18076
|
// app/lib/migrate-admin-webchat-sidecars.ts
|
|
17969
18077
|
import { readdir as readdir6, readFile as readFile6, rename as rename3, writeFile as writeFile4, unlink as unlink3 } from "fs/promises";
|
|
17970
|
-
import { existsSync as
|
|
17971
|
-
import { join as
|
|
18078
|
+
import { existsSync as existsSync29 } from "fs";
|
|
18079
|
+
import { join as join26 } from "path";
|
|
17972
18080
|
var ADMIN_ROLE2 = "admin";
|
|
17973
18081
|
var WEBCHAT_CHANNEL2 = "webchat";
|
|
17974
18082
|
var SESSION_META_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.meta\.json$/i;
|
|
@@ -17997,7 +18105,7 @@ async function writeRaw(path2, obj) {
|
|
|
17997
18105
|
await rename3(tmp, path2);
|
|
17998
18106
|
} catch (err) {
|
|
17999
18107
|
try {
|
|
18000
|
-
if (
|
|
18108
|
+
if (existsSync29(tmp)) await unlink3(tmp);
|
|
18001
18109
|
} catch {
|
|
18002
18110
|
}
|
|
18003
18111
|
throw err;
|
|
@@ -18013,7 +18121,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
18013
18121
|
}
|
|
18014
18122
|
for (const slug of slugs) {
|
|
18015
18123
|
if (!slug.isDirectory()) continue;
|
|
18016
|
-
const slugDir =
|
|
18124
|
+
const slugDir = join26(projectsRoot, slug.name);
|
|
18017
18125
|
let entries;
|
|
18018
18126
|
try {
|
|
18019
18127
|
entries = await readdir6(slugDir, { withFileTypes: true });
|
|
@@ -18022,9 +18130,9 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
18022
18130
|
}
|
|
18023
18131
|
for (const entry of entries) {
|
|
18024
18132
|
if (entry.isFile() && SESSION_META_RE.test(entry.name)) {
|
|
18025
|
-
out.push(
|
|
18133
|
+
out.push(join26(slugDir, entry.name));
|
|
18026
18134
|
} else if (entry.isDirectory() && entry.name === "subagents") {
|
|
18027
|
-
const subDir =
|
|
18135
|
+
const subDir = join26(slugDir, entry.name);
|
|
18028
18136
|
let subs;
|
|
18029
18137
|
try {
|
|
18030
18138
|
subs = await readdir6(subDir, { withFileTypes: true });
|
|
@@ -18032,7 +18140,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
18032
18140
|
continue;
|
|
18033
18141
|
}
|
|
18034
18142
|
for (const s of subs) {
|
|
18035
|
-
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(
|
|
18143
|
+
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join26(subDir, s.name));
|
|
18036
18144
|
}
|
|
18037
18145
|
}
|
|
18038
18146
|
}
|
|
@@ -18044,7 +18152,7 @@ function shortId(path2) {
|
|
|
18044
18152
|
return base.slice(0, 8);
|
|
18045
18153
|
}
|
|
18046
18154
|
async function migrateAdminWebchatSidecars(opts = {}) {
|
|
18047
|
-
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ?
|
|
18155
|
+
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join26(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
|
|
18048
18156
|
const usersFile = opts.usersFile ?? USERS_FILE;
|
|
18049
18157
|
const accountId = opts.accountId ?? resolveAccount()?.accountId ?? null;
|
|
18050
18158
|
const resolveName = opts.resolveName ?? defaultResolveName;
|
|
@@ -18386,8 +18494,8 @@ var streamSSE = (c, cb, onError) => {
|
|
|
18386
18494
|
|
|
18387
18495
|
// app/lib/whatsapp/gateway/routes.ts
|
|
18388
18496
|
function createWaChannelRoutes(deps) {
|
|
18389
|
-
const
|
|
18390
|
-
|
|
18497
|
+
const app53 = new Hono();
|
|
18498
|
+
app53.get("/wa-channel/inbound", (c) => {
|
|
18391
18499
|
const senderId = c.req.query("senderId");
|
|
18392
18500
|
if (!senderId) return c.json({ error: "senderId required" }, 400);
|
|
18393
18501
|
return streamSSE(c, async (stream2) => {
|
|
@@ -18405,7 +18513,7 @@ function createWaChannelRoutes(deps) {
|
|
|
18405
18513
|
}
|
|
18406
18514
|
});
|
|
18407
18515
|
});
|
|
18408
|
-
|
|
18516
|
+
app53.post("/wa-channel/reply", async (c) => {
|
|
18409
18517
|
const body = await c.req.json().catch(() => null);
|
|
18410
18518
|
const senderId = body?.senderId;
|
|
18411
18519
|
const text = body?.text;
|
|
@@ -18426,7 +18534,7 @@ function createWaChannelRoutes(deps) {
|
|
|
18426
18534
|
console.error(`[whatsapp-native] op=reply-dispatch senderId=${senderId} bytes=${bytes}`);
|
|
18427
18535
|
return c.json({ ok: true });
|
|
18428
18536
|
});
|
|
18429
|
-
|
|
18537
|
+
app53.post("/wa-channel/reply-document", async (c) => {
|
|
18430
18538
|
const body = await c.req.json().catch(() => null);
|
|
18431
18539
|
const senderId = body?.senderId;
|
|
18432
18540
|
const files = body?.files;
|
|
@@ -18465,7 +18573,7 @@ function createWaChannelRoutes(deps) {
|
|
|
18465
18573
|
}
|
|
18466
18574
|
return c.json({ ok: true, results });
|
|
18467
18575
|
});
|
|
18468
|
-
|
|
18576
|
+
app53.post("/wa-channel/ready", async (c) => {
|
|
18469
18577
|
const body = await c.req.json().catch(() => null);
|
|
18470
18578
|
const senderId = body?.senderId;
|
|
18471
18579
|
if (typeof senderId !== "string") {
|
|
@@ -18474,7 +18582,7 @@ function createWaChannelRoutes(deps) {
|
|
|
18474
18582
|
deps.onReady?.(senderId);
|
|
18475
18583
|
return c.json({ ok: true });
|
|
18476
18584
|
});
|
|
18477
|
-
|
|
18585
|
+
app53.post("/wa-channel/received", async (c) => {
|
|
18478
18586
|
const body = await c.req.json().catch(() => null);
|
|
18479
18587
|
const senderId = body?.senderId;
|
|
18480
18588
|
const waMessageId = body?.waMessageId;
|
|
@@ -18484,7 +18592,7 @@ function createWaChannelRoutes(deps) {
|
|
|
18484
18592
|
deps.onReceived?.(senderId, waMessageId);
|
|
18485
18593
|
return c.json({ ok: true });
|
|
18486
18594
|
});
|
|
18487
|
-
|
|
18595
|
+
app53.post("/wa-channel/turn-end", async (c) => {
|
|
18488
18596
|
const body = await c.req.json().catch(() => null);
|
|
18489
18597
|
const senderId = body?.senderId;
|
|
18490
18598
|
const sessionId = body?.sessionId;
|
|
@@ -18515,7 +18623,7 @@ function createWaChannelRoutes(deps) {
|
|
|
18515
18623
|
console.error(`[whatsapp-native] op=turn-end sessionId=${sid} replied=no delivered=fallback bytes=${bytes}`);
|
|
18516
18624
|
return c.json({ ok: true, delivered: "fallback" });
|
|
18517
18625
|
});
|
|
18518
|
-
return
|
|
18626
|
+
return app53;
|
|
18519
18627
|
}
|
|
18520
18628
|
|
|
18521
18629
|
// app/lib/whatsapp/gateway/wa-gateway.ts
|
|
@@ -18768,8 +18876,8 @@ var InboundHub2 = class {
|
|
|
18768
18876
|
|
|
18769
18877
|
// app/lib/webchat/gateway/routes.ts
|
|
18770
18878
|
function createWebchatChannelRoutes(deps) {
|
|
18771
|
-
const
|
|
18772
|
-
|
|
18879
|
+
const app53 = new Hono();
|
|
18880
|
+
app53.get("/webchat-channel/inbound", (c) => {
|
|
18773
18881
|
const key = c.req.query("key");
|
|
18774
18882
|
if (!key) return c.json({ error: "key required" }, 400);
|
|
18775
18883
|
return streamSSE(c, async (stream2) => {
|
|
@@ -18787,7 +18895,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
18787
18895
|
}
|
|
18788
18896
|
});
|
|
18789
18897
|
});
|
|
18790
|
-
|
|
18898
|
+
app53.post("/webchat-channel/reply", async (c) => {
|
|
18791
18899
|
const body = await c.req.json().catch(() => null);
|
|
18792
18900
|
const key = body?.key;
|
|
18793
18901
|
const text = body?.text;
|
|
@@ -18797,7 +18905,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
18797
18905
|
deps.onReply?.(key, text);
|
|
18798
18906
|
return c.json({ ok: true });
|
|
18799
18907
|
});
|
|
18800
|
-
|
|
18908
|
+
app53.post("/webchat-channel/ready", async (c) => {
|
|
18801
18909
|
const body = await c.req.json().catch(() => null);
|
|
18802
18910
|
const key = body?.key;
|
|
18803
18911
|
if (typeof key !== "string") {
|
|
@@ -18806,7 +18914,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
18806
18914
|
deps.onReady?.(key);
|
|
18807
18915
|
return c.json({ ok: true });
|
|
18808
18916
|
});
|
|
18809
|
-
|
|
18917
|
+
app53.post("/webchat-channel/received", async (c) => {
|
|
18810
18918
|
const body = await c.req.json().catch(() => null);
|
|
18811
18919
|
const key = body?.key;
|
|
18812
18920
|
const messageId = body?.messageId;
|
|
@@ -18816,7 +18924,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
18816
18924
|
deps.onReceived?.(key, messageId);
|
|
18817
18925
|
return c.json({ ok: true });
|
|
18818
18926
|
});
|
|
18819
|
-
return
|
|
18927
|
+
return app53;
|
|
18820
18928
|
}
|
|
18821
18929
|
|
|
18822
18930
|
// app/lib/webchat/gateway/webchat-gateway.ts
|
|
@@ -19129,7 +19237,7 @@ function broadcastAdminShutdown(reason) {
|
|
|
19129
19237
|
|
|
19130
19238
|
// ../lib/entitlement/src/index.ts
|
|
19131
19239
|
import { createPublicKey, createHash as createHash5, verify as cryptoVerify } from "crypto";
|
|
19132
|
-
import { existsSync as
|
|
19240
|
+
import { existsSync as existsSync30, readFileSync as readFileSync28, statSync as statSync12 } from "fs";
|
|
19133
19241
|
import { resolve as resolve30 } from "path";
|
|
19134
19242
|
|
|
19135
19243
|
// ../lib/entitlement/src/canonicalize.ts
|
|
@@ -19178,7 +19286,7 @@ function resolveEntitlement(brand, account) {
|
|
|
19178
19286
|
return logResolved(implicitTrust(account), null);
|
|
19179
19287
|
}
|
|
19180
19288
|
const entitlementPath = resolve30(brand.configDir, "entitlement.json");
|
|
19181
|
-
if (!
|
|
19289
|
+
if (!existsSync30(entitlementPath)) {
|
|
19182
19290
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
19183
19291
|
}
|
|
19184
19292
|
const stat7 = statSync12(entitlementPath);
|
|
@@ -19193,7 +19301,7 @@ function resolveEntitlement(brand, account) {
|
|
|
19193
19301
|
function verifyAndResolve(brand, entitlementPath, account) {
|
|
19194
19302
|
let pubkeyPem;
|
|
19195
19303
|
try {
|
|
19196
|
-
pubkeyPem =
|
|
19304
|
+
pubkeyPem = readFileSync28(pubkeyPath(brand), "utf-8");
|
|
19197
19305
|
} catch (err) {
|
|
19198
19306
|
return logResolved(anonymousFallback("pubkey-missing"), {
|
|
19199
19307
|
reason: "pubkey-missing"
|
|
@@ -19207,7 +19315,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
|
|
|
19207
19315
|
}
|
|
19208
19316
|
let envelope;
|
|
19209
19317
|
try {
|
|
19210
|
-
envelope = JSON.parse(
|
|
19318
|
+
envelope = JSON.parse(readFileSync28(entitlementPath, "utf-8"));
|
|
19211
19319
|
} catch {
|
|
19212
19320
|
return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
|
|
19213
19321
|
}
|
|
@@ -19368,14 +19476,14 @@ function clientFrom(c) {
|
|
|
19368
19476
|
);
|
|
19369
19477
|
}
|
|
19370
19478
|
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
19371
|
-
var BRAND_JSON_PATH = PLATFORM_ROOT8 ?
|
|
19479
|
+
var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join27(PLATFORM_ROOT8, "config", "brand.json") : "";
|
|
19372
19480
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
19373
|
-
if (BRAND_JSON_PATH && !
|
|
19481
|
+
if (BRAND_JSON_PATH && !existsSync31(BRAND_JSON_PATH)) {
|
|
19374
19482
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
19375
19483
|
}
|
|
19376
|
-
if (BRAND_JSON_PATH &&
|
|
19484
|
+
if (BRAND_JSON_PATH && existsSync31(BRAND_JSON_PATH)) {
|
|
19377
19485
|
try {
|
|
19378
|
-
const parsed = JSON.parse(
|
|
19486
|
+
const parsed = JSON.parse(readFileSync29(BRAND_JSON_PATH, "utf-8"));
|
|
19379
19487
|
BRAND = { ...BRAND, ...parsed };
|
|
19380
19488
|
} catch (err) {
|
|
19381
19489
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -19394,11 +19502,11 @@ var brandLoginOpts = {
|
|
|
19394
19502
|
bodyFont: BRAND.defaultFonts?.body,
|
|
19395
19503
|
logoContainsName: !!BRAND.logoContainsName
|
|
19396
19504
|
};
|
|
19397
|
-
var ALIAS_DOMAINS_PATH =
|
|
19505
|
+
var ALIAS_DOMAINS_PATH = join27(homedir3(), BRAND.configDir, "alias-domains.json");
|
|
19398
19506
|
function loadAliasDomains() {
|
|
19399
19507
|
try {
|
|
19400
|
-
if (!
|
|
19401
|
-
const parsed = JSON.parse(
|
|
19508
|
+
if (!existsSync31(ALIAS_DOMAINS_PATH)) return null;
|
|
19509
|
+
const parsed = JSON.parse(readFileSync29(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
19402
19510
|
if (!Array.isArray(parsed)) {
|
|
19403
19511
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
19404
19512
|
return null;
|
|
@@ -19422,11 +19530,11 @@ watchFile(ALIAS_DOMAINS_PATH, { interval: 2e3 }, () => {
|
|
|
19422
19530
|
function isPublicHost(host) {
|
|
19423
19531
|
return host.startsWith("public.") || aliasDomains.has(host);
|
|
19424
19532
|
}
|
|
19425
|
-
var
|
|
19533
|
+
var app52 = new Hono();
|
|
19426
19534
|
var nativeFileFollowers = /* @__PURE__ */ new Map();
|
|
19427
19535
|
var waGateway = new WaGateway({
|
|
19428
19536
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
19429
|
-
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve31(process.env.MAXY_PLATFORM_ROOT ??
|
|
19537
|
+
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve31(process.env.MAXY_PLATFORM_ROOT ?? join27(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
19430
19538
|
// Task 751 — file delivery on the native channel: resolve the platform
|
|
19431
19539
|
// account + path validation here and funnel through the shared send core.
|
|
19432
19540
|
sendDocument: async ({ senderId, accountId, filePath, caption }) => {
|
|
@@ -19442,7 +19550,7 @@ var waGateway = new WaGateway({
|
|
|
19442
19550
|
caption,
|
|
19443
19551
|
accountId,
|
|
19444
19552
|
maxyAccountId,
|
|
19445
|
-
platformRoot: resolve31(process.env.MAXY_PLATFORM_ROOT ??
|
|
19553
|
+
platformRoot: resolve31(process.env.MAXY_PLATFORM_ROOT ?? join27(__dirname, ".."))
|
|
19446
19554
|
});
|
|
19447
19555
|
return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
|
|
19448
19556
|
},
|
|
@@ -19472,7 +19580,7 @@ var waGateway = new WaGateway({
|
|
|
19472
19580
|
nativeFileFollowers.set(senderId, ac);
|
|
19473
19581
|
}
|
|
19474
19582
|
});
|
|
19475
|
-
|
|
19583
|
+
app52.route("/", waGateway.routes());
|
|
19476
19584
|
waGateway.startSweeper();
|
|
19477
19585
|
var webchatGateway = new WebchatGateway({
|
|
19478
19586
|
gatewayUrl: webchatGatewayUrl(),
|
|
@@ -19512,15 +19620,15 @@ var webchatGateway = new WebchatGateway({
|
|
|
19512
19620
|
deleteSession: (sessionId) => managerDelete(sessionId),
|
|
19513
19621
|
firePublicSessionEndReview: (input) => firePublicSessionEndReview(input)
|
|
19514
19622
|
});
|
|
19515
|
-
|
|
19623
|
+
app52.route("/", webchatGateway.routes());
|
|
19516
19624
|
webchatGateway.startSweeper();
|
|
19517
19625
|
webchatGateway.startPublicReaper();
|
|
19518
19626
|
var chatRoutes = createChatRoutes({
|
|
19519
19627
|
handleInbound: (input) => webchatGateway.handleInbound(input),
|
|
19520
19628
|
awaitReply: (key, timeoutMs) => webchatGateway.awaitReply(key, timeoutMs)
|
|
19521
19629
|
});
|
|
19522
|
-
|
|
19523
|
-
|
|
19630
|
+
app52.use("*", clientIpMiddleware);
|
|
19631
|
+
app52.use("*", async (c, next) => {
|
|
19524
19632
|
await next();
|
|
19525
19633
|
c.header("X-Content-Type-Options", "nosniff");
|
|
19526
19634
|
c.header("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
@@ -19530,7 +19638,7 @@ app51.use("*", async (c, next) => {
|
|
|
19530
19638
|
);
|
|
19531
19639
|
});
|
|
19532
19640
|
var HTTP_LOG_PATHS = /* @__PURE__ */ new Set(["/vnc-viewer.html", "/vnc-popout.html"]);
|
|
19533
|
-
|
|
19641
|
+
app52.use("*", async (c, next) => {
|
|
19534
19642
|
if (!HTTP_LOG_PATHS.has(c.req.path)) {
|
|
19535
19643
|
await next();
|
|
19536
19644
|
return;
|
|
@@ -19548,7 +19656,7 @@ app51.use("*", async (c, next) => {
|
|
|
19548
19656
|
});
|
|
19549
19657
|
}
|
|
19550
19658
|
});
|
|
19551
|
-
|
|
19659
|
+
app52.use("*", async (c, next) => {
|
|
19552
19660
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
19553
19661
|
if (isOperatorHost(host, getOperatorDomains()) || !isPublicHost(host)) {
|
|
19554
19662
|
await next();
|
|
@@ -19579,7 +19687,7 @@ function resolveRemoteAuthOpts() {
|
|
|
19579
19687
|
return brandLoginOpts;
|
|
19580
19688
|
}
|
|
19581
19689
|
var MAX_LOGIN_BODY = 8 * 1024;
|
|
19582
|
-
|
|
19690
|
+
app52.post("/__remote-auth/login", async (c) => {
|
|
19583
19691
|
const client = clientFrom(c);
|
|
19584
19692
|
const clientIp = client.ip || "unknown";
|
|
19585
19693
|
if (!requestIsTlsTerminated(c)) {
|
|
@@ -19624,7 +19732,7 @@ app51.post("/__remote-auth/login", async (c) => {
|
|
|
19624
19732
|
}
|
|
19625
19733
|
});
|
|
19626
19734
|
});
|
|
19627
|
-
|
|
19735
|
+
app52.get("/__remote-auth/logout", (c) => {
|
|
19628
19736
|
const client = clientFrom(c);
|
|
19629
19737
|
const clientIp = client.ip || "unknown";
|
|
19630
19738
|
console.error(`[remote-auth] logout ip=${clientIp}`);
|
|
@@ -19637,7 +19745,7 @@ app51.get("/__remote-auth/logout", (c) => {
|
|
|
19637
19745
|
}
|
|
19638
19746
|
});
|
|
19639
19747
|
});
|
|
19640
|
-
|
|
19748
|
+
app52.post("/__remote-auth/change-password", async (c) => {
|
|
19641
19749
|
const client = clientFrom(c);
|
|
19642
19750
|
const clientIp = client.ip || "unknown";
|
|
19643
19751
|
const rateLimited = checkRateLimit(client);
|
|
@@ -19696,13 +19804,13 @@ app51.post("/__remote-auth/change-password", async (c) => {
|
|
|
19696
19804
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "change", changeError: "Failed to save password", redirect }), 200);
|
|
19697
19805
|
}
|
|
19698
19806
|
});
|
|
19699
|
-
|
|
19807
|
+
app52.get("/__remote-auth/setup", (c) => {
|
|
19700
19808
|
if (isRemoteAuthConfigured()) {
|
|
19701
19809
|
return c.redirect("/");
|
|
19702
19810
|
}
|
|
19703
19811
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup" }), 200);
|
|
19704
19812
|
});
|
|
19705
|
-
|
|
19813
|
+
app52.post("/__remote-auth/set-initial-password", async (c) => {
|
|
19706
19814
|
if (isRemoteAuthConfigured()) {
|
|
19707
19815
|
return c.redirect("/");
|
|
19708
19816
|
}
|
|
@@ -19740,10 +19848,10 @@ app51.post("/__remote-auth/set-initial-password", async (c) => {
|
|
|
19740
19848
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
|
|
19741
19849
|
}
|
|
19742
19850
|
});
|
|
19743
|
-
|
|
19851
|
+
app52.get("/api/remote-auth/status", (c) => {
|
|
19744
19852
|
return c.json({ configured: isRemoteAuthConfigured() });
|
|
19745
19853
|
});
|
|
19746
|
-
|
|
19854
|
+
app52.post("/api/remote-auth/set-password", async (c) => {
|
|
19747
19855
|
let body;
|
|
19748
19856
|
try {
|
|
19749
19857
|
body = await c.req.json();
|
|
@@ -19782,10 +19890,10 @@ app51.post("/api/remote-auth/set-password", async (c) => {
|
|
|
19782
19890
|
return c.json({ error: "Failed to save password" }, 500);
|
|
19783
19891
|
}
|
|
19784
19892
|
});
|
|
19785
|
-
|
|
19893
|
+
app52.route("/api/_client-error", client_error_default);
|
|
19786
19894
|
console.log("[client-error-route] mounted");
|
|
19787
19895
|
var PWA_PUBLIC_PATHS = /* @__PURE__ */ new Set(["/sw.js", ...PWA_SURFACES.map((s) => s.manifestPath)]);
|
|
19788
|
-
|
|
19896
|
+
app52.use("*", async (c, next) => {
|
|
19789
19897
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
19790
19898
|
const path2 = c.req.path;
|
|
19791
19899
|
if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/") || PWA_PUBLIC_PATHS.has(path2)) {
|
|
@@ -19825,18 +19933,19 @@ app51.use("*", async (c, next) => {
|
|
|
19825
19933
|
}
|
|
19826
19934
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), redirect: path2 }), 200);
|
|
19827
19935
|
});
|
|
19828
|
-
|
|
19829
|
-
|
|
19830
|
-
|
|
19831
|
-
|
|
19832
|
-
|
|
19833
|
-
|
|
19834
|
-
|
|
19835
|
-
|
|
19836
|
-
|
|
19837
|
-
|
|
19838
|
-
|
|
19839
|
-
|
|
19936
|
+
app52.route("/api/health", health_default);
|
|
19937
|
+
app52.route("/api/chat", chatRoutes);
|
|
19938
|
+
app52.route("/api/whatsapp", whatsapp_default);
|
|
19939
|
+
app52.route("/api/whatsapp-reader", whatsapp_reader_default);
|
|
19940
|
+
app52.route("/api/public-reader", public_reader_default);
|
|
19941
|
+
app52.route("/api/webchat", createWebchatRoutes({ handleInbound: (input) => webchatGateway.handleInbound(input) }));
|
|
19942
|
+
app52.route("/api/webchat/greeting", webchat_greeting_default);
|
|
19943
|
+
app52.route("/api/telegram", telegram_default);
|
|
19944
|
+
app52.route("/api/quickbooks", quickbooks_default);
|
|
19945
|
+
app52.route("/api/onboarding", onboarding_default);
|
|
19946
|
+
app52.route("/api/admin", admin_default);
|
|
19947
|
+
app52.route("/api/access", access_default);
|
|
19948
|
+
app52.route("/api/session", session_default2);
|
|
19840
19949
|
var SAFE_SLUG_RE2 = /^[a-z][a-z0-9-]{2,49}$/;
|
|
19841
19950
|
var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
19842
19951
|
var IMAGE_MIME = {
|
|
@@ -19848,7 +19957,7 @@ var IMAGE_MIME = {
|
|
|
19848
19957
|
".svg": "image/svg+xml",
|
|
19849
19958
|
".ico": "image/x-icon"
|
|
19850
19959
|
};
|
|
19851
|
-
|
|
19960
|
+
app52.get("/agent-assets/:slug/:filename", (c) => {
|
|
19852
19961
|
const slug = c.req.param("slug");
|
|
19853
19962
|
const filename = c.req.param("filename");
|
|
19854
19963
|
if (!SAFE_SLUG_RE2.test(slug)) {
|
|
@@ -19870,20 +19979,20 @@ app51.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
19870
19979
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
19871
19980
|
return c.text("Forbidden", 403);
|
|
19872
19981
|
}
|
|
19873
|
-
if (!
|
|
19982
|
+
if (!existsSync31(filePath)) {
|
|
19874
19983
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
19875
19984
|
return c.text("Not found", 404);
|
|
19876
19985
|
}
|
|
19877
19986
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
19878
19987
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
19879
19988
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
19880
|
-
const body =
|
|
19989
|
+
const body = readFileSync29(filePath);
|
|
19881
19990
|
return c.body(body, 200, {
|
|
19882
19991
|
"Content-Type": contentType,
|
|
19883
19992
|
"Cache-Control": "public, max-age=3600"
|
|
19884
19993
|
});
|
|
19885
19994
|
});
|
|
19886
|
-
|
|
19995
|
+
app52.get("/generated/:filename", (c) => {
|
|
19887
19996
|
const filename = c.req.param("filename");
|
|
19888
19997
|
if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
|
|
19889
19998
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
@@ -19900,29 +20009,29 @@ app51.get("/generated/:filename", (c) => {
|
|
|
19900
20009
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
19901
20010
|
return c.text("Forbidden", 403);
|
|
19902
20011
|
}
|
|
19903
|
-
if (!
|
|
20012
|
+
if (!existsSync31(filePath)) {
|
|
19904
20013
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
19905
20014
|
return c.text("Not found", 404);
|
|
19906
20015
|
}
|
|
19907
20016
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
19908
20017
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
19909
20018
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
19910
|
-
const body =
|
|
20019
|
+
const body = readFileSync29(filePath);
|
|
19911
20020
|
return c.body(body, 200, {
|
|
19912
20021
|
"Content-Type": contentType,
|
|
19913
20022
|
"Cache-Control": "public, max-age=86400"
|
|
19914
20023
|
});
|
|
19915
20024
|
});
|
|
19916
|
-
|
|
19917
|
-
|
|
19918
|
-
|
|
19919
|
-
|
|
20025
|
+
app52.route("/sites", sites_default);
|
|
20026
|
+
app52.route("/listings", listings_default);
|
|
20027
|
+
app52.route("/v", visitor_event_default);
|
|
20028
|
+
app52.route("/v", visitor_consent_default);
|
|
19920
20029
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
19921
20030
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
19922
20031
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
19923
|
-
if (BRAND_JSON_PATH &&
|
|
20032
|
+
if (BRAND_JSON_PATH && existsSync31(BRAND_JSON_PATH)) {
|
|
19924
20033
|
try {
|
|
19925
|
-
const fullBrand = JSON.parse(
|
|
20034
|
+
const fullBrand = JSON.parse(readFileSync29(BRAND_JSON_PATH, "utf-8"));
|
|
19926
20035
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
19927
20036
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
19928
20037
|
} catch {
|
|
@@ -19939,10 +20048,10 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
19939
20048
|
var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
|
|
19940
20049
|
var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
|
|
19941
20050
|
var brandIconFsPath = resolve31(process.cwd(), "public", brandIconPath.replace(/^\//, ""));
|
|
19942
|
-
var brandIconExists =
|
|
20051
|
+
var brandIconExists = existsSync31(brandIconFsPath);
|
|
19943
20052
|
var SW_SOURCE = (() => {
|
|
19944
20053
|
try {
|
|
19945
|
-
return
|
|
20054
|
+
return readFileSync29(resolve31(process.cwd(), "public", "sw.js"), "utf-8");
|
|
19946
20055
|
} catch {
|
|
19947
20056
|
return null;
|
|
19948
20057
|
}
|
|
@@ -19950,9 +20059,9 @@ var SW_SOURCE = (() => {
|
|
|
19950
20059
|
function readInstalledVersion() {
|
|
19951
20060
|
try {
|
|
19952
20061
|
if (!PLATFORM_ROOT8) return "unknown";
|
|
19953
|
-
const versionFile =
|
|
19954
|
-
if (!
|
|
19955
|
-
const content =
|
|
20062
|
+
const versionFile = join27(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
|
|
20063
|
+
if (!existsSync31(versionFile)) return "unknown";
|
|
20064
|
+
const content = readFileSync29(versionFile, "utf-8").trim();
|
|
19956
20065
|
return content || "unknown";
|
|
19957
20066
|
} catch {
|
|
19958
20067
|
return "unknown";
|
|
@@ -19993,7 +20102,7 @@ var clientErrorReporterScript = `<script>
|
|
|
19993
20102
|
function cachedHtml(file) {
|
|
19994
20103
|
let html = htmlCache.get(file);
|
|
19995
20104
|
if (!html) {
|
|
19996
|
-
html =
|
|
20105
|
+
html = readFileSync29(resolve31(process.cwd(), "public", file), "utf-8");
|
|
19997
20106
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
19998
20107
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
19999
20108
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -20011,13 +20120,13 @@ ${clientErrorReporterScript}
|
|
|
20011
20120
|
}
|
|
20012
20121
|
var brandedHtmlCache = /* @__PURE__ */ new Map();
|
|
20013
20122
|
function loadBrandingCache(agentSlug) {
|
|
20014
|
-
const configDir2 =
|
|
20123
|
+
const configDir2 = join27(homedir3(), BRAND.configDir);
|
|
20015
20124
|
try {
|
|
20016
20125
|
const accountId = getDefaultAccountId();
|
|
20017
20126
|
if (!accountId) return null;
|
|
20018
|
-
const cachePath =
|
|
20019
|
-
if (!
|
|
20020
|
-
return JSON.parse(
|
|
20127
|
+
const cachePath = join27(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
20128
|
+
if (!existsSync31(cachePath)) return null;
|
|
20129
|
+
return JSON.parse(readFileSync29(cachePath, "utf-8"));
|
|
20021
20130
|
} catch {
|
|
20022
20131
|
return null;
|
|
20023
20132
|
}
|
|
@@ -20063,7 +20172,7 @@ function escapeHtml(s) {
|
|
|
20063
20172
|
function agentUnavailableHtml() {
|
|
20064
20173
|
return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>${escapeHtml(BRAND.productName)}</title></head><body style="font-family:system-ui,sans-serif;max-width:32rem;margin:4rem auto;padding:0 1.5rem;color:#222"><h1 style="font-size:1.25rem">Agent unavailable</h1><p>This agent isn't available right now. If you reached this page from a saved link, the agent may have been turned off.</p></body></html>`;
|
|
20065
20174
|
}
|
|
20066
|
-
|
|
20175
|
+
app52.get("/", (c) => {
|
|
20067
20176
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
20068
20177
|
const klass = classifyHost(host, getOperatorDomains(), isPublicHost);
|
|
20069
20178
|
if (klass === "operator") {
|
|
@@ -20086,13 +20195,13 @@ app51.get("/", (c) => {
|
|
|
20086
20195
|
console.log(`[host-class] host=${host} class=admin served=index.html`);
|
|
20087
20196
|
return c.html(cachedHtml("index.html"));
|
|
20088
20197
|
});
|
|
20089
|
-
|
|
20198
|
+
app52.get("/public", (c) => {
|
|
20090
20199
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
20091
20200
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
20092
20201
|
if (wantsNextSurface(c)) return c.html(cachedHtml("public-next.html"));
|
|
20093
20202
|
return c.html(cachedHtml("public.html"));
|
|
20094
20203
|
});
|
|
20095
|
-
|
|
20204
|
+
app52.get("/public-chat", (c) => {
|
|
20096
20205
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
20097
20206
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
20098
20207
|
if (wantsNextSurface(c)) return c.html(cachedHtml("public-next.html"));
|
|
@@ -20112,12 +20221,12 @@ async function logViewerFetch(c, next) {
|
|
|
20112
20221
|
duration_ms: Date.now() - start
|
|
20113
20222
|
});
|
|
20114
20223
|
}
|
|
20115
|
-
|
|
20116
|
-
|
|
20117
|
-
|
|
20224
|
+
app52.use("/vnc-viewer.html", logViewerFetch);
|
|
20225
|
+
app52.use("/vnc-popout.html", logViewerFetch);
|
|
20226
|
+
app52.get("/vnc-popout.html", (c) => {
|
|
20118
20227
|
let html = htmlCache.get("vnc-popout.html");
|
|
20119
20228
|
if (!html) {
|
|
20120
|
-
html =
|
|
20229
|
+
html = readFileSync29(resolve31(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
20121
20230
|
const name = escapeHtml(BRAND.productName);
|
|
20122
20231
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
20123
20232
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -20127,7 +20236,7 @@ app51.get("/vnc-popout.html", (c) => {
|
|
|
20127
20236
|
}
|
|
20128
20237
|
return c.html(html);
|
|
20129
20238
|
});
|
|
20130
|
-
|
|
20239
|
+
app52.post("/api/vnc/client-event", async (c) => {
|
|
20131
20240
|
let body;
|
|
20132
20241
|
try {
|
|
20133
20242
|
body = await c.req.json();
|
|
@@ -20148,11 +20257,11 @@ app51.post("/api/vnc/client-event", async (c) => {
|
|
|
20148
20257
|
});
|
|
20149
20258
|
return c.json({ ok: true });
|
|
20150
20259
|
});
|
|
20151
|
-
|
|
20260
|
+
app52.get("/g/:slug", (c) => {
|
|
20152
20261
|
return c.html(brandedPublicHtml());
|
|
20153
20262
|
});
|
|
20154
20263
|
for (const pwa of PWA_SURFACES) {
|
|
20155
|
-
|
|
20264
|
+
app52.get(pwa.manifestPath, (c) => {
|
|
20156
20265
|
const manifest = buildManifest(pwa, {
|
|
20157
20266
|
productName: BRAND.productName,
|
|
20158
20267
|
iconPath: brandIconPath,
|
|
@@ -20166,7 +20275,7 @@ for (const pwa of PWA_SURFACES) {
|
|
|
20166
20275
|
return c.body(JSON.stringify(manifest));
|
|
20167
20276
|
});
|
|
20168
20277
|
}
|
|
20169
|
-
|
|
20278
|
+
app52.get("/sw.js", (c) => {
|
|
20170
20279
|
if (SW_SOURCE == null) {
|
|
20171
20280
|
console.error("[pwa] op=sw status=500 reason=sw-source-missing");
|
|
20172
20281
|
return c.text("Service worker unavailable", 500);
|
|
@@ -20175,27 +20284,27 @@ app51.get("/sw.js", (c) => {
|
|
|
20175
20284
|
console.log(`[pwa] op=sw status=200 ct=${SW_CONTENT_TYPE}`);
|
|
20176
20285
|
return c.body(SW_SOURCE);
|
|
20177
20286
|
});
|
|
20178
|
-
|
|
20287
|
+
app52.get("/graph", (c) => {
|
|
20179
20288
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
20180
20289
|
if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
|
|
20181
20290
|
return c.html(cachedHtml("graph.html"));
|
|
20182
20291
|
});
|
|
20183
|
-
|
|
20292
|
+
app52.get("/chat", (c) => {
|
|
20184
20293
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
20185
20294
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
20186
20295
|
return c.html(cachedHtml("chat.html"));
|
|
20187
20296
|
});
|
|
20188
|
-
|
|
20297
|
+
app52.get("/data", (c) => {
|
|
20189
20298
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
20190
20299
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
20191
20300
|
return c.html(cachedHtml("data.html"));
|
|
20192
20301
|
});
|
|
20193
|
-
|
|
20302
|
+
app52.get("/browser", (c) => {
|
|
20194
20303
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
20195
20304
|
if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
|
|
20196
20305
|
return c.html(cachedHtml("browser.html"));
|
|
20197
20306
|
});
|
|
20198
|
-
|
|
20307
|
+
app52.get("/:slug", async (c, next) => {
|
|
20199
20308
|
const slug = c.req.param("slug");
|
|
20200
20309
|
if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
|
|
20201
20310
|
const account = resolveAccount();
|
|
@@ -20211,13 +20320,13 @@ app51.get("/:slug", async (c, next) => {
|
|
|
20211
20320
|
await next();
|
|
20212
20321
|
});
|
|
20213
20322
|
if (brandFaviconPath !== "/favicon.ico") {
|
|
20214
|
-
|
|
20323
|
+
app52.get("/favicon.ico", (c) => {
|
|
20215
20324
|
c.header("Cache-Control", "public, max-age=300");
|
|
20216
20325
|
return c.redirect(brandFaviconPath, 302);
|
|
20217
20326
|
});
|
|
20218
20327
|
}
|
|
20219
|
-
|
|
20220
|
-
|
|
20328
|
+
app52.use("/*", serveStatic({ root: "./public" }));
|
|
20329
|
+
app52.all("*", (c) => {
|
|
20221
20330
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
20222
20331
|
const path2 = c.req.path;
|
|
20223
20332
|
if (isPublicHost(host)) {
|
|
@@ -20231,7 +20340,7 @@ app51.all("*", (c) => {
|
|
|
20231
20340
|
});
|
|
20232
20341
|
var port = requirePortEnv("MAXY_UI_INTERNAL_PORT", { tag: "ui-server" });
|
|
20233
20342
|
var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
20234
|
-
var httpServer = serve({ fetch:
|
|
20343
|
+
var httpServer = serve({ fetch: app52.fetch, port, hostname });
|
|
20235
20344
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
20236
20345
|
{
|
|
20237
20346
|
const census = pwaCensus({
|
|
@@ -20285,7 +20394,7 @@ for (const m of SUBAPP_MANIFEST) {
|
|
|
20285
20394
|
}
|
|
20286
20395
|
try {
|
|
20287
20396
|
const registered = [];
|
|
20288
|
-
for (const r of
|
|
20397
|
+
for (const r of app52.routes ?? []) {
|
|
20289
20398
|
if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
|
|
20290
20399
|
if (AGENT_SLUG_PATTERN.test(r.path)) {
|
|
20291
20400
|
registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
|
|
@@ -20325,11 +20434,11 @@ try {
|
|
|
20325
20434
|
var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
20326
20435
|
async function runAdminUserReconcileTick() {
|
|
20327
20436
|
try {
|
|
20328
|
-
if (!
|
|
20437
|
+
if (!existsSync31(USERS_FILE)) {
|
|
20329
20438
|
console.error("[adminuser-self-heal] skip reason=no-users-file");
|
|
20330
20439
|
return;
|
|
20331
20440
|
}
|
|
20332
|
-
const usersRaw =
|
|
20441
|
+
const usersRaw = readFileSync29(USERS_FILE, "utf-8").trim();
|
|
20333
20442
|
if (!usersRaw) {
|
|
20334
20443
|
console.error("[adminuser-self-heal] skip reason=empty-users-file");
|
|
20335
20444
|
return;
|
|
@@ -20443,7 +20552,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
20443
20552
|
}
|
|
20444
20553
|
init({
|
|
20445
20554
|
configDir: configDirForWhatsApp,
|
|
20446
|
-
platformRoot: resolve31(process.env.MAXY_PLATFORM_ROOT ??
|
|
20555
|
+
platformRoot: resolve31(process.env.MAXY_PLATFORM_ROOT ?? join27(__dirname, "..")),
|
|
20447
20556
|
accountConfig: bootAccountConfig,
|
|
20448
20557
|
onMessage: async (msg) => {
|
|
20449
20558
|
if (msg.isOwnerMirror) {
|