@rubytech/create-maxy-code 0.1.310 → 0.1.311
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/admin/skills/platform-architecture/SKILL.md +2 -2
- package/payload/platform/plugins/docs/references/admin-ui.md +1 -1
- package/payload/platform/scripts/check-no-esm-require.mjs +4 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +29 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +16 -2
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +10 -0
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +22 -2
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/reseat-ledger.d.ts +39 -0
- package/payload/platform/services/claude-session-manager/dist/reseat-ledger.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/reseat-ledger.js +139 -0
- package/payload/platform/services/claude-session-manager/dist/reseat-ledger.js.map +1 -0
- package/payload/server/public/assets/{AccessGate-BOqUU-za.js → AccessGate-ChFLk-rp.js} +1 -1
- package/payload/server/public/assets/{AdminLoginScreens-WvRuaNIg.js → AdminLoginScreens-DU6zgbk5.js} +1 -1
- package/payload/server/public/assets/AdminShell-BJCYb1v5.js +1 -0
- package/payload/server/public/assets/{Checkbox-DjM6aYP_.js → Checkbox-CQGLKMXu.js} +1 -1
- package/payload/server/public/assets/{OperatorConversations-CDY0jUMb.js → OperatorConversations-CHEQTz20.js} +1 -1
- package/payload/server/public/assets/{admin-XbVTsU2q.js → admin-COHPIWdb.js} +1 -1
- package/payload/server/public/assets/{audio-attachment-mime-CVxjPN8V.js → audio-attachment-mime-DL06xo72.js} +1 -1
- package/payload/server/public/assets/brand-CN7uSSKl.css +1 -0
- package/payload/server/public/assets/{browser-Ct5Kwlmk.js → browser-L7N4tAOl.js} +1 -1
- package/payload/server/public/assets/chat-B_jYIH9a.js +1 -0
- package/payload/server/public/assets/data-BmSTKHR1.js +1 -0
- package/payload/server/public/assets/{graph-DWT1rhy9.js → graph-Cro3-mgY.js} +1 -1
- package/payload/server/public/assets/{graph-labels-OBadNo54.js → graph-labels-WQQn6JIJ.js} +1 -1
- package/payload/server/public/assets/operator-B4I25isQ.js +1 -0
- package/payload/server/public/assets/page-B-6ZQ4JG.js +1 -0
- package/payload/server/public/assets/{public-owWW-MIA.js → public-CX148JKi.js} +1 -1
- package/payload/server/public/assets/{public-next-ClQwtyeC.js → public-next-BCItsUbZ.js} +1 -1
- package/payload/server/public/assets/{useSelectionMode-BZsJuUm-.js → useSelectionMode-BHAAhkDg.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 +196 -35
- package/payload/server/public/assets/AdminShell-DHv6_SZ4.js +0 -1
- package/payload/server/public/assets/brand-N-Hi3IPA.css +0 -1
- package/payload/server/public/assets/chat-CEde1CLX.js +0 -1
- package/payload/server/public/assets/data-TZOmA1Qg.js +0 -1
- package/payload/server/public/assets/operator-BpzQ9Ezb.js +0 -1
- package/payload/server/public/assets/page-Dts8u8MD.js +0 -1
- /package/payload/server/public/assets/{brand-zL3tAdql.js → brand-MKGM8WZp.js} +0 -0
|
@@ -5,15 +5,15 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Maxy</title>
|
|
7
7
|
<link rel="icon" href="/favicon.ico">
|
|
8
|
-
<script type="module" crossorigin src="/assets/public-
|
|
8
|
+
<script type="module" crossorigin src="/assets/public-CX148JKi.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/chunk-CAM3fms7.js">
|
|
10
|
-
<link rel="modulepreload" crossorigin href="/assets/brand-
|
|
11
|
-
<link rel="modulepreload" crossorigin href="/assets/useSelectionMode-
|
|
12
|
-
<link rel="modulepreload" crossorigin href="/assets/Checkbox-
|
|
10
|
+
<link rel="modulepreload" crossorigin href="/assets/brand-MKGM8WZp.js">
|
|
11
|
+
<link rel="modulepreload" crossorigin href="/assets/useSelectionMode-BHAAhkDg.js">
|
|
12
|
+
<link rel="modulepreload" crossorigin href="/assets/Checkbox-CQGLKMXu.js">
|
|
13
13
|
<link rel="modulepreload" crossorigin href="/assets/preload-helper-C5gCWwwF.js">
|
|
14
|
-
<link rel="modulepreload" crossorigin href="/assets/audio-attachment-mime-
|
|
15
|
-
<link rel="modulepreload" crossorigin href="/assets/AccessGate-
|
|
16
|
-
<link rel="stylesheet" crossorigin href="/assets/brand-
|
|
14
|
+
<link rel="modulepreload" crossorigin href="/assets/audio-attachment-mime-DL06xo72.js">
|
|
15
|
+
<link rel="modulepreload" crossorigin href="/assets/AccessGate-ChFLk-rp.js">
|
|
16
|
+
<link rel="stylesheet" crossorigin href="/assets/brand-CN7uSSKl.css">
|
|
17
17
|
<link rel="stylesheet" crossorigin href="/assets/public-vnj7OhQj.css">
|
|
18
18
|
<link rel="stylesheet" href="/brand-defaults.css">
|
|
19
19
|
</head>
|
package/payload/server/server.js
CHANGED
|
@@ -4871,6 +4871,10 @@ function crossesForeignAccountPartition(relPath, accountId) {
|
|
|
4871
4871
|
if (!ACCOUNT_UUID_RE.test(owner)) return false;
|
|
4872
4872
|
return owner !== accountId;
|
|
4873
4873
|
}
|
|
4874
|
+
function isWithinOwnAccountPartition(relPath, accountId) {
|
|
4875
|
+
const segs = relPath.split("/").filter(Boolean);
|
|
4876
|
+
return segs.length >= 2 && segs[0] === "accounts" && segs[1] === accountId;
|
|
4877
|
+
}
|
|
4874
4878
|
function resolveUnderRoot(raw, rootAbs, rootLabel) {
|
|
4875
4879
|
const cleaned = normalize("/" + (raw ?? "").replace(/\\/g, "/")).replace(/^\/+/, "");
|
|
4876
4880
|
const absolute = resolve5(rootAbs, cleaned);
|
|
@@ -6615,10 +6619,8 @@ function selectReaderChannelSessions(rows) {
|
|
|
6615
6619
|
// server/routes/admin/sidebar-sessions.ts
|
|
6616
6620
|
var SESSION_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.jsonl$/i;
|
|
6617
6621
|
var CLI_MARKER_PREFIXES = ["<local-command-", "<command-name>", "<command-message>"];
|
|
6618
|
-
var PUBLIC_ROLE = "public";
|
|
6619
6622
|
var ADMIN_ROLE = "admin";
|
|
6620
6623
|
var WEBCHAT_CHANNEL = "webchat";
|
|
6621
|
-
var WHATSAPP_CHANNEL = "whatsapp";
|
|
6622
6624
|
var app3 = new Hono();
|
|
6623
6625
|
function claudeConfigDir() {
|
|
6624
6626
|
return process.env.CLAUDE_CONFIG_DIR ?? null;
|
|
@@ -6836,7 +6838,6 @@ app3.get("/", requireAdminSession, async (c) => {
|
|
|
6836
6838
|
const seenIds = /* @__PURE__ */ new Set();
|
|
6837
6839
|
let liveCount = 0;
|
|
6838
6840
|
let subagentCount = 0;
|
|
6839
|
-
let nonResumableCount = 0;
|
|
6840
6841
|
let archivedCount = 0;
|
|
6841
6842
|
let excludedChannelCount = 0;
|
|
6842
6843
|
const titleSourceCounts = { user: 0, ai: 0, "first-message": 0, prefix: 0 };
|
|
@@ -6870,7 +6871,6 @@ app3.get("/", requireAdminSession, async (c) => {
|
|
|
6870
6871
|
excludedChannelCount += 1;
|
|
6871
6872
|
continue;
|
|
6872
6873
|
}
|
|
6873
|
-
const resumable = !(role === PUBLIC_ROLE && (sidecarChannel === WEBCHAT_CHANNEL || sidecarChannel === WHATSAPP_CHANNEL));
|
|
6874
6874
|
if (personId) personIdBySession.set(sessionId, personId);
|
|
6875
6875
|
if (adminUserId && role === ADMIN_ROLE && sidecarChannel === WEBCHAT_CHANNEL) {
|
|
6876
6876
|
adminUserIdBySession.set(sessionId, adminUserId);
|
|
@@ -6885,14 +6885,12 @@ app3.get("/", requireAdminSession, async (c) => {
|
|
|
6885
6885
|
pid,
|
|
6886
6886
|
projectDir,
|
|
6887
6887
|
bridgeIds,
|
|
6888
|
-
resumable,
|
|
6889
6888
|
archived,
|
|
6890
6889
|
channel: resolved.channel,
|
|
6891
6890
|
personName: null
|
|
6892
6891
|
});
|
|
6893
6892
|
if (live) liveCount += 1;
|
|
6894
6893
|
if (isSubagent) subagentCount += 1;
|
|
6895
|
-
if (!resumable) nonResumableCount += 1;
|
|
6896
6894
|
if (archived) archivedCount += 1;
|
|
6897
6895
|
}
|
|
6898
6896
|
let personNameCount = 0;
|
|
@@ -6923,7 +6921,7 @@ app3.get("/", requireAdminSession, async (c) => {
|
|
|
6923
6921
|
}
|
|
6924
6922
|
rows.sort((a, b) => a.startedAt < b.startedAt ? 1 : -1);
|
|
6925
6923
|
console.log(
|
|
6926
|
-
`[admin-sessions-list] rows=${rows.length} live=${liveCount} subagents=${subagentCount} archived=${archivedCount}
|
|
6924
|
+
`[admin-sessions-list] rows=${rows.length} live=${liveCount} subagents=${subagentCount} archived=${archivedCount} excludedChannel=${excludedChannelCount} titles user=${titleSourceCounts.user} ai=${titleSourceCounts.ai} first=${titleSourceCounts["first-message"]} prefix=${titleSourceCounts.prefix} personNames=${personNameCount} adminNames=${adminNameCount} accountId=${accountId ? accountId.slice(0, 8) : "unset"}`
|
|
6927
6925
|
);
|
|
6928
6926
|
return c.json({ sessions: rows, accountId });
|
|
6929
6927
|
});
|
|
@@ -7653,7 +7651,7 @@ var public_reader_default = app5;
|
|
|
7653
7651
|
// server/routes/webchat.ts
|
|
7654
7652
|
import { basename as basename4, dirname as dirname3 } from "path";
|
|
7655
7653
|
import { join as join13 } from "path";
|
|
7656
|
-
import { existsSync as existsSync8, readdirSync as readdirSync7, readFileSync as readFileSync13, renameSync as renameSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
7654
|
+
import { existsSync as existsSync8, readdirSync as readdirSync7, readFileSync as readFileSync13, renameSync as renameSync2, statSync as statSync6, writeFileSync as writeFileSync6 } from "fs";
|
|
7657
7655
|
|
|
7658
7656
|
// server/canonical-webchat-override.ts
|
|
7659
7657
|
import { readFileSync as readFileSync12, writeFileSync as writeFileSync5, renameSync } from "fs";
|
|
@@ -7726,6 +7724,14 @@ function locateSidecar(sessionId) {
|
|
|
7726
7724
|
function sessionSidecarExists(sessionId) {
|
|
7727
7725
|
return locateSidecar(sessionId) !== null;
|
|
7728
7726
|
}
|
|
7727
|
+
function jsonlSizeBytes(projectDir, sessionId) {
|
|
7728
|
+
if (projectDir === null) return null;
|
|
7729
|
+
try {
|
|
7730
|
+
return statSync6(join13(projectDir, `${sessionId}.jsonl`)).size;
|
|
7731
|
+
} catch {
|
|
7732
|
+
return null;
|
|
7733
|
+
}
|
|
7734
|
+
}
|
|
7729
7735
|
function conflictingBinding(channel) {
|
|
7730
7736
|
return channel !== null && channel !== "webchat" ? channel : null;
|
|
7731
7737
|
}
|
|
@@ -7813,6 +7819,8 @@ async function reapplyLeversViaManager() {
|
|
|
7813
7819
|
return false;
|
|
7814
7820
|
}
|
|
7815
7821
|
}
|
|
7822
|
+
var WEBCHAT_SEND_TURN_WINDOW_MS = Number(process.env.WEBCHAT_SEND_TURN_WINDOW_MS ?? String(15e3));
|
|
7823
|
+
var sendSeq = 0;
|
|
7816
7824
|
function createWebchatRoutes(deps) {
|
|
7817
7825
|
const app51 = new Hono();
|
|
7818
7826
|
app51.post("/send", requireAdminSession, async (c) => {
|
|
@@ -7944,6 +7952,30 @@ ${note}` : note;
|
|
|
7944
7952
|
} else {
|
|
7945
7953
|
await deps.handleInbound({ role: "admin", accountId, key: deliveryKey, text });
|
|
7946
7954
|
}
|
|
7955
|
+
const sendId = ++sendSeq;
|
|
7956
|
+
let turnSessionId = deliverySessionId;
|
|
7957
|
+
if (turnSessionId === void 0) {
|
|
7958
|
+
let canonAccount;
|
|
7959
|
+
try {
|
|
7960
|
+
canonAccount = resolveAccount();
|
|
7961
|
+
} catch {
|
|
7962
|
+
canonAccount = null;
|
|
7963
|
+
}
|
|
7964
|
+
turnSessionId = resolveCanonicalSessionId(accountId, canonAccount?.accountDir ?? null);
|
|
7965
|
+
}
|
|
7966
|
+
const keyDisplay2 = deliveryKey.startsWith("session:") ? deliveryKey.slice(0, "session:".length + 8) : WEBCHAT_ADMIN_KEY;
|
|
7967
|
+
const baseline = jsonlSizeBytes(locateSession(turnSessionId).projectDir, turnSessionId);
|
|
7968
|
+
console.error(`[webchat:inbound] op=send-accepted key=${keyDisplay2} sendId=${sendId} baselineBytes=${baseline ?? "absent"}`);
|
|
7969
|
+
const turnTimer = setTimeout(() => {
|
|
7970
|
+
const now = jsonlSizeBytes(locateSession(turnSessionId).projectDir, turnSessionId);
|
|
7971
|
+
const grew = now !== null && (baseline === null || now > baseline);
|
|
7972
|
+
if (grew) {
|
|
7973
|
+
console.error(`[webchat:inbound] op=send-turned key=${keyDisplay2} sendId=${sendId} bytes=${now}`);
|
|
7974
|
+
} else {
|
|
7975
|
+
console.error(`[webchat:inbound] op=send-no-turn key=${keyDisplay2} sendId=${sendId} baselineBytes=${baseline ?? "absent"}`);
|
|
7976
|
+
}
|
|
7977
|
+
}, WEBCHAT_SEND_TURN_WINDOW_MS);
|
|
7978
|
+
if (turnTimer.unref) turnTimer.unref();
|
|
7947
7979
|
return c.json({ ok: true });
|
|
7948
7980
|
});
|
|
7949
7981
|
app51.post("/settings", requireAdminSession, async (c) => {
|
|
@@ -8003,7 +8035,7 @@ ${note}` : note;
|
|
|
8003
8035
|
const { projectDir: projectDir2, channel } = locateSession(target);
|
|
8004
8036
|
const known = projectDir2 !== null || sessionSidecarExists(target);
|
|
8005
8037
|
const indicators2 = await fetchComposerIndicators(target);
|
|
8006
|
-
return c.json({ sessionId: target, projectDir: projectDir2, channelBinding: conflictingBinding(channel), known, ...indicators2, ...readLevers() });
|
|
8038
|
+
return c.json({ sessionId: target, projectDir: projectDir2, channelBinding: conflictingBinding(channel), known, sizeBytes: jsonlSizeBytes(projectDir2, target), ...indicators2, ...readLevers() });
|
|
8007
8039
|
}
|
|
8008
8040
|
let account;
|
|
8009
8041
|
try {
|
|
@@ -8023,7 +8055,7 @@ ${note}` : note;
|
|
|
8023
8055
|
}
|
|
8024
8056
|
}
|
|
8025
8057
|
const indicators = await fetchComposerIndicators(sessionId);
|
|
8026
|
-
return c.json({ sessionId, projectDir, ...indicators, ...readLevers(account) });
|
|
8058
|
+
return c.json({ sessionId, projectDir, sizeBytes: jsonlSizeBytes(projectDir, sessionId), ...indicators, ...readLevers(account) });
|
|
8027
8059
|
});
|
|
8028
8060
|
return app51;
|
|
8029
8061
|
}
|
|
@@ -9164,7 +9196,7 @@ import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeF
|
|
|
9164
9196
|
import { createHash as createHash3, randomUUID as randomUUID8 } from "crypto";
|
|
9165
9197
|
|
|
9166
9198
|
// ../lib/admins-write/src/index.ts
|
|
9167
|
-
import { existsSync as existsSync11, readFileSync as readFileSync16, writeFileSync as writeFileSync7, renameSync as renameSync3, mkdirSync as mkdirSync2, readdirSync as readdirSync9, statSync as
|
|
9199
|
+
import { existsSync as existsSync11, readFileSync as readFileSync16, writeFileSync as writeFileSync7, renameSync as renameSync3, mkdirSync as mkdirSync2, readdirSync as readdirSync9, statSync as statSync7 } from "fs";
|
|
9168
9200
|
import { dirname as dirname4, join as join16 } from "path";
|
|
9169
9201
|
function logLine(input, result) {
|
|
9170
9202
|
const userIdShort = input.userId.slice(0, 8);
|
|
@@ -9264,7 +9296,7 @@ function checkAdminAuthInvariant(input) {
|
|
|
9264
9296
|
if (entry.startsWith(".")) continue;
|
|
9265
9297
|
const accountDir = join16(input.accountsDir, entry);
|
|
9266
9298
|
try {
|
|
9267
|
-
if (!
|
|
9299
|
+
if (!statSync7(accountDir).isDirectory()) continue;
|
|
9268
9300
|
} catch {
|
|
9269
9301
|
continue;
|
|
9270
9302
|
}
|
|
@@ -9556,7 +9588,7 @@ app8.delete("/set-pin", async (c) => {
|
|
|
9556
9588
|
var onboarding_default = app8;
|
|
9557
9589
|
|
|
9558
9590
|
// server/routes/client-error.ts
|
|
9559
|
-
import { appendFileSync, existsSync as existsSync13, renameSync as renameSync4, statSync as
|
|
9591
|
+
import { appendFileSync, existsSync as existsSync13, renameSync as renameSync4, statSync as statSync8 } from "fs";
|
|
9560
9592
|
import { join as join17 } from "path";
|
|
9561
9593
|
var CLIENT_ERRORS_LOG = join17(LOG_DIR, "client-errors.log");
|
|
9562
9594
|
var MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
@@ -9602,7 +9634,7 @@ function stackHead(stack) {
|
|
|
9602
9634
|
function rotateIfNeeded() {
|
|
9603
9635
|
try {
|
|
9604
9636
|
if (!existsSync13(CLIENT_ERRORS_LOG)) return;
|
|
9605
|
-
const stats =
|
|
9637
|
+
const stats = statSync8(CLIENT_ERRORS_LOG);
|
|
9606
9638
|
if (stats.size < MAX_LOG_SIZE) return;
|
|
9607
9639
|
renameSync4(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
|
|
9608
9640
|
} catch (err) {
|
|
@@ -9883,7 +9915,7 @@ app10.post("/", async (c) => {
|
|
|
9883
9915
|
var session_default = app10;
|
|
9884
9916
|
|
|
9885
9917
|
// server/routes/admin/logs.ts
|
|
9886
|
-
import { existsSync as existsSync15, readdirSync as readdirSync10, readFileSync as readFileSync18, statSync as
|
|
9918
|
+
import { existsSync as existsSync15, readdirSync as readdirSync10, readFileSync as readFileSync18, statSync as statSync9 } from "fs";
|
|
9887
9919
|
import { resolve as resolve16, basename as basename5 } from "path";
|
|
9888
9920
|
|
|
9889
9921
|
// app/lib/logs-read-resolve.ts
|
|
@@ -9923,7 +9955,7 @@ app11.get("/", async (c) => {
|
|
|
9923
9955
|
searched.push(filePath);
|
|
9924
9956
|
try {
|
|
9925
9957
|
const buffer = readFileSync18(filePath);
|
|
9926
|
-
const onDiskBytes =
|
|
9958
|
+
const onDiskBytes = statSync9(filePath).size;
|
|
9927
9959
|
const headers = {
|
|
9928
9960
|
"Content-Type": "text/plain; charset=utf-8",
|
|
9929
9961
|
"Content-Length": String(buffer.byteLength)
|
|
@@ -9988,7 +10020,7 @@ app11.get("/", async (c) => {
|
|
|
9988
10020
|
try {
|
|
9989
10021
|
const filename = basename5(hit.path);
|
|
9990
10022
|
const buffer = readFileSync18(hit.path);
|
|
9991
|
-
const onDiskBytes =
|
|
10023
|
+
const onDiskBytes = statSync9(hit.path).size;
|
|
9992
10024
|
const headers = {
|
|
9993
10025
|
"Content-Type": "text/plain; charset=utf-8",
|
|
9994
10026
|
"Content-Length": String(buffer.byteLength)
|
|
@@ -10031,7 +10063,7 @@ app11.get("/", async (c) => {
|
|
|
10031
10063
|
console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
|
|
10032
10064
|
continue;
|
|
10033
10065
|
}
|
|
10034
|
-
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime:
|
|
10066
|
+
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 }) => {
|
|
10035
10067
|
seen.add(name);
|
|
10036
10068
|
try {
|
|
10037
10069
|
const content = readFileSync18(resolve16(dir, name));
|
|
@@ -10894,7 +10926,7 @@ app15.put("/:id/label", requireAdminSession, async (c) => {
|
|
|
10894
10926
|
var sessions_default = app15;
|
|
10895
10927
|
|
|
10896
10928
|
// app/lib/claude-agent/spawn-context.ts
|
|
10897
|
-
import { existsSync as existsSync19, readFileSync as readFileSync20, readdirSync as readdirSync12, statSync as
|
|
10929
|
+
import { existsSync as existsSync19, readFileSync as readFileSync20, readdirSync as readdirSync12, statSync as statSync10 } from "fs";
|
|
10898
10930
|
import { dirname as dirname5, resolve as resolve19, join as join19 } from "path";
|
|
10899
10931
|
async function resolveOwnerProfileBlock(accountId, userId) {
|
|
10900
10932
|
if (!userId) return { ok: false, reason: "missing-user-id" };
|
|
@@ -10997,7 +11029,7 @@ function listPluginDirs() {
|
|
|
10997
11029
|
for (const name of readdirSync12(platformPlugins)) {
|
|
10998
11030
|
const dir = join19(platformPlugins, name);
|
|
10999
11031
|
try {
|
|
11000
|
-
if (
|
|
11032
|
+
if (statSync10(dir).isDirectory()) out.set(name, dir);
|
|
11001
11033
|
} catch {
|
|
11002
11034
|
}
|
|
11003
11035
|
}
|
|
@@ -11011,7 +11043,7 @@ function listPluginDirs() {
|
|
|
11011
11043
|
for (const name of readdirSync12(bundlePlugins)) {
|
|
11012
11044
|
const dir = join19(bundlePlugins, name);
|
|
11013
11045
|
try {
|
|
11014
|
-
if (
|
|
11046
|
+
if (statSync10(dir).isDirectory()) out.set(name, dir);
|
|
11015
11047
|
} catch {
|
|
11016
11048
|
}
|
|
11017
11049
|
}
|
|
@@ -11448,7 +11480,7 @@ var events_default = app18;
|
|
|
11448
11480
|
|
|
11449
11481
|
// server/routes/admin/files.ts
|
|
11450
11482
|
import { createReadStream as createReadStream2 } from "fs";
|
|
11451
|
-
import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, writeFile as writeFile4, unlink as unlink2 } from "fs/promises";
|
|
11483
|
+
import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, writeFile as writeFile4, unlink as unlink2, rename } from "fs/promises";
|
|
11452
11484
|
import { realpathSync as realpathSync4 } from "fs";
|
|
11453
11485
|
import { basename as basename7, dirname as dirname6, join as join21, resolve as resolve22, sep as sep6 } from "path";
|
|
11454
11486
|
import { Readable as Readable2 } from "stream";
|
|
@@ -12311,6 +12343,44 @@ function isProtectedFromDeletion(relPath) {
|
|
|
12311
12343
|
}
|
|
12312
12344
|
return { protected: false };
|
|
12313
12345
|
}
|
|
12346
|
+
function isProtectedFromRename(relPath) {
|
|
12347
|
+
if (isProtectedFromDeletion(relPath).protected) return true;
|
|
12348
|
+
const segments = relPath.split("/").filter(Boolean);
|
|
12349
|
+
const base = segments[segments.length - 1] ?? "";
|
|
12350
|
+
if (segments.length === 2 && segments[0] === "accounts") return true;
|
|
12351
|
+
if (segments.length === 3 && segments[0] === "accounts" && segments[2] === "uploads") {
|
|
12352
|
+
return true;
|
|
12353
|
+
}
|
|
12354
|
+
if (segments.length === 4 && segments[0] === "accounts" && segments[2] === "uploads" && UUID_RE3.test(segments[3])) {
|
|
12355
|
+
return true;
|
|
12356
|
+
}
|
|
12357
|
+
if (parseAttachmentPath(relPath) !== null) return true;
|
|
12358
|
+
if (UUID_RE3.test(base.replace(/\.meta\.json$/, "")) && base.endsWith(".meta.json")) {
|
|
12359
|
+
return true;
|
|
12360
|
+
}
|
|
12361
|
+
return false;
|
|
12362
|
+
}
|
|
12363
|
+
function isValidEntryName(name) {
|
|
12364
|
+
if (typeof name !== "string" || name.length === 0) return false;
|
|
12365
|
+
if (name === "." || name === "..") return false;
|
|
12366
|
+
return !/[\\/\0]/.test(name);
|
|
12367
|
+
}
|
|
12368
|
+
function resolveOwnAccountWrite(rawPath, accountId, endpoint) {
|
|
12369
|
+
const res = resolveDataPath(rawPath);
|
|
12370
|
+
if (!res.ok) {
|
|
12371
|
+
if (res.status === 403) console.error(`[data] path-traversal-blocked requested="${rawPath}" resolved="${res.resolved ?? "n/a"}"`);
|
|
12372
|
+
return { ok: false, status: res.status, error: res.error };
|
|
12373
|
+
}
|
|
12374
|
+
if (crossesForeignAccountPartition(res.relative, accountId)) {
|
|
12375
|
+
console.error(`[data] account-scope-blocked endpoint="${endpoint}" path="${res.relative}" account=${accountId.slice(0, 8)}\u2026`);
|
|
12376
|
+
return { ok: false, status: 404, error: "Not found" };
|
|
12377
|
+
}
|
|
12378
|
+
if (!isWithinOwnAccountPartition(res.relative, accountId)) {
|
|
12379
|
+
console.error(`[data] write-scope-blocked endpoint="${endpoint}" path="${res.relative}" account=${accountId.slice(0, 8)}\u2026`);
|
|
12380
|
+
return { ok: false, status: 403, error: "Path is outside your account folder" };
|
|
12381
|
+
}
|
|
12382
|
+
return { ok: true, absolute: res.absolute, relative: res.relative };
|
|
12383
|
+
}
|
|
12314
12384
|
async function knowledgeDocOwnedByAccount(accountId, attachmentId) {
|
|
12315
12385
|
if (!attachmentId) return false;
|
|
12316
12386
|
const session = getSession();
|
|
@@ -12494,14 +12564,18 @@ app19.post("/upload", requireAdminSession, async (c) => {
|
|
|
12494
12564
|
}
|
|
12495
12565
|
const safeName = basename7(file.name).replace(/[\0/\\]/g, "_");
|
|
12496
12566
|
const finalName = `${Date.now()}-${safeName}`;
|
|
12497
|
-
const
|
|
12567
|
+
const rawDir = formData.get("path");
|
|
12568
|
+
const dest = resolveOwnAccountWrite(typeof rawDir === "string" ? rawDir : "", accountId, "POST /api/admin/files/upload");
|
|
12569
|
+
if (!dest.ok) return c.json({ error: dest.error }, dest.status);
|
|
12570
|
+
const destDir = dest.absolute;
|
|
12498
12571
|
const destPath = resolve22(destDir, finalName);
|
|
12499
12572
|
try {
|
|
12500
|
-
await
|
|
12573
|
+
const info = await stat4(destDir);
|
|
12574
|
+
if (!info.isDirectory()) return c.json({ error: "Upload destination is not a directory" }, 400);
|
|
12501
12575
|
const dataRootReal = realpathSync4(DATA_ROOT);
|
|
12502
12576
|
const destDirReal = realpathSync4(destDir);
|
|
12503
12577
|
if (destDirReal !== dataRootReal && !destDirReal.startsWith(dataRootReal + sep6)) {
|
|
12504
|
-
console.error(`[data] path-traversal-blocked requested="
|
|
12578
|
+
console.error(`[data] path-traversal-blocked requested="${dest.relative}" resolved="${destDirReal}"`);
|
|
12505
12579
|
return c.json({ error: "Upload destination escapes DATA_ROOT" }, 403);
|
|
12506
12580
|
}
|
|
12507
12581
|
const buffer = Buffer.from(await file.arrayBuffer());
|
|
@@ -12511,7 +12585,7 @@ app19.post("/upload", requireAdminSession, async (c) => {
|
|
|
12511
12585
|
console.error(`[data] file-upload error filename="${safeName}" err="${message}"`);
|
|
12512
12586
|
return c.json({ error: message }, 500);
|
|
12513
12587
|
}
|
|
12514
|
-
const relativeDest =
|
|
12588
|
+
const relativeDest = `${dest.relative}/${finalName}`;
|
|
12515
12589
|
console.error(`[data] file-upload filename="${safeName}" size=${file.size} dest="${relativeDest}"`);
|
|
12516
12590
|
void indexFile(accountId, relativeDest).catch((err) => {
|
|
12517
12591
|
console.error(`[data] file-upload index-failed dest="${relativeDest}" err="${err instanceof Error ? err.message : String(err)}"`);
|
|
@@ -12599,6 +12673,91 @@ app19.delete("/", requireAdminSession, async (c) => {
|
|
|
12599
12673
|
return c.json({ error: message }, 500);
|
|
12600
12674
|
}
|
|
12601
12675
|
});
|
|
12676
|
+
app19.post("/folder", requireAdminSession, async (c) => {
|
|
12677
|
+
const cacheKey = c.var.cacheKey;
|
|
12678
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
12679
|
+
if (!accountId) {
|
|
12680
|
+
console.error(`[data] auth-rejected endpoint="POST /api/admin/files/folder" reason="no account for session"`);
|
|
12681
|
+
return c.json({ error: "Account not found for session" }, 401);
|
|
12682
|
+
}
|
|
12683
|
+
let body;
|
|
12684
|
+
try {
|
|
12685
|
+
body = await c.req.json();
|
|
12686
|
+
} catch {
|
|
12687
|
+
return c.json({ error: "Invalid JSON body" }, 400);
|
|
12688
|
+
}
|
|
12689
|
+
const rawPath = typeof body.path === "string" ? body.path : "";
|
|
12690
|
+
const name = typeof body.name === "string" ? body.name : "";
|
|
12691
|
+
if (!isValidEntryName(name)) return c.json({ error: "Invalid folder name" }, 400);
|
|
12692
|
+
const parent = resolveOwnAccountWrite(rawPath, accountId, "POST /api/admin/files/folder");
|
|
12693
|
+
if (!parent.ok) return c.json({ error: parent.error }, parent.status);
|
|
12694
|
+
const newAbs = resolve22(parent.absolute, name);
|
|
12695
|
+
const newRel = `${parent.relative}/${name}`;
|
|
12696
|
+
try {
|
|
12697
|
+
const info = await stat4(parent.absolute);
|
|
12698
|
+
if (!info.isDirectory()) return c.json({ error: "Parent is not a directory" }, 400);
|
|
12699
|
+
await mkdir3(newAbs, { recursive: false });
|
|
12700
|
+
} catch (err) {
|
|
12701
|
+
const code = err.code;
|
|
12702
|
+
if (code === "EEXIST") return c.json({ error: "A file or folder with that name already exists" }, 409);
|
|
12703
|
+
if (code === "ENOENT") return c.json({ error: "Not found" }, 404);
|
|
12704
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
12705
|
+
console.error(`[data] folder-create error path="${newRel}" err="${message}"`);
|
|
12706
|
+
return c.json({ error: message }, 500);
|
|
12707
|
+
}
|
|
12708
|
+
console.error(`[data] folder-create path="${newRel}"`);
|
|
12709
|
+
return c.json({ path: newRel });
|
|
12710
|
+
});
|
|
12711
|
+
app19.post("/rename", requireAdminSession, async (c) => {
|
|
12712
|
+
const cacheKey = c.var.cacheKey;
|
|
12713
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
12714
|
+
if (!accountId) {
|
|
12715
|
+
console.error(`[data] auth-rejected endpoint="POST /api/admin/files/rename" reason="no account for session"`);
|
|
12716
|
+
return c.json({ error: "Account not found for session" }, 401);
|
|
12717
|
+
}
|
|
12718
|
+
let body;
|
|
12719
|
+
try {
|
|
12720
|
+
body = await c.req.json();
|
|
12721
|
+
} catch {
|
|
12722
|
+
return c.json({ error: "Invalid JSON body" }, 400);
|
|
12723
|
+
}
|
|
12724
|
+
const rawPath = typeof body.path === "string" ? body.path : "";
|
|
12725
|
+
const newName = typeof body.newName === "string" ? body.newName : "";
|
|
12726
|
+
if (!isValidEntryName(newName)) return c.json({ error: "Invalid name" }, 400);
|
|
12727
|
+
const src = resolveOwnAccountWrite(rawPath, accountId, "POST /api/admin/files/rename");
|
|
12728
|
+
if (!src.ok) return c.json({ error: src.error }, src.status);
|
|
12729
|
+
if (isProtectedFromRename(src.relative)) {
|
|
12730
|
+
console.error(`[data] file-rename blocked path="${src.relative}" reason="protected"`);
|
|
12731
|
+
return c.json({ error: "Protected entry \u2014 refusing to rename" }, 403);
|
|
12732
|
+
}
|
|
12733
|
+
const destAbs = resolve22(dirname6(src.absolute), newName);
|
|
12734
|
+
const newRel = `${dirname6(src.relative)}/${newName}`.replace(/^\.\//, "");
|
|
12735
|
+
if (isProtectedFromRename(newRel)) {
|
|
12736
|
+
console.error(`[data] file-rename blocked path="${newRel}" reason="protected-target"`);
|
|
12737
|
+
return c.json({ error: "That name is reserved" }, 403);
|
|
12738
|
+
}
|
|
12739
|
+
try {
|
|
12740
|
+
let collision = true;
|
|
12741
|
+
try {
|
|
12742
|
+
await stat4(destAbs);
|
|
12743
|
+
} catch (e) {
|
|
12744
|
+
if (e.code === "ENOENT") collision = false;
|
|
12745
|
+
}
|
|
12746
|
+
if (collision) return c.json({ error: "A file or folder with that name already exists" }, 409);
|
|
12747
|
+
await rename(src.absolute, destAbs);
|
|
12748
|
+
} catch (err) {
|
|
12749
|
+
const code = err.code;
|
|
12750
|
+
if (code === "ENOENT") return c.json({ error: "Not found" }, 404);
|
|
12751
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
12752
|
+
console.error(`[data] file-rename error from="${src.relative}" to="${newRel}" err="${message}"`);
|
|
12753
|
+
return c.json({ error: message }, 500);
|
|
12754
|
+
}
|
|
12755
|
+
console.error(`[data] file-rename from="${src.relative}" to="${newRel}"`);
|
|
12756
|
+
void reconcileFileIndex(accountId).catch((err) => {
|
|
12757
|
+
console.error(`[data] file-rename reconcile-failed account=${accountId.slice(0, 8)}\u2026 err="${err instanceof Error ? err.message : String(err)}"`);
|
|
12758
|
+
});
|
|
12759
|
+
return c.json({ path: newRel });
|
|
12760
|
+
});
|
|
12602
12761
|
var files_default = app19;
|
|
12603
12762
|
|
|
12604
12763
|
// ../lib/graph-search/src/index.ts
|
|
@@ -14938,7 +15097,9 @@ function resolveSpawnPlan(host, operatorDomains, body, mintId = randomUUID10, ad
|
|
|
14938
15097
|
}
|
|
14939
15098
|
function shapeWebchatResponse(sessionId, manager) {
|
|
14940
15099
|
const outcome = typeof manager?.outcome === "string" ? manager.outcome : "bound";
|
|
14941
|
-
|
|
15100
|
+
const redirected = manager?.redirected === true && typeof manager?.sessionId === "string";
|
|
15101
|
+
const landed = redirected ? manager.sessionId : sessionId;
|
|
15102
|
+
return { sessionId: landed, outcome, target: `/chat?session=${landed}` };
|
|
14942
15103
|
}
|
|
14943
15104
|
var app30 = new Hono();
|
|
14944
15105
|
app30.post("/", requireAdminSession, async (c) => {
|
|
@@ -16101,7 +16262,7 @@ app44.route("/request-magic-link", request_magic_link_default);
|
|
|
16101
16262
|
var access_default = app44;
|
|
16102
16263
|
|
|
16103
16264
|
// server/routes/sites.ts
|
|
16104
|
-
import { existsSync as existsSync23, readFileSync as readFileSync23, realpathSync as realpathSync5, statSync as
|
|
16265
|
+
import { existsSync as existsSync23, readFileSync as readFileSync23, realpathSync as realpathSync5, statSync as statSync11 } from "fs";
|
|
16105
16266
|
import { resolve as resolve26 } from "path";
|
|
16106
16267
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
16107
16268
|
var MIME = {
|
|
@@ -16167,7 +16328,7 @@ app45.get("/:rel{.*}", (c) => {
|
|
|
16167
16328
|
}
|
|
16168
16329
|
let stat7;
|
|
16169
16330
|
try {
|
|
16170
|
-
stat7 = existsSync23(filePath) ?
|
|
16331
|
+
stat7 = existsSync23(filePath) ? statSync11(filePath) : null;
|
|
16171
16332
|
} catch {
|
|
16172
16333
|
stat7 = null;
|
|
16173
16334
|
}
|
|
@@ -17295,7 +17456,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
17295
17456
|
}
|
|
17296
17457
|
|
|
17297
17458
|
// app/lib/migrate-uploads.ts
|
|
17298
|
-
import { mkdir as mkdir5, readdir as readdir5, rename, rm as rm3 } from "fs/promises";
|
|
17459
|
+
import { mkdir as mkdir5, readdir as readdir5, rename as rename2, rm as rm3 } from "fs/promises";
|
|
17299
17460
|
import { dirname as dirname8, relative as relative4, resolve as resolve29 } from "path";
|
|
17300
17461
|
var ACCOUNT_UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
17301
17462
|
async function walkFiles(dir) {
|
|
@@ -17329,7 +17490,7 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
|
|
|
17329
17490
|
const suffix = relative4(srcDir, oldAbs);
|
|
17330
17491
|
const newAbs = resolve29(destDir, suffix);
|
|
17331
17492
|
await mkdir5(dirname8(newAbs), { recursive: true });
|
|
17332
|
-
await
|
|
17493
|
+
await rename2(oldAbs, newAbs);
|
|
17333
17494
|
moved++;
|
|
17334
17495
|
const oldRel = relative4(dataRoot, oldAbs);
|
|
17335
17496
|
const newRel = relative4(dataRoot, newAbs);
|
|
@@ -17418,7 +17579,7 @@ async function migrateUploads(opts = {}) {
|
|
|
17418
17579
|
}
|
|
17419
17580
|
|
|
17420
17581
|
// app/lib/migrate-admin-webchat-sidecars.ts
|
|
17421
|
-
import { readdir as readdir6, readFile as readFile6, rename as
|
|
17582
|
+
import { readdir as readdir6, readFile as readFile6, rename as rename3, writeFile as writeFile5, unlink as unlink3 } from "fs/promises";
|
|
17422
17583
|
import { existsSync as existsSync26 } from "fs";
|
|
17423
17584
|
import { join as join24 } from "path";
|
|
17424
17585
|
var ADMIN_ROLE2 = "admin";
|
|
@@ -17446,7 +17607,7 @@ async function writeRaw(path2, obj) {
|
|
|
17446
17607
|
const tmp = `${path2}.tmp.${process.pid}.${Date.now()}`;
|
|
17447
17608
|
try {
|
|
17448
17609
|
await writeFile5(tmp, JSON.stringify(obj, null, 2), "utf8");
|
|
17449
|
-
await
|
|
17610
|
+
await rename3(tmp, path2);
|
|
17450
17611
|
} catch (err) {
|
|
17451
17612
|
try {
|
|
17452
17613
|
if (existsSync26(tmp)) await unlink3(tmp);
|
|
@@ -18581,7 +18742,7 @@ function broadcastAdminShutdown(reason) {
|
|
|
18581
18742
|
|
|
18582
18743
|
// ../lib/entitlement/src/index.ts
|
|
18583
18744
|
import { createPublicKey, createHash as createHash5, verify as cryptoVerify } from "crypto";
|
|
18584
|
-
import { existsSync as existsSync27, readFileSync as readFileSync26, statSync as
|
|
18745
|
+
import { existsSync as existsSync27, readFileSync as readFileSync26, statSync as statSync12 } from "fs";
|
|
18585
18746
|
import { resolve as resolve30 } from "path";
|
|
18586
18747
|
|
|
18587
18748
|
// ../lib/entitlement/src/canonicalize.ts
|
|
@@ -18633,7 +18794,7 @@ function resolveEntitlement(brand, account) {
|
|
|
18633
18794
|
if (!existsSync27(entitlementPath)) {
|
|
18634
18795
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
18635
18796
|
}
|
|
18636
|
-
const stat7 =
|
|
18797
|
+
const stat7 = statSync12(entitlementPath);
|
|
18637
18798
|
const key = memoKey(stat7.mtimeMs, account);
|
|
18638
18799
|
if (memo && memo.key === key) {
|
|
18639
18800
|
return memo.result;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as e}from"./chunk-CAM3fms7.js";import{c as t,o as n,s as r,t as i,u as a}from"./brand-zL3tAdql.js";import{b as o,c as s,d as c,g as l,l as u,p as d,s as f,t as p,u as m,y as h}from"./OperatorConversations-CDY0jUMb.js";import{i as g,t as ee}from"./useSelectionMode-BZsJuUm-.js";async function _(){try{let e=await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`logout`})});return e.ok?(await e.json().catch(()=>({})))?.logged_out===!0:(console.error(`[admin-ui] claude-logout http-status=${e.status}`),!1)}catch(e){return console.error(`[admin-ui] claude-logout fetch failed: ${e instanceof Error?e.message:String(e)}`),!1}}var te=t(`archive-restore`,[[`rect`,{width:`20`,height:`5`,x:`2`,y:`3`,rx:`1`,key:`1wp1u1`}],[`path`,{d:`M4 8v11a2 2 0 0 0 2 2h2`,key:`tvwodi`}],[`path`,{d:`M20 8v11a2 2 0 0 1-2 2h-2`,key:`1gkqxj`}],[`path`,{d:`m9 15 3-3 3 3`,key:`1pd0qc`}],[`path`,{d:`M12 12v9`,key:`192myk`}]]),v=t(`archive`,[[`rect`,{width:`20`,height:`5`,x:`2`,y:`3`,rx:`1`,key:`1wp1u1`}],[`path`,{d:`M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8`,key:`1s80jp`}],[`path`,{d:`M10 12h4`,key:`a56b0p`}]]),y=t(`bot`,[[`path`,{d:`M12 8V4H8`,key:`hb8ula`}],[`rect`,{width:`16`,height:`12`,x:`4`,y:`8`,rx:`2`,key:`enze0r`}],[`path`,{d:`M2 14h2`,key:`vft8re`}],[`path`,{d:`M20 14h2`,key:`4cs60a`}],[`path`,{d:`M15 13v2`,key:`1xurst`}],[`path`,{d:`M9 13v2`,key:`rq6x2g`}]]),ne=t(`box`,[[`path`,{d:`M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z`,key:`hh9hay`}],[`path`,{d:`m3.3 7 8.7 5 8.7-5`,key:`g66t2b`}],[`path`,{d:`M12 22V12`,key:`d0xqtd`}]]),b=t(`history`,[[`path`,{d:`M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8`,key:`1357e3`}],[`path`,{d:`M3 3v5h5`,key:`1xhq8a`}],[`path`,{d:`M12 7v5l4 2`,key:`1fdv2h`}]]),x=t(`list-todo`,[[`path`,{d:`M13 5h8`,key:`a7qcls`}],[`path`,{d:`M13 12h8`,key:`h98zly`}],[`path`,{d:`M13 19h8`,key:`c3s6r1`}],[`path`,{d:`m3 17 2 2 4-4`,key:`1jhpwq`}],[`rect`,{x:`3`,y:`4`,width:`6`,height:`6`,rx:`1`,key:`cif1o7`}]]),re=t(`message-square`,[[`path`,{d:`M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z`,key:`18887p`}]]),S=t(`plus`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`M12 5v14`,key:`s699le`}]]),C=t(`square`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}]]),w=t(`users`,[[`path`,{d:`M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2`,key:`1yyitq`}],[`path`,{d:`M16 3.128a4 4 0 0 1 0 7.744`,key:`16gr8j`}],[`path`,{d:`M22 21v-2a4 4 0 0 0-3-3.87`,key:`kshegd`}],[`circle`,{cx:`9`,cy:`7`,r:`4`,key:`nufk8`}]]),T=e(a(),1),E=n(),D=`maxy-shell-side-px`;function O(){if(typeof window>`u`)return 0;let e=document.querySelector(`.platform > .artefact`)?.getBoundingClientRect();return e&&e.width>0?Math.round(e.width):0}function k(e){if(typeof window>`u`)return e;let t=window.innerWidth,n=Math.max(248,t-480-O());return Math.min(Math.max(e,248),n)}function A(){if(typeof window>`u`)return 264;try{let e=window.localStorage.getItem(D);if(!e)return 264;let t=parseInt(e,10);if(!Number.isFinite(t))return console.warn(`[admin-ui] sidebar-width-parse-failed stored=${JSON.stringify(e)} fallback=264`),264;if(t>=248)return k(t)}catch{}return 264}function ie({targetSelector:e=`.platform`}){let t=(0,T.useRef)(null),[n,r]=(0,T.useState)(()=>A()),i=(0,T.useRef)(n);(0,T.useLayoutEffect)(()=>{let t=document.querySelector(e);!t||!(t instanceof HTMLElement)||(t.style.setProperty(`--side-px`,`${n}px`),i.current=n)},[n,e]);let a=(0,T.useCallback)(()=>{r(e=>{let t=k(e);return t===e?e:t})},[]);(0,T.useEffect)(()=>{a(),window.addEventListener(`resize`,a);let t=document.querySelector(e),n=null;return t instanceof HTMLElement&&(n=new MutationObserver(a),n.observe(t,{attributes:!0,attributeFilter:[`data-artefact`,`class`]})),()=>{window.removeEventListener(`resize`,a),n?.disconnect()}},[a,e]);let o=e=>{e.preventDefault();let n=t.current;if(!n)return;n.setPointerCapture(e.pointerId),n.classList.add(`dragging`);let a=!1,o=e=>{a=!0,r(k(Math.round(e.clientX)))},s=()=>{if(n.releasePointerCapture(e.pointerId),n.classList.remove(`dragging`),window.removeEventListener(`pointermove`,o),window.removeEventListener(`pointerup`,s),!a)return;let t=i.current;try{window.localStorage.setItem(D,String(t))}catch{}console.info(`[admin-ui] sidebar-resize px=${t}`)};window.addEventListener(`pointermove`,o),window.addEventListener(`pointerup`,s)},s=()=>{let e=k(264);r(e);try{window.localStorage.removeItem(D)}catch{}console.info(`[admin-ui] sidebar-resize px=${e}`)};return(0,E.jsx)(`div`,{ref:t,className:`side-resize-handle`,role:`separator`,"aria-orientation":`vertical`,"aria-label":`Resize sidebar`,onPointerDown:o,onDoubleClick:s})}var j=[`whatsapp`,`telegram`];function M(e){if(e<60)return`${e}s`;let t=Math.floor(e/60),n=e%60;return n>0?`${t}m ${n}s`:`${t}m`}function ae(e){return e>=1e3?`${(e/1e3).toFixed(1)}k`:String(e)}var N=`auth-refresh-failed`;function oe({error:e,onClose:t}){if(!e)return null;let n=e.reason===N,r=n?`Claude sign-in expired`:`Session didn’t open`,i=n?`Your claude.ai login has expired. Re-authenticate to resume sessions.`:`The session did not bind within 60 seconds, so there is no live conversation to open.`;return(0,E.jsx)(`div`,{className:`claude-info-overlay`,onClick:t,children:(0,E.jsxs)(`div`,{className:`claude-info-modal`,onClick:e=>e.stopPropagation(),role:`alertdialog`,"aria-label":`Session could not be opened`,children:[(0,E.jsxs)(`div`,{className:`claude-info-header`,children:[(0,E.jsx)(`span`,{children:r}),(0,E.jsx)(`button`,{className:`claude-info-close`,onClick:t,"aria-label":`Close`,children:`✕`})]}),(0,E.jsxs)(`div`,{className:`claude-info-section`,style:{padding:`12px 14px`,fontSize:`11px`,color:`var(--text-secondary)`},children:[i,(0,E.jsxs)(`div`,{className:`claude-info-row`,style:{marginTop:`8px`},children:[(0,E.jsx)(`span`,{className:`claude-info-label`,children:`Reason`}),(0,E.jsx)(`span`,{className:`claude-info-value`,children:e.reason})]}),e.sessionId&&(0,E.jsxs)(`div`,{className:`claude-info-row`,children:[(0,E.jsx)(`span`,{className:`claude-info-label`,children:`Session`}),(0,E.jsxs)(`span`,{className:`claude-info-value`,children:[e.sessionId.slice(0,8),`…`]})]})]})]})})}function se(e){let{show:t,onClose:n,claudeInfo:r,messages:i,sessionElapsed:a,sessionId:o,cacheKey:s}=e,[c,l]=(0,T.useState)(null);if(!t)return null;let u=i.flatMap(e=>e.events?.filter(e=>e.type===`usage`)??[]),d=u.at(-1),f=d?.peak_request_pct==null?d?.context_window?Math.round((d.input_tokens+d.cache_creation_tokens+d.cache_read_tokens)/d.context_window*100):0:Math.round(d.peak_request_pct*100),p=u.reduce((e,t)=>e+t.input_tokens+t.cache_creation_tokens+t.cache_read_tokens+t.output_tokens,0),m=i.flatMap(e=>e.events?.filter(e=>e.type===`rate_limit`)??[]).at(-1),h=u.reduce((e,t)=>e+(t.total_cost_usd??0),0),g=r?.account?.subscriptionType,_=e=>{let t=e*1e3-Date.now();if(t<=0)return`now`;let n=Math.floor(t/36e5),r=Math.floor(t%36e5/6e4);return n>0?`${n}h ${r}m`:`${r}m`};return(0,E.jsx)(`div`,{className:`claude-info-overlay`,onClick:n,children:(0,E.jsxs)(`div`,{className:`claude-info-modal`,onClick:e=>e.stopPropagation(),children:[(0,E.jsxs)(`div`,{className:`claude-info-header`,children:[(0,E.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`claude-info-icon`}),(0,E.jsx)(`span`,{children:`Claude Code`}),(0,E.jsx)(`button`,{className:`claude-info-close`,onClick:n,"aria-label":`Close`,children:`✕`})]}),(0,E.jsxs)(`div`,{className:`claude-info-section`,children:[(0,E.jsxs)(`div`,{className:`claude-info-row`,children:[(0,E.jsx)(`span`,{className:`claude-info-label`,children:`Version`}),(0,E.jsx)(`span`,{className:`claude-info-value`,children:r?r.version:`…`})]}),(0,E.jsxs)(`div`,{className:`claude-info-row`,children:[(0,E.jsx)(`span`,{className:`claude-info-label`,children:`Email`}),(0,E.jsx)(`span`,{className:`claude-info-value`,children:r?.account?.email??`…`})]})]}),(g||m||h>0)&&(0,E.jsxs)(`div`,{className:`claude-info-section`,children:[g&&(0,E.jsxs)(`div`,{className:`claude-info-row`,children:[(0,E.jsx)(`span`,{className:`claude-info-label`,children:`Plan`}),(0,E.jsx)(`span`,{className:`claude-info-value`,style:{textTransform:`capitalize`},children:g})]}),m&&(0,E.jsxs)(E.Fragment,{children:[(0,E.jsxs)(`div`,{className:`claude-info-row`,children:[(0,E.jsx)(`span`,{className:`claude-info-label`,children:`Usage`}),(0,E.jsxs)(`span`,{className:`claude-info-value`,children:[Math.round(m.utilization*100),`%`]})]}),(0,E.jsxs)(`div`,{className:`claude-info-row`,children:[(0,E.jsx)(`span`,{className:`claude-info-label`,children:`Resets in`}),(0,E.jsx)(`span`,{className:`claude-info-value`,children:_(m.resetsAt)})]}),m.isUsingOverage&&(0,E.jsxs)(`div`,{className:`claude-info-row`,children:[(0,E.jsx)(`span`,{className:`claude-info-label`,children:`Overage`}),(0,E.jsx)(`span`,{className:`claude-info-value`,children:`Active`})]})]}),h>0&&(0,E.jsxs)(`div`,{className:`claude-info-row`,children:[(0,E.jsx)(`span`,{className:`claude-info-label`,children:`Session cost`}),(0,E.jsxs)(`span`,{className:`claude-info-value`,children:[`$`,h<.01?h.toFixed(4):h.toFixed(2)]})]})]}),(0,E.jsxs)(`div`,{className:`claude-info-section`,children:[(0,E.jsxs)(`div`,{className:`claude-info-row`,children:[(0,E.jsx)(`span`,{className:`claude-info-label`,children:`Model`}),(0,E.jsx)(`span`,{className:`claude-info-value`,children:r?.model??`…`})]}),(0,E.jsxs)(`div`,{className:`claude-info-row`,children:[(0,E.jsx)(`span`,{className:`claude-info-label`,children:`Context used`}),(0,E.jsx)(`span`,{className:`claude-info-value`,children:f>0?`${f}%`:`—`})]}),(0,E.jsxs)(`div`,{className:`claude-info-row`,children:[(0,E.jsx)(`span`,{className:`claude-info-label`,children:`Tokens`}),(0,E.jsx)(`span`,{className:`claude-info-value`,children:p>0?ae(p):`—`})]}),(0,E.jsxs)(`div`,{className:`claude-info-row`,children:[(0,E.jsx)(`span`,{className:`claude-info-label`,children:`Session`}),(0,E.jsx)(`span`,{className:`claude-info-value`,children:M(a)})]}),(o||s)&&(()=>{let e=o??s??``;return(0,E.jsxs)(`div`,{className:`claude-info-row`,children:[(0,E.jsx)(`span`,{className:`claude-info-label`,children:`Session`}),(0,E.jsx)(`button`,{type:`button`,className:`claude-info-value claude-info-id-copy`,title:`${e} (${o?`flushed`:`pre-flush`}) — click to copy`,onClick:async()=>{l(await ee(e)?`copied`:`failed`),setTimeout(()=>l(null),1200)},children:c===`copied`?`copied ✓`:c===`failed`?`copy failed ✕`:`${e.slice(0,8)}…`})]})})()]})]})})}var P=`https://claude.ai/code`,ce=[500,1e3,1500,2e3,2500,3e3,3e3];function le(e,t,n){if(e&&n.target)return{kind:`navigate`,url:n.target};let r=n.slug??n.bridgeSessionId??null;if(e&&r)return{kind:`navigate`,url:`${P}/${r}`};let i=n.reason||n.error||`status ${t}`;return{kind:`error`,sessionId:n.sessionId??null,reason:i}}function ue(e){if(!e)return``;let t=Date.parse(e);return Number.isFinite(t)?new Date(t).toLocaleString(void 0,{dateStyle:`medium`,timeStyle:`short`}):``}function de(e){let{businessName:t,cacheKey:n,role:a,userName:c,userAvatar:p,onSelectProjects:ee,onSelectPeople:_,onSelectTasks:D,onSelectAgents:O,onCloseMobileDrawer:k,collapsed:A,selectedWhatsappId:ie,onSelectWhatsappConversation:M,initialWhatsappSurface:ae=!1}=e,N=d(n),se=i.productName,P=typeof c==`string`?c:c===null?`name unavailable`:t||se,de=(P.trim().charAt(0)||`?`).toUpperCase(),[F,I]=(0,T.useState)(ae?`whatsapp`:`sessions`),[L,me]=(0,T.useState)([]),[R,he]=(0,T.useState)(!1),[z,B]=(0,T.useState)(null),[V,ge]=(0,T.useState)(!1),[H,_e]=(0,T.useState)(`file`),[U,W]=(0,T.useState)(null),[ve,G]=(0,T.useState)(null),[K,ye]=(0,T.useState)([]),[q,be]=(0,T.useState)(!1),[xe,Se]=(0,T.useState)(null),[Ce,we]=(0,T.useState)(!1),[Te,Ee]=(0,T.useState)(!1),[De,Oe]=(0,T.useState)(!1),[ke,Ae]=(0,T.useState)(null),[je,Me]=(0,T.useState)(new Set),[Ne,Pe]=(0,T.useState)(new Set),[Fe,Ie]=(0,T.useState)(new Set),[Le,Re]=(0,T.useState)(new Set),[J,ze]=(0,T.useState)(!1),[Be,Ve]=(0,T.useState)([]),[He,Ue]=(0,T.useState)(!1),[We,Ge]=(0,T.useState)(null),[Y,Ke]=(0,T.useState)(`whatsapp`),qe=(0,T.useCallback)(e=>{if(k(),!n){console.error(`[admin-ui] artefact-download-blocked id=${e.id} reason=no-cache-key`),W({message:`Session not ready — try again`,failed:!0});return}if(!e.downloadPath){console.error(`[admin-ui] artefact-download-blocked id=${e.id} reason=not-downloadable`),W({message:`${e.name} can’t be downloaded`,failed:!0});return}console.info(`[admin-ui] artefact-download id=${e.id} root=${e.downloadRoot??`data`} path=${e.downloadPath}`),f(n,e.downloadPath,e.downloadRoot??`data`),W({message:`Downloading ${e.name}`,failed:!1})},[n,k]);(0,T.useEffect)(()=>{if(!U)return;let e=setTimeout(()=>W(null),2500);return()=>clearTimeout(e)},[U]);let Je=(0,T.useCallback)(async()=>{if(n){ge(!0),B(null);try{let e=await N(`/api/admin/sidebar-artefacts`);if(!e.ok)throw Error(`status ${e.status}`);me((await e.json()).artefacts??[]),he(!0)}catch(e){let t=e instanceof Error?e.message:String(e);B(`Failed to load artefacts: ${t}`),console.error(`[admin-ui] sidebar-artefacts fetch failed: ${t}`)}finally{ge(!1)}}},[n,N]),X=(0,T.useCallback)(async()=>{if(!n)return null;we(!0),Se(null);try{let e=await N(`/api/admin/sidebar-sessions`);if(!e.ok)throw Error(`status ${e.status}`);let t=await e.json(),n=t.sessions??[];return ye(n),Ae(t.accountId??null),be(!0),n}catch(e){let t=e instanceof Error?e.message:String(e);return Se(`Failed to load sessions: ${t}`),console.error(`[admin-ui] sidebar-sessions fetch failed: ${t}`),null}finally{we(!1)}},[n,N]),Z=(0,T.useCallback)(async()=>{if(n){Ge(null);try{let e=await N(`/api/whatsapp-reader/conversations`);if(!e.ok)throw Error(`status ${e.status}`);Ve((await e.json()).conversations??[]),Ue(!0)}catch(e){let t=e instanceof Error?e.message:String(e);Ge(`Couldn't load conversations.`),console.error(`[admin-ui] channel-convos fetch failed: ${t}`)}}},[n,N]);(0,T.useEffect)(()=>{!n||q||X()},[n,q,X]),(0,T.useEffect)(()=>{if(!n)return;let e=null;return Z(),e=setInterval(()=>{Z()},fe),()=>{e!==null&&clearInterval(e)}},[n,Z]);let Q=(0,T.useMemo)(()=>{let e=new Map;for(let t of j)e.set(t,[]);for(let t of Be)e.get(t.channel)?.push(t);for(let t of j)console.info(`[admin-ui] sidebar-nav surface=${t} count=${e.get(t).length}`);return e},[Be]),Ye={whatsapp:`WhatsApp`,telegram:`Telegram`,webchat:`Webchat`},Xe=()=>{M(null),I(`artefacts`),console.info(`[admin-ui] sidebar-nav surface=artefacts count=${R?L.length:0} collapsed=${A}`),Je()},$=1.5,Ze=()=>{console.info(`[admin-ui] sidebar-refresh surface=artefacts`),Je()},Qe=()=>{M(null),I(`sessions`),console.info(`[admin-ui] sidebar-nav surface=sessions count=${q?K.length:0} collapsed=${A}`),q||X()},$e=()=>{console.info(`[admin-ui] sidebar-refresh surface=sessions`),X()},et=e=>{I(`whatsapp`),Ke(e),console.info(`[admin-ui] sidebar-nav surface=${e} count=${Q.get(e)?.length??0} collapsed=${A}`)},tt=(0,T.useCallback)(async e=>{if(e.resumable===!1||Ne.has(e.sessionId))return;Pe(t=>{let n=new Set(t);return n.add(e.sessionId),n});let t=window.open(``,`_blank`);try{let n=await N(`/api/admin/session-rc-spawn`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sessionId:e.sessionId,name:e.title||e.sessionId})}),r=await n.json().catch(()=>({})),i=le(n.ok,n.status,{...r,sessionId:r.sessionId??e.sessionId});console.info(`[admin-ui] sidebar-session-resume sessionId=${e.sessionId} status=${n.status} outcome=${i.kind} slug=${r.slug??r.bridgeSessionId??`none`}`),i.kind===`navigate`?(k(),t?t.location.href=i.url:window.open(i.url,`_blank`)):(t?.close(),console.error(`[admin-ui] sidebar-session-resume-failed sessionId=${e.sessionId} status=${n.status} reason=${i.reason}`),G(i))}catch(n){t?.close();let r=n instanceof Error?n.message:String(n);console.error(`[admin-ui] sidebar-session-resume-failed sessionId=${e.sessionId} error=${r}`),G({sessionId:e.sessionId,reason:r})}finally{Pe(t=>{let n=new Set(t);return n.delete(e.sessionId),n})}},[N,k,Ne]),nt=(0,T.useCallback)(async e=>{let t=e.slice(0,8);for(let n=1;n<=ce.length;n++){await new Promise(e=>setTimeout(e,ce[n-1]));let r=await X();if(r&&r.some(t=>t.sessionId===e)){console.info(`[admin-ui] sidebar-new-session-converged sessionId=${t} via=retry attempts=${n}`);return}}console.error(`[admin-ui] sidebar-new-session-converge-timeout sessionId=${t}`)},[X]),rt=(0,T.useCallback)(async()=>{if(J)return;ze(!0);let e=window.open(``,`_blank`);try{let t=await N(`/api/admin/session-rc-spawn`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({})}),n=await t.json().catch(()=>({})),r=le(t.ok,t.status,n);console.info(`[admin-ui] sidebar-new-session-spawned status=${t.status} outcome=${r.kind} slug=${n.slug??n.bridgeSessionId??`none`}`),r.kind===`navigate`?(e?e.location.href=r.url:window.open(r.url,`_blank`),n.sessionId?nt(n.sessionId):console.error(`[admin-ui] sidebar-new-session-converge-skipped reason=no-session-id`)):(e?.close(),console.error(`[admin-ui] sidebar-new-session-failed status=${t.status} reason=${r.reason}`),G(r))}catch(t){e?.close();let n=t instanceof Error?t.message:String(t);console.error(`[admin-ui] sidebar-new-session-failed error=${n}`),G({sessionId:null,reason:n})}finally{ze(!1)}},[N,J,nt]),it=(0,T.useCallback)(async(e,t)=>{if(e.stopPropagation(),!je.has(t.sessionId)){Me(e=>{let n=new Set(e);return n.add(t.sessionId),n});try{let e=await N(`/api/admin/session-delete`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sessionId:t.sessionId})});if(!e.ok){let n=await e.json().catch(()=>({}));console.error(`[admin-ui] sidebar-session-delete-failed sessionId=${t.sessionId} status=${e.status} error=${n.error??`unknown`}`),W({message:`Delete failed: ${n.error??`status ${e.status}`}`,failed:!0});return}let n=await e.json();console.info(`[admin-ui] sidebar-session-delete sessionId=${t.sessionId} pidKilled=${n.pidKilled??`?`} deleted=${n.deleted??`?`}`),ye(e=>e.filter(e=>e.sessionId!==t.sessionId)),X()}catch(e){let n=e instanceof Error?e.message:String(e);console.error(`[admin-ui] sidebar-session-delete-failed sessionId=${t.sessionId} error=${n}`),W({message:`Delete failed: ${n}`,failed:!0})}finally{Me(e=>{let n=new Set(e);return n.delete(t.sessionId),n})}}},[N,je,X]),at=(0,T.useCallback)(async(e,t)=>{if(e.stopPropagation(),!Fe.has(t.sessionId)){Ie(e=>{let n=new Set(e);return n.add(t.sessionId),n});try{let e=await N(`/api/admin/session-stop`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sessionId:t.sessionId})});if(!e.ok){let n=await e.json().catch(()=>({}));console.error(`[admin-ui] sidebar-session-stop-failed sessionId=${t.sessionId} status=${e.status} error=${n.error??`unknown`}`),W({message:`Stop failed: ${n.error??`status ${e.status}`}`,failed:!0});return}console.info(`[admin-ui] sidebar-session-stop sessionId=${t.sessionId}`),X()}catch(e){let n=e instanceof Error?e.message:String(e);console.error(`[admin-ui] sidebar-session-stop-failed sessionId=${t.sessionId} error=${n}`),W({message:`Stop failed: ${n}`,failed:!0})}finally{Ie(e=>{let n=new Set(e);return n.delete(t.sessionId),n})}}},[N,Fe,X]),ot=(0,T.useCallback)(async(e,t,n)=>{if(e.stopPropagation(),!Le.has(t.sessionId)){Re(e=>{let n=new Set(e);return n.add(t.sessionId),n});try{let e=await N(`/api/admin/session-archive`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sessionId:t.sessionId,mode:n})});if(!e.ok){let r=await e.json().catch(()=>({})),i=r.detail??r.error??`status ${e.status}`;console.error(`[admin-ui] sidebar-session-archive-failed sessionId=${t.sessionId} mode=${n} status=${e.status} error=${r.error??`unknown`}`),W({message:`${n===`archive`?`Archive`:`Unarchive`} failed: ${i}`,failed:!0});return}console.info(`[admin-ui] sidebar-session-archive sessionId=${t.sessionId} mode=${n}`),X()}catch(e){let r=e instanceof Error?e.message:String(e);console.error(`[admin-ui] sidebar-session-archive-failed sessionId=${t.sessionId} mode=${n} error=${r}`),W({message:`${n===`archive`?`Archive`:`Unarchive`} failed: ${r}`,failed:!0})}finally{Re(e=>{let n=new Set(e);return n.delete(t.sessionId),n})}}},[N,Le,X]);return(0,E.jsxs)(`aside`,{className:`side`,children:[(0,E.jsx)(`div`,{className:`side-new-session-row`,children:(0,E.jsxs)(`button`,{type:`button`,className:`side-new-session`,onClick:rt,disabled:J,"aria-busy":J,children:[(0,E.jsx)(S,{size:14}),(0,E.jsx)(`span`,{children:J?`Spawning…`:`New session`})]})}),(0,E.jsxs)(`nav`,{className:`side-nav`,children:[(0,E.jsxs)(`button`,{type:`button`,className:`nav-row`,onClick:()=>{console.info(`[admin-ui] sidebar-nav surface=people`),_(),k()},children:[(0,E.jsx)(w,{size:20,strokeWidth:$}),(0,E.jsx)(`span`,{className:`label`,children:`People`}),(0,E.jsx)(`span`,{className:`kbd`})]}),(0,E.jsxs)(`button`,{type:`button`,className:`nav-row`,onClick:()=>{console.info(`[admin-ui] sidebar-nav surface=agents`),O(),k()},children:[(0,E.jsx)(y,{size:20,strokeWidth:$}),(0,E.jsx)(`span`,{className:`label`,children:`Agents`}),(0,E.jsx)(`span`,{className:`kbd`})]}),(0,E.jsxs)(`button`,{type:`button`,className:`nav-row`,onClick:()=>{console.info(`[admin-ui] sidebar-nav surface=projects`),ee(),k()},children:[(0,E.jsx)(ne,{size:20,strokeWidth:$}),(0,E.jsx)(`span`,{className:`label`,children:`Projects`}),(0,E.jsx)(`span`,{className:`kbd`})]}),(0,E.jsxs)(`button`,{type:`button`,className:`nav-row`,onClick:()=>{console.info(`[admin-ui] sidebar-nav surface=tasks`),D(),k()},children:[(0,E.jsx)(x,{size:20,strokeWidth:$}),(0,E.jsx)(`span`,{className:`label`,children:`Tasks`}),(0,E.jsx)(`span`,{className:`kbd`})]}),(0,E.jsxs)(`button`,{type:`button`,className:`nav-row${F===`artefacts`?` active`:``}`,onClick:Xe,children:[(0,E.jsx)(g,{size:20,strokeWidth:$}),(0,E.jsx)(`span`,{className:`label`,children:`Artefacts`}),(0,E.jsx)(`span`,{className:`kbd`})]}),(0,E.jsxs)(`button`,{type:`button`,className:`nav-row${F===`sessions`?` active`:``}`,onClick:Qe,children:[(0,E.jsx)(b,{size:20,strokeWidth:$}),(0,E.jsx)(`span`,{className:`label`,children:`Sessions`}),(0,E.jsx)(`span`,{className:`kbd`})]}),He&&j.filter(e=>Q.get(e).length>0).map(e=>(0,E.jsxs)(`button`,{type:`button`,className:`nav-row${F===`whatsapp`&&Y===e?` active`:``}`,onClick:()=>et(e),children:[(0,E.jsx)(u,{channel:e,size:16}),(0,E.jsx)(`span`,{className:`label`,children:Ye[e]}),(0,E.jsx)(`span`,{className:`kbd`})]},e)),We&&(0,E.jsx)(`div`,{className:`nav-row`,style:{color:`var(--text-tertiary)`,cursor:`default`},"aria-disabled":`true`,children:(0,E.jsx)(`span`,{className:`label`,children:We})})]}),F===`artefacts`&&(0,E.jsxs)(`div`,{className:`side-list`,children:[(0,E.jsxs)(`div`,{className:`group-head`,children:[(0,E.jsx)(`span`,{children:`Artefacts`}),(0,E.jsxs)(`span`,{className:`group-head-meta`,children:[(0,E.jsx)(`button`,{type:`button`,className:`group-head-refresh`,title:`Refresh artefacts`,"aria-label":`Refresh artefacts`,onClick:Ze,disabled:V,children:(0,E.jsx)(l,{size:12,className:V?`spinning`:void 0})}),(0,E.jsx)(`span`,{children:V?`…`:String(L.length)})]})]}),z&&(0,E.jsx)(`div`,{className:`conv`,style:{color:`var(--text-tertiary)`,cursor:`default`},children:z}),R&&!z&&L.length>0&&(()=>{let e=L.filter(e=>e.kind===`agent-template`).length,t=L.length-e;return(0,E.jsx)(`div`,{className:`artefact-filter-chips`,children:[{key:`all`,label:`All`,count:L.length},{key:`agent`,label:`Agents`,count:e},{key:`file`,label:`Files`,count:t}].map(e=>(0,E.jsxs)(`button`,{type:`button`,className:`artefact-filter-chip${H===e.key?` active`:``}`,onClick:()=>_e(e.key),disabled:e.count===0&&e.key!==`all`,children:[e.label,(0,E.jsx)(`span`,{className:`artefact-filter-chip-count`,children:e.count})]},e.key))})})(),R&&!z&&L.length===0&&(0,E.jsx)(`div`,{className:`conv`,style:{color:`var(--text-tertiary)`,cursor:`default`},children:`No artefacts yet`}),L.filter(e=>H===`all`?!0:H===`agent`?e.kind===`agent-template`:e.kind!==`agent-template`).map(e=>{let t=e.kind===`agent-template`,n=t?y:g,r=ue(e.updatedAt),i=e.downloadPath!==null;return(0,E.jsxs)(`button`,{type:`button`,className:`conv`,onClick:()=>qe(e),disabled:!i,style:i?void 0:{cursor:`default`},title:i?`Download ${e.name}`:`${e.name} can’t be downloaded`,children:[(0,E.jsx)(n,{size:14,className:`conv-icon`,"data-kind":t?`agent`:`file`,"aria-label":t?`agent template`:`file`}),(0,E.jsxs)(`span`,{className:`conv-stack`,children:[(0,E.jsx)(`span`,{className:`conv-name-line`,children:(0,E.jsx)(`span`,{className:`conv-name`,children:e.name})}),r&&(0,E.jsx)(`span`,{className:`conv-timestamp`,children:r})]}),i&&(0,E.jsx)(o,{size:12,className:`conv-rc-icon`,"aria-hidden":`true`})]},e.id)})]}),F===`sessions`&&(()=>{let e=K.filter(e=>Te?!0:!e.isSubagent).filter(e=>De?!0:!e.archived),t=K.some(e=>e.isSubagent),n=K.some(e=>e.archived);return(0,E.jsxs)(`div`,{className:`side-list`,children:[(0,E.jsxs)(`div`,{className:`group-head`,children:[(0,E.jsx)(`span`,{children:`Sessions`}),(0,E.jsxs)(`span`,{className:`group-head-meta`,children:[(0,E.jsx)(`button`,{type:`button`,className:`group-head-refresh`,title:`Refresh sessions`,"aria-label":`Refresh sessions`,onClick:$e,disabled:Ce,children:(0,E.jsx)(l,{size:12,className:Ce?`spinning`:void 0})}),(0,E.jsx)(`span`,{children:Ce?`…`:String(e.length)})]})]}),ke&&(0,E.jsx)(`div`,{className:`side-account-id`,title:`This install's accountId. The first 8 characters match the truncated UUID label on the live Remote Control daemon entry in claude.ai/code.`,children:(0,E.jsx)(`code`,{children:ke})}),(t||n)&&(0,E.jsxs)(`div`,{className:`artefact-filter-chips`,children:[t&&(0,E.jsx)(`button`,{type:`button`,className:`artefact-filter-chip${Te?` active`:``}`,onClick:()=>Ee(e=>!e),title:Te?`Hide subagent sessions`:`Show subagent sessions`,children:`Subagents`}),n&&(0,E.jsx)(`button`,{type:`button`,className:`artefact-filter-chip${De?` active`:``}`,onClick:()=>Oe(e=>!e),title:De?`Hide archived sessions`:`Show archived sessions`,children:`Archived`})]}),xe&&(0,E.jsx)(`div`,{className:`conv`,style:{color:`var(--text-tertiary)`,cursor:`default`},children:xe}),q&&!xe&&e.length===0&&(0,E.jsx)(`div`,{className:`conv`,style:{color:`var(--text-tertiary)`,cursor:`default`},children:`No sessions yet`}),e.map(e=>{let t=ue(e.startedAt),n=Ne.has(e.sessionId),i=je.has(e.sessionId),a=Fe.has(e.sessionId),o=Le.has(e.sessionId);return(0,E.jsxs)(`div`,{className:`conv conv-with-actions`,children:[(0,E.jsxs)(`div`,{className:`conv-main-static`,children:[(0,E.jsx)(`span`,{className:`conv-live-dot`,"data-live":e.live?`1`:`0`,"aria-label":e.live?`live session`:`ended session`}),(0,E.jsxs)(`span`,{className:`conv-stack`,children:[(0,E.jsxs)(`span`,{className:`conv-name-line`,children:[e.channel&&(0,E.jsx)(m,{channel:e.channel,size:13}),(0,E.jsx)(`span`,{className:`conv-name`,title:e.personName??e.title,children:e.personName??e.title})]}),(0,E.jsxs)(`span`,{className:`conv-timestamp`,children:[(0,E.jsx)(`code`,{className:`conv-session-id`,title:`First 8 characters of this session's id — distinguishes rows with identical auto-titles. The resume/delete buttons act on the full id.`,children:e.sessionId.slice(0,8)}),t&&(0,E.jsxs)(`span`,{children:[` · `,t]})]})]})]}),(0,E.jsxs)(`div`,{className:`conv-actions`,children:[e.resumable===!1?(0,E.jsx)(`span`,{className:`conv-ephemeral`,title:`Public webchat session — ephemeral, not resumable`,"aria-label":`Ephemeral public session (not resumable)`,children:(0,E.jsx)(b,{size:12})}):(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(`button`,{type:`button`,className:`conv-action`,onClick:()=>{tt(e)},disabled:n||i||a||o,"aria-busy":n,"aria-label":`Resume session ${e.title} in claude.ai/code`,title:`Resume in a fresh local Remote Control PTY`,children:(0,E.jsx)(h,{size:12})}),(0,E.jsx)(`button`,{type:`button`,className:`conv-action`,onClick:()=>{window.location.assign(`/chat?session=${e.sessionId}`)},disabled:n||i||a||o,"aria-label":`Open session ${e.title} in admin webchat`,title:`Open in admin webchat (/chat) — sending resumes this session`,children:(0,E.jsx)(re,{size:12})})]}),e.live?(0,E.jsx)(`button`,{type:`button`,className:`conv-action`,onClick:t=>{at(t,e)},disabled:n||i||a||o,"aria-busy":a,"aria-label":`Stop session ${e.title}`,title:`Stop session process (keeps the conversation, can resume later)`,children:(0,E.jsx)(C,{size:12})}):null,e.archived?(0,E.jsx)(`button`,{type:`button`,className:`conv-action`,onClick:t=>{ot(t,e,`unarchive`)},disabled:n||i||a||o,"aria-busy":o,"aria-label":`Unarchive session ${e.title}`,title:`Unarchive (move back to the active list)`,children:(0,E.jsx)(te,{size:12})}):(0,E.jsx)(`button`,{type:`button`,className:`conv-action`,onClick:t=>{ot(t,e,`archive`)},disabled:n||i||a||o,"aria-busy":o,"aria-label":`Archive session ${e.title}`,title:`Archive (hide from the list, keeps the conversation resumable)`,children:(0,E.jsx)(v,{size:12})}),(0,E.jsx)(`button`,{type:`button`,className:`conv-action conv-action-danger`,onClick:t=>{it(t,e)},disabled:n||i||a||o,"aria-busy":i,"aria-label":`Delete session ${e.title}`,title:`Delete session (stops the process, removes the conversation)`,children:(0,E.jsx)(r,{size:12})})]})]},e.sessionId)})]})})(),F===`whatsapp`&&(0,E.jsxs)(`div`,{className:`side-list`,children:[(0,E.jsxs)(`div`,{className:`group-head`,children:[(0,E.jsx)(`span`,{children:Ye[Y]}),(0,E.jsxs)(`span`,{className:`group-head-meta`,children:[(0,E.jsx)(`button`,{type:`button`,className:`group-head-refresh`,title:`Refresh conversations`,"aria-label":`Refresh conversations`,onClick:()=>{Z()},children:(0,E.jsx)(l,{size:12})}),(0,E.jsx)(`span`,{children:String(Q.get(Y).length)})]})]}),Q.get(Y).map(e=>{let t=ue(e.lastMessageAt);return(0,E.jsxs)(`button`,{type:`button`,className:`conv${ie===e.sessionId?` active`:``}`,onClick:()=>{M(e),k()},title:e.title,children:[(0,E.jsx)(u,{channel:e.channel,size:14}),(0,E.jsxs)(`span`,{className:`conv-stack`,children:[(0,E.jsxs)(`span`,{className:`conv-name-line`,children:[(0,E.jsx)(`span`,{className:`conv-name`,children:s(e)}),e.role===`public`&&(0,E.jsx)(`span`,{className:`conv-tag conv-tag-public`,children:`Public`})]}),t&&(0,E.jsx)(`span`,{className:`conv-timestamp`,children:t})]})]},e.sessionId)})]}),(0,E.jsx)(pe,{}),(0,E.jsxs)(`div`,{className:`side-foot`,children:[(0,E.jsx)(`div`,{className:`avatar`,children:p?(0,E.jsx)(`img`,{src:p,alt:P}):de}),(0,E.jsxs)(`div`,{className:`who`,children:[(0,E.jsx)(`span`,{className:`name`,children:P}),(0,E.jsx)(`span`,{className:`role`,children:a??`operator`})]})]}),U&&(0,E.jsx)(`div`,{className:`copy-toast${U.failed?` copy-toast-failed`:``}`,role:`status`,children:U.message}),(0,E.jsx)(oe,{error:ve,onClose:()=>G(null)})]})}var F=5e3,fe=3e4;function pe(){let[e,t]=(0,T.useState)(null);if((0,T.useEffect)(()=>{let e=!1,n=null;async function r(){try{let n=await fetch(`/api/admin/system-stats`);if(!n.ok){console.error(`[admin-ui] system-stats-fetch-failed status=${n.status}`);return}let r=await n.json();e||t(r)}catch(e){console.error(`[admin-ui] system-stats-fetch-failed reason=${e instanceof Error?e.message:String(e)}`)}}function i(){n===null&&(r(),n=setInterval(()=>{r()},F))}function a(){n!==null&&(clearInterval(n),n=null)}function o(){document.hidden?a():i()}return document.hidden||i(),document.addEventListener(`visibilitychange`,o),()=>{e=!0,a(),document.removeEventListener(`visibilitychange`,o)}},[]),!e||e.platform===`darwin`)return null;let n=e.cpuPct,r=e.memUsedPct,i=n!==null&&n>=.9,a=n!==null&&n>=.98,o=r!==null&&r>=.9,s=r!==null&&r>=.98,c=i||o,l=a||s,u=e=>e===null?`—`:`${Math.round(e*100)}%`,d=e=>{if(e===null)return{width:`0%`,background:`var(--text-tertiary)`};let t=Math.min(1,Math.max(0,e)),n=Math.round(140*(1-t));return{width:`${Math.round(t*100)}%`,background:`hsl(${n}, 65%, 45%)`}},f=[`system-stats`];return c&&f.push(`system-stats--warn`),l&&f.push(`system-stats--crit`),(0,E.jsxs)(`div`,{className:f.join(` `),role:`status`,"aria-label":`host CPU and RAM`,children:[(0,E.jsxs)(`div`,{className:`system-stats__metric`,children:[(0,E.jsxs)(`span`,{className:i?`system-stats__fig system-stats__fig--warn`:`system-stats__fig`,children:[`CPU `,u(n)]}),(0,E.jsx)(`div`,{className:`system-stats__bar`,children:(0,E.jsx)(`div`,{className:`system-stats__bar-fill`,style:d(n)})})]}),(0,E.jsxs)(`div`,{className:`system-stats__metric`,children:[(0,E.jsxs)(`span`,{className:o?`system-stats__fig system-stats__fig--warn`:`system-stats__fig`,children:[`RAM `,u(r)]}),(0,E.jsx)(`div`,{className:`system-stats__bar`,children:(0,E.jsx)(`div`,{className:`system-stats__bar-fill`,style:d(r)})})]})]})}var I=`admin-sidebar-collapsed`,L=`admin-sidebar-drawer-open`;function me(){if(typeof window>`u`)return!1;try{return window.sessionStorage.getItem(I)===`1`}catch{return!1}}function R(e){if(!(typeof window>`u`))try{e?window.sessionStorage.setItem(I,`1`):window.sessionStorage.removeItem(I)}catch{}}function he(){if(typeof window>`u`)return!1;try{return window.sessionStorage.getItem(L)===`1`}catch{return!1}}function z(e){if(!(typeof window>`u`))try{e?window.sessionStorage.setItem(L,`1`):window.sessionStorage.removeItem(L)}catch{}}var B=720;function V(e,t){return e===`/`?{via:`in-place`}:{via:`navigate`,href:`/?wa=${encodeURIComponent(t.sessionId)}&projectDir=${encodeURIComponent(t.projectDir)}`}}function ge(e,t){if(e!==`/`)return null;let n=new URLSearchParams(t),r=n.get(`wa`),i=n.get(`projectDir`);return!r||!i?null:{sessionId:r,projectDir:i,title:``,senderId:null,startedAt:``,channel:`whatsapp`,role:`admin`,operatorName:null,whatsappName:null,lastMessageAt:null,modelGated:!1}}function H(e,t){return t===`operator`&&e===`chat`||e===`dashboard`?`/`:e===`data`?`/data`:e===`graph`?`/graph`:e===`chat`?`/chat`:`/browser`}function _e(e){let{cacheKey:t,businessName:n,variant:r=`admin`,onLogout:i,onDisconnect:a,disconnecting:o,userName:s,userAvatar:l,role:u,children:d,footer:f}=e,[m,h]=(0,T.useState)(()=>me()),[g,ee]=(0,T.useState)(()=>he()),[_,te]=(0,T.useState)(()=>typeof window<`u`&&window.matchMedia(`(max-width: ${B}px)`).matches),[v,y]=(0,T.useState)(()=>typeof window>`u`?null:ge(window.location.pathname,window.location.search)),[ne]=(0,T.useState)(()=>v!==null);(0,T.useEffect)(()=>{if(typeof window>`u`)return;let e=window.matchMedia(`(max-width: ${B}px)`),t=e=>te(e.matches);return e.addEventListener(`change`,t),()=>e.removeEventListener(`change`,t)},[]);let b=(0,T.useCallback)(e=>{R(e),h(e)},[]),x=(0,T.useCallback)(e=>{z(e),ee(e)},[]);(0,T.useEffect)(()=>{if(typeof window>`u`)return;let e=window.location?.pathname??``;console.info(`[admin-ui] shell-mount route=${e} variant=${r} sidebar=${r===`operator`?`none`:`present`} collapsed=${m} drawer=${g}`)},[]),(0,T.useEffect)(()=>{typeof window>`u`||!v||(console.info(`[admin-ui] wa-hydrate route=/ sessionId=${v.sessionId.slice(0,8)}`),window.history.replaceState(null,``,`/`))},[]);let re=(0,T.useCallback)(e=>{if(e===null){y(null);return}let t=typeof window<`u`?window.location.pathname:`/`,n=V(t,e);console.info(`[admin-ui] wa-open route=${t} via=${n.via} sessionId=${e.sessionId.slice(0,8)}`),n.via===`in-place`?y(e):window.location.href=n.href},[]),S=_?g:!m,C=(0,T.useCallback)(()=>{if(!(typeof window>`u`))if(window.matchMedia(`(max-width: ${B}px)`).matches){let e=g;console.info(`[admin-ui] header-sidebar-toggle from=${e?`open`:`closed`} mode=drawer`),x(!e)}else{let e=m;console.info(`[admin-ui] header-sidebar-toggle from=${e?`closed`:`open`} mode=collapse`),b(!e)}},[m,g,b,x]),w=(0,T.useCallback)(e=>{let t=H(e,r);console.info(`[admin-ui] header-menu-nav target=${e} dest=${t}`),window.location.href=t},[r]),[D,O]=(0,T.useState)(`chat`),[k,A]=(0,T.useState)([]);(0,T.useEffect)(()=>{if(r!==`operator`||!t)return;let e=!1;return fetch(`/api/whatsapp-reader/conversations?session_key=${encodeURIComponent(t)}`).then(e=>e.ok?e.json():{conversations:[]}).then(t=>{e||A(t.conversations??[])}).catch(()=>{}),()=>{e=!0}},[r,t]);let j=(0,T.useMemo)(()=>[...new Set(k.map(e=>e.channel))],[k]),M={collapsed:m,mobileDrawerOpen:g,sidebarOpen:S,onToggleSidebar:C,setMobileDrawerOpen:x,selectedWhatsapp:v,onClearWhatsapp:()=>y(null)};return r===`operator`?(0,E.jsxs)(`div`,{className:`admin-shell admin-page admin-shell-root`,children:[(0,E.jsx)(c,{businessName:n,variant:r,onNavigate:w,conversationsCount:k.length,conversationsChannels:j,onOpenConversations:()=>O(`conversations`),onToggleSidebar:C,sidebarOpen:S,onLogout:i,onDisconnect:a,disconnecting:o}),(0,E.jsx)(`div`,{className:`platform platform-operator`,children:D===`conversations`?(0,E.jsx)(p,{conversations:k,sessionKey:t??``,onBack:()=>O(`chat`)}):typeof d==`function`?d(M):d}),f]}):(0,E.jsxs)(`div`,{className:`admin-shell admin-page admin-shell-root`,children:[(0,E.jsx)(c,{businessName:n,variant:r,onNavigate:w,onToggleSidebar:C,sidebarOpen:S,onLogout:i,onDisconnect:a,disconnecting:o}),(0,E.jsxs)(`div`,{className:`platform${g?` menu-open`:``}${m?` sidebar-collapsed`:``}`,"data-artefact":`closed`,children:[(0,E.jsx)(de,{businessName:n,cacheKey:t,role:u??null,userName:s,userAvatar:l??null,onSelectProjects:()=>{window.location.href=`/graph?label=Project`},onSelectPeople:()=>{window.location.href=`/graph?label=Person`},onSelectTasks:()=>{window.location.href=`/graph?label=Task`},onSelectAgents:()=>{window.location.href=`/graph?label=Agent`},onCloseMobileDrawer:()=>x(!1),collapsed:m,mobileDrawerOpen:g,selectedWhatsappId:v?.sessionId??null,onSelectWhatsappConversation:re,initialWhatsappSurface:ne}),!_&&(0,E.jsx)(ie,{}),typeof d==`function`?d(M):d]}),g&&(0,E.jsx)(`div`,{className:`sidebar-backdrop menu-open`,"aria-hidden":`true`,onClick:()=>x(!1)}),f]})}export{x as a,S as i,se as n,y as o,w as r,_ as s,_e as t};
|