@rubytech/create-maxy-code 0.1.378 → 0.1.379
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 +3 -3
- package/payload/platform/plugins/docs/references/admin-ui.md +2 -2
- package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +13 -0
- package/payload/server/{chunk-AQO6KLIH.js → chunk-ZYS5V5QG.js} +0 -21
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/public/assets/{AdminLoginScreens-B9u1V35g.js → AdminLoginScreens-BHo8w_9J.js} +1 -1
- package/payload/server/public/assets/AdminShell-DbTijFVA.js +1 -0
- package/payload/server/public/assets/{Checkbox-B2g2SCpw.js → Checkbox-LmjNFccS.js} +1 -1
- package/payload/server/public/assets/admin-BBWILfl8.js +1 -0
- package/payload/server/public/assets/{browser-B8omhYsK.js → browser-DtLvD_ES.js} +1 -1
- package/payload/server/public/assets/calendar-D3i4IqOV.js +1 -0
- package/payload/server/public/assets/chat-DU-T6blN.js +1 -0
- package/payload/server/public/assets/data-B_vDxQrO.js +1 -0
- package/payload/server/public/assets/{graph-DJOKFr_s.js → graph-ClQeGEH4.js} +3 -3
- package/payload/server/public/assets/{graph-labels-DFdBydWC.js → graph-labels-OaIKHgMg.js} +1 -1
- package/payload/server/public/assets/operator-Dxqfta5U.js +1 -0
- package/payload/server/public/assets/{page-BMeSKYGZ.js → page-BkIb7CHh.js} +4 -4
- package/payload/server/public/assets/page-Dv_YEOUW.js +1 -0
- package/payload/server/public/assets/{public-CGl0i1f-.js → public-C_mM8sSZ.js} +1 -1
- package/payload/server/public/assets/{rotate-ccw-Cg_V4XIU.js → rotate-ccw-VF0b6NTt.js} +1 -1
- package/payload/server/public/assets/useSubAccountSwitcher-CQbgG-FH.js +9 -0
- package/payload/server/public/assets/{useSubAccountSwitcher-Ca1GJeBC.css → useSubAccountSwitcher-VzvzZC7h.css} +1 -1
- package/payload/server/public/browser.html +4 -4
- package/payload/server/public/calendar.html +4 -4
- package/payload/server/public/chat.html +6 -6
- package/payload/server/public/data.html +5 -5
- package/payload/server/public/graph.html +7 -7
- package/payload/server/public/index.html +8 -8
- package/payload/server/public/operator.html +8 -8
- package/payload/server/public/public.html +6 -6
- package/payload/server/server.js +247 -72
- package/payload/server/public/assets/AdminShell-C2UXTLSB.js +0 -1
- package/payload/server/public/assets/admin-CRBQgWsm.js +0 -1
- package/payload/server/public/assets/calendar-Blb-5arm.js +0 -1
- package/payload/server/public/assets/chat--1ajLxwi.js +0 -1
- package/payload/server/public/assets/data-BYUmu98z.js +0 -1
- package/payload/server/public/assets/operator-DUVqlubZ.js +0 -1
- package/payload/server/public/assets/page-DBkTNfei.js +0 -1
- package/payload/server/public/assets/useSubAccountSwitcher-DAgBUed_.js +0 -9
package/payload/server/server.js
CHANGED
|
@@ -72,7 +72,6 @@ import {
|
|
|
72
72
|
loadAdminUserName,
|
|
73
73
|
loadPersonNameByElementId,
|
|
74
74
|
loadUserProfile,
|
|
75
|
-
loadWhatsappSenderName,
|
|
76
75
|
migrateLegacyRemotePassword,
|
|
77
76
|
persistMessage,
|
|
78
77
|
projectAgent,
|
|
@@ -110,7 +109,7 @@ import {
|
|
|
110
109
|
vncLog,
|
|
111
110
|
walkPremiumBundles,
|
|
112
111
|
writeAdminUserAndPerson
|
|
113
|
-
} from "./chunk-
|
|
112
|
+
} from "./chunk-ZYS5V5QG.js";
|
|
114
113
|
import {
|
|
115
114
|
__commonJS,
|
|
116
115
|
__toESM
|
|
@@ -1869,6 +1868,24 @@ function readSelfId(authDir) {
|
|
|
1869
1868
|
return { e164: null, jid: null, lid: null };
|
|
1870
1869
|
}
|
|
1871
1870
|
}
|
|
1871
|
+
function credsCensus(authDir) {
|
|
1872
|
+
const raw = readCredsJsonRaw(resolveCredsPath(authDir));
|
|
1873
|
+
if (!raw) return { credsPresent: false, registered: false, hasAccountSignature: false, e164: null };
|
|
1874
|
+
try {
|
|
1875
|
+
const parsed = JSON.parse(raw);
|
|
1876
|
+
const registered = parsed?.registered === true;
|
|
1877
|
+
const hasAccountSignature = parsed?.account != null;
|
|
1878
|
+
let e164 = null;
|
|
1879
|
+
const jid = parsed?.me?.id;
|
|
1880
|
+
if (jid) {
|
|
1881
|
+
const match = jid.match(/^(\d+)(?::\d+)?@s\.whatsapp\.net$/i);
|
|
1882
|
+
if (match) e164 = match[1];
|
|
1883
|
+
}
|
|
1884
|
+
return { credsPresent: true, registered, hasAccountSignature, e164 };
|
|
1885
|
+
} catch {
|
|
1886
|
+
return { credsPresent: true, registered: false, hasAccountSignature: false, e164: null };
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1872
1889
|
async function clearAuth(authDir) {
|
|
1873
1890
|
try {
|
|
1874
1891
|
await fs.access(authDir);
|
|
@@ -2027,13 +2044,22 @@ function enqueueSaveCreds(authDir, saveCreds) {
|
|
|
2027
2044
|
});
|
|
2028
2045
|
}
|
|
2029
2046
|
async function createWaSocket(opts) {
|
|
2030
|
-
const { authDir, onQr, onConnectionUpdate, silent } = opts;
|
|
2047
|
+
const { authDir, onQr, onConnectionUpdate, silent, correlationId, account, getCodeIssuedTs } = opts;
|
|
2048
|
+
const cid = correlationId ?? "none";
|
|
2049
|
+
const acct = account ?? "unknown";
|
|
2031
2050
|
await fs2.mkdir(authDir, { recursive: true });
|
|
2032
2051
|
maybeRestoreCredsFromBackup(authDir);
|
|
2033
2052
|
const { state, saveCreds } = await useMultiFileAuthState(authDir);
|
|
2034
2053
|
const { version } = await fetchLatestBaileysVersion();
|
|
2054
|
+
if (!silent) {
|
|
2055
|
+
const preCensus = credsCensus(authDir);
|
|
2056
|
+
console.error(
|
|
2057
|
+
`${TAG2} op=creds-pre cid=${cid} account=${acct} credsPresent=${preCensus.credsPresent} registered=${preCensus.registered} hasAccount=${preCensus.hasAccountSignature}`
|
|
2058
|
+
);
|
|
2059
|
+
}
|
|
2060
|
+
const openTs = Date.now();
|
|
2035
2061
|
console.error(
|
|
2036
|
-
`${TAG2}
|
|
2062
|
+
`${TAG2} op=socket-open cid=${cid} account=${acct} baileysVersion=${baileysPkgVersion} waProtocolVersion=${version.join(".")} openTs=${openTs}`
|
|
2037
2063
|
);
|
|
2038
2064
|
const baileysLogger = createBaileysLogger();
|
|
2039
2065
|
const sock = makeWASocket({
|
|
@@ -2054,6 +2080,9 @@ async function createWaSocket(opts) {
|
|
|
2054
2080
|
enqueueSaveCreds(authDir, saveCreds);
|
|
2055
2081
|
});
|
|
2056
2082
|
let qrSequence = 0;
|
|
2083
|
+
let everOpen = false;
|
|
2084
|
+
let lastQrTs = 0;
|
|
2085
|
+
let pairSuccessLogged = false;
|
|
2057
2086
|
sock.ev.on("connection.update", (update) => {
|
|
2058
2087
|
try {
|
|
2059
2088
|
const parts = [];
|
|
@@ -2069,17 +2098,40 @@ async function createWaSocket(opts) {
|
|
|
2069
2098
|
if (!silent && parts.length > 0) {
|
|
2070
2099
|
console.error(`${TAG2} connection.update ${parts.join(" ")}`);
|
|
2071
2100
|
}
|
|
2101
|
+
if (update.qr && !silent) {
|
|
2102
|
+
const now = Date.now();
|
|
2103
|
+
const sinceLastRefMs = lastQrTs ? now - lastQrTs : null;
|
|
2104
|
+
lastQrTs = now;
|
|
2105
|
+
console.error(
|
|
2106
|
+
`${TAG2} op=qr cid=${cid} qr=#${qrSequence} sinceOpenMs=${now - openTs} sinceLastRefMs=${sinceLastRefMs ?? "n/a"}`
|
|
2107
|
+
);
|
|
2108
|
+
}
|
|
2109
|
+
if (update.isNewLogin === true && !pairSuccessLogged && !silent) {
|
|
2110
|
+
pairSuccessLogged = true;
|
|
2111
|
+
const codeIssuedTs = getCodeIssuedTs?.();
|
|
2112
|
+
const sinceCodeIssuedMs = codeIssuedTs ? Date.now() - codeIssuedTs : null;
|
|
2113
|
+
const afterCensus = credsCensus(authDir);
|
|
2114
|
+
console.error(
|
|
2115
|
+
`${TAG2} op=pair-success cid=${cid} account=${acct} sinceCodeIssuedMs=${sinceCodeIssuedMs ?? "n/a"} hasAccountAfter=${afterCensus.hasAccountSignature}`
|
|
2116
|
+
);
|
|
2117
|
+
}
|
|
2072
2118
|
if (update.qr && onQr) {
|
|
2073
2119
|
onQr(update.qr);
|
|
2074
2120
|
}
|
|
2075
2121
|
if (update.connection === "close") {
|
|
2076
2122
|
const status = getStatusCode(update.lastDisconnect?.error);
|
|
2123
|
+
if (!silent) {
|
|
2124
|
+
console.error(
|
|
2125
|
+
`${TAG2} op=close cid=${cid} account=${acct} status=${status ?? "unknown"} reason="${formatError(update.lastDisconnect?.error)}" socketLifeMs=${Date.now() - openTs} kind=${closeKind(status, everOpen)}`
|
|
2126
|
+
);
|
|
2127
|
+
}
|
|
2077
2128
|
if (status === DisconnectReason.loggedOut && !silent) {
|
|
2078
2129
|
console.error(`${TAG2} session logged out (401) \u2014 re-link required`);
|
|
2079
2130
|
}
|
|
2080
2131
|
}
|
|
2081
|
-
if (update.connection === "open"
|
|
2082
|
-
|
|
2132
|
+
if (update.connection === "open") {
|
|
2133
|
+
everOpen = true;
|
|
2134
|
+
if (!silent) console.error(`${TAG2} connected`);
|
|
2083
2135
|
}
|
|
2084
2136
|
onConnectionUpdate?.(update);
|
|
2085
2137
|
} catch (err) {
|
|
@@ -2143,6 +2195,12 @@ function extractBoomDetails(err) {
|
|
|
2143
2195
|
if (!statusCode && !error && !message) return null;
|
|
2144
2196
|
return { statusCode, error, message };
|
|
2145
2197
|
}
|
|
2198
|
+
function closeKind(status, everOpen) {
|
|
2199
|
+
if (status === DisconnectReason.restartRequired) return "restart-required-515";
|
|
2200
|
+
if (status === DisconnectReason.loggedOut) return "logged-out-401";
|
|
2201
|
+
if (status === 408) return everOpen ? "conn-lost-408" : "qr-refs-ended-408";
|
|
2202
|
+
return "other";
|
|
2203
|
+
}
|
|
2146
2204
|
|
|
2147
2205
|
// app/lib/whatsapp/reconnect.ts
|
|
2148
2206
|
import { DisconnectReason as DisconnectReason2 } from "@whiskeysockets/baileys";
|
|
@@ -3102,6 +3160,9 @@ var STORE_ROOT = () => join3(process.env.MAXY_DIR_OVERRIDE ?? MAXY_DIR, "data",
|
|
|
3102
3160
|
function conversationFile(platformAccountId, remoteJid) {
|
|
3103
3161
|
return join3(STORE_ROOT(), platformAccountId, `${remoteJid}.jsonl`);
|
|
3104
3162
|
}
|
|
3163
|
+
function conversationFilePath(platformAccountId, remoteJid) {
|
|
3164
|
+
return conversationFile(platformAccountId, remoteJid);
|
|
3165
|
+
}
|
|
3105
3166
|
function parseLines(raw) {
|
|
3106
3167
|
const out = [];
|
|
3107
3168
|
for (const line of raw.split("\n")) {
|
|
@@ -6055,6 +6116,13 @@ async function runPostPairing(login) {
|
|
|
6055
6116
|
}
|
|
6056
6117
|
async function loginConnectionLoop(accountId, login) {
|
|
6057
6118
|
let attempt = 0;
|
|
6119
|
+
const cidShort = login.id.slice(0, 8);
|
|
6120
|
+
const logTerminal = (outcome, errMsg) => {
|
|
6121
|
+
const fc = credsCensus(login.authDir);
|
|
6122
|
+
console.error(
|
|
6123
|
+
`${TAG17} op=terminal cid=${cidShort} outcome=${outcome} credsFinal={registered=${fc.registered},account=${fc.hasAccountSignature},me=${fc.e164 ?? "null"}}` + (errMsg ? ` error="${errMsg}"` : "")
|
|
6124
|
+
);
|
|
6125
|
+
};
|
|
6058
6126
|
while (true) {
|
|
6059
6127
|
try {
|
|
6060
6128
|
await waitForConnection(login.sock);
|
|
@@ -6063,6 +6131,7 @@ async function loginConnectionLoop(accountId, login) {
|
|
|
6063
6131
|
await runPostPairing(current);
|
|
6064
6132
|
current.connected = true;
|
|
6065
6133
|
console.error(`${TAG17} loginConnectionLoop: connected account=${accountId} attempt=${attempt} configPersisted=${current.configPersisted}`);
|
|
6134
|
+
logTerminal("connected");
|
|
6066
6135
|
}
|
|
6067
6136
|
return;
|
|
6068
6137
|
} catch (err) {
|
|
@@ -6079,6 +6148,7 @@ async function loginConnectionLoop(accountId, login) {
|
|
|
6079
6148
|
current.error = formatError(err);
|
|
6080
6149
|
}
|
|
6081
6150
|
current.errorStatus = getStatusCode(err);
|
|
6151
|
+
logTerminal("error", current.error);
|
|
6082
6152
|
return;
|
|
6083
6153
|
}
|
|
6084
6154
|
attempt++;
|
|
@@ -6090,14 +6160,19 @@ async function loginConnectionLoop(accountId, login) {
|
|
|
6090
6160
|
await new Promise((r) => setTimeout(r, delay));
|
|
6091
6161
|
const afterDelay = activeLogins.get(accountId);
|
|
6092
6162
|
if (afterDelay?.id !== login.id) return;
|
|
6163
|
+
const rc = credsCensus(login.authDir);
|
|
6164
|
+
console.error(
|
|
6165
|
+
`${TAG17} op=reconnect cid=${cidShort} attempt=${attempt}/${LOGIN_MAX_RECONNECTS} withRegistered=${rc.registered} withAccount=${rc.hasAccountSignature}`
|
|
6166
|
+
);
|
|
6093
6167
|
try {
|
|
6094
|
-
const newSock = await createWaSocket({ authDir: login.authDir });
|
|
6168
|
+
const newSock = await createWaSocket({ authDir: login.authDir, correlationId: cidShort, account: accountId });
|
|
6095
6169
|
current.sock = newSock;
|
|
6096
6170
|
} catch (sockErr) {
|
|
6097
6171
|
console.error(
|
|
6098
6172
|
`${TAG17} reconnect socket creation failed (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}): ${String(sockErr)}`
|
|
6099
6173
|
);
|
|
6100
6174
|
current.error = `Reconnection failed: ${String(sockErr)}`;
|
|
6175
|
+
logTerminal("error", current.error);
|
|
6101
6176
|
return;
|
|
6102
6177
|
}
|
|
6103
6178
|
}
|
|
@@ -6105,11 +6180,13 @@ async function loginConnectionLoop(accountId, login) {
|
|
|
6105
6180
|
}
|
|
6106
6181
|
async function startLogin(opts) {
|
|
6107
6182
|
const { accountId, authDir, phone, accountDir = null, force, timeoutMs = 3e4 } = opts;
|
|
6183
|
+
const loginId = randomUUID6();
|
|
6184
|
+
const cid = loginId.slice(0, 8);
|
|
6108
6185
|
const existing0 = activeLogins.get(accountId);
|
|
6109
6186
|
const hasAuth = await authExists(authDir);
|
|
6110
6187
|
const selfId = readSelfId(authDir);
|
|
6111
6188
|
console.error(
|
|
6112
|
-
`${TAG17}
|
|
6189
|
+
`${TAG17} op=start cid=${cid} account=${accountId} force=${!!force} hasAuth=${hasAuth}` + (existing0 ? ` activeLogin={id=${existing0.id.slice(0, 8)},age=${Math.round((Date.now() - existing0.startedAt) / 1e3)}s,hasCode=${!!existing0.pairingCode}}` : " activeLogin=none")
|
|
6113
6190
|
);
|
|
6114
6191
|
if (hasAuth && !force) {
|
|
6115
6192
|
const who = selfId.e164 ?? selfId.jid ?? "unknown";
|
|
@@ -6148,21 +6225,32 @@ async function startLogin(opts) {
|
|
|
6148
6225
|
);
|
|
6149
6226
|
let requested = false;
|
|
6150
6227
|
let sock;
|
|
6228
|
+
let socketOpenTs = 0;
|
|
6229
|
+
let codeIssuedTs;
|
|
6151
6230
|
try {
|
|
6152
6231
|
sock = await createWaSocket({
|
|
6153
6232
|
authDir,
|
|
6233
|
+
correlationId: cid,
|
|
6234
|
+
account: accountId,
|
|
6235
|
+
getCodeIssuedTs: () => codeIssuedTs,
|
|
6154
6236
|
// The first QR event means the noise handshake is complete and the
|
|
6155
6237
|
// socket can send the pairing IQ — the safe moment to request the code.
|
|
6156
6238
|
// We never render the QR; it is only a readiness signal.
|
|
6157
6239
|
onQr: () => {
|
|
6158
6240
|
if (requested) return;
|
|
6159
6241
|
requested = true;
|
|
6242
|
+
console.error(
|
|
6243
|
+
`${TAG17} op=pairing-request cid=${cid} account=${accountId} qrRef=#1 sinceOpenMs=${socketOpenTs ? Date.now() - socketOpenTs : 0}`
|
|
6244
|
+
);
|
|
6160
6245
|
void sock.requestPairingCode(digits).then((code) => {
|
|
6161
6246
|
clearTimeout(codeTimer);
|
|
6247
|
+
codeIssuedTs = Date.now();
|
|
6162
6248
|
const current = activeLogins.get(accountId);
|
|
6163
6249
|
if (current?.id !== login.id) return;
|
|
6164
6250
|
if (!current.pairingCode) current.pairingCode = code;
|
|
6165
|
-
console.error(
|
|
6251
|
+
console.error(
|
|
6252
|
+
`${TAG17} op=code-issued cid=${cid} account=${accountId} phone=${maskPhone(digits)} codeLen=${code.length} sinceOpenMs=${socketOpenTs ? codeIssuedTs - socketOpenTs : 0}`
|
|
6253
|
+
);
|
|
6166
6254
|
resolveCode?.(code);
|
|
6167
6255
|
}).catch((err) => {
|
|
6168
6256
|
clearTimeout(codeTimer);
|
|
@@ -6170,6 +6258,7 @@ async function startLogin(opts) {
|
|
|
6170
6258
|
});
|
|
6171
6259
|
}
|
|
6172
6260
|
});
|
|
6261
|
+
socketOpenTs = Date.now();
|
|
6173
6262
|
} catch (err) {
|
|
6174
6263
|
clearTimeout(codeTimer);
|
|
6175
6264
|
resetActiveLogin(accountId);
|
|
@@ -6179,7 +6268,7 @@ async function startLogin(opts) {
|
|
|
6179
6268
|
accountId,
|
|
6180
6269
|
authDir,
|
|
6181
6270
|
accountDir,
|
|
6182
|
-
id:
|
|
6271
|
+
id: loginId,
|
|
6183
6272
|
sock,
|
|
6184
6273
|
startedAt: Date.now(),
|
|
6185
6274
|
phone: digits,
|
|
@@ -6474,6 +6563,10 @@ function reconcileCredsOnDisk(opts) {
|
|
|
6474
6563
|
for (const accountId of listCredsAccountIds(credsRoot)) {
|
|
6475
6564
|
if (liveAccountIds.has(accountId)) continue;
|
|
6476
6565
|
const authDir = join9(credsRoot, accountId);
|
|
6566
|
+
const census = credsCensus(authDir);
|
|
6567
|
+
if (census.registered && !census.hasAccountSignature) {
|
|
6568
|
+
console.error(`${TAG19} op=half-registered account=${accountId} registered=true hasAccount=false`);
|
|
6569
|
+
}
|
|
6477
6570
|
const selfPhone = readSelfId(authDir).e164 ?? void 0;
|
|
6478
6571
|
const configured = accountDir ? isAccountConfigured(accountDir, accountId) : false;
|
|
6479
6572
|
console.error(
|
|
@@ -6947,9 +7040,39 @@ function selectReaderChannelSessions(rows) {
|
|
|
6947
7040
|
lastMessageAt: r.lastMessageAt,
|
|
6948
7041
|
modelGated: r.modelGated,
|
|
6949
7042
|
model: r.model,
|
|
6950
|
-
|
|
7043
|
+
source: "session"
|
|
6951
7044
|
}));
|
|
6952
7045
|
}
|
|
7046
|
+
function buildStoreConversationRows(accountId, convos) {
|
|
7047
|
+
const rows = [];
|
|
7048
|
+
for (const [remoteJid, messages] of convos) {
|
|
7049
|
+
if (messages.length === 0) continue;
|
|
7050
|
+
const last = messages[messages.length - 1];
|
|
7051
|
+
const scope = last.scope;
|
|
7052
|
+
const isGroup = remoteJid.endsWith("@g.us");
|
|
7053
|
+
const senderTelephone = isGroup ? null : messages[0].senderTelephone;
|
|
7054
|
+
const senderName = messages.find((m) => m.senderName)?.senderName ?? null;
|
|
7055
|
+
rows.push({
|
|
7056
|
+
sessionId: "",
|
|
7057
|
+
projectDir: "",
|
|
7058
|
+
title: remoteJid,
|
|
7059
|
+
senderId: senderTelephone,
|
|
7060
|
+
startedAt: messages[0].dateSent,
|
|
7061
|
+
channel: "whatsapp",
|
|
7062
|
+
role: scope === "admin" ? "admin" : "public",
|
|
7063
|
+
operatorName: null,
|
|
7064
|
+
whatsappName: senderName,
|
|
7065
|
+
lastMessageAt: last.dateSent,
|
|
7066
|
+
modelGated: false,
|
|
7067
|
+
model: null,
|
|
7068
|
+
source: "store",
|
|
7069
|
+
accountId,
|
|
7070
|
+
remoteJid,
|
|
7071
|
+
scope
|
|
7072
|
+
});
|
|
7073
|
+
}
|
|
7074
|
+
return rows.sort((a, b) => (b.lastMessageAt ?? "").localeCompare(a.lastMessageAt ?? ""));
|
|
7075
|
+
}
|
|
6953
7076
|
|
|
6954
7077
|
// server/routes/admin/sidebar-sessions.ts
|
|
6955
7078
|
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;
|
|
@@ -7744,7 +7867,7 @@ app4.get("/conversations", requireAdminSession, async (c) => {
|
|
|
7744
7867
|
model: lastAssistantModel(body)
|
|
7745
7868
|
});
|
|
7746
7869
|
}
|
|
7747
|
-
const
|
|
7870
|
+
const sessionRows = selectReaderChannelSessions(rows).filter((r) => r.channel !== "whatsapp");
|
|
7748
7871
|
const account = resolveAccount();
|
|
7749
7872
|
let users = [];
|
|
7750
7873
|
if (account) {
|
|
@@ -7757,13 +7880,11 @@ app4.get("/conversations", requireAdminSession, async (c) => {
|
|
|
7757
7880
|
}
|
|
7758
7881
|
const admins = account?.config.admins ?? [];
|
|
7759
7882
|
const nameBySender = /* @__PURE__ */ new Map();
|
|
7760
|
-
const
|
|
7761
|
-
const distinct = [...new Set(selected.map((r) => r.senderId).filter((s) => !!s))];
|
|
7883
|
+
const distinct = [...new Set(sessionRows.map((r) => r.senderId).filter((s) => !!s))];
|
|
7762
7884
|
await Promise.all(
|
|
7763
7885
|
distinct.map(async (senderId) => {
|
|
7764
7886
|
if (!account) {
|
|
7765
7887
|
nameBySender.set(senderId, null);
|
|
7766
|
-
whatsappNameBySender.set(senderId, null);
|
|
7767
7888
|
return;
|
|
7768
7889
|
}
|
|
7769
7890
|
const idRes = classifyAdminUserId(users, admins, senderId);
|
|
@@ -7771,57 +7892,19 @@ app4.get("/conversations", requireAdminSession, async (c) => {
|
|
|
7771
7892
|
const { name, reason } = resolveOperatorDisplay(idRes, nameRes);
|
|
7772
7893
|
if (reason) console.error(`[wa-reader] op=operator-unresolved senderId=${senderId} reason=${reason}`);
|
|
7773
7894
|
nameBySender.set(senderId, name);
|
|
7774
|
-
if (!name) {
|
|
7775
|
-
const waName = await loadWhatsappSenderName(account.accountId, senderId);
|
|
7776
|
-
if (waName) console.error(`[wa-reader] op=operator-name-fallback senderId=${senderId} source=whatsapp-pushname`);
|
|
7777
|
-
whatsappNameBySender.set(senderId, waName);
|
|
7778
|
-
} else {
|
|
7779
|
-
whatsappNameBySender.set(senderId, null);
|
|
7780
|
-
}
|
|
7781
7895
|
})
|
|
7782
7896
|
);
|
|
7783
|
-
const
|
|
7897
|
+
const sessionConversations = sessionRows.map((r) => ({
|
|
7784
7898
|
...r,
|
|
7785
|
-
operatorName: r.senderId ? nameBySender.get(r.senderId) ?? null : null
|
|
7786
|
-
whatsappName: r.senderId ? whatsappNameBySender.get(r.senderId) ?? null : null,
|
|
7787
|
-
rowType: "session"
|
|
7899
|
+
operatorName: r.senderId ? nameBySender.get(r.senderId) ?? null : null
|
|
7788
7900
|
}));
|
|
7789
|
-
const
|
|
7790
|
-
|
|
7791
|
-
|
|
7792
|
-
|
|
7793
|
-
|
|
7794
|
-
|
|
7795
|
-
|
|
7796
|
-
for (const [remoteJid, messages] of allConvos) {
|
|
7797
|
-
if (messages.length === 0) continue;
|
|
7798
|
-
const isGroup = remoteJid.endsWith("@g.us");
|
|
7799
|
-
const senderTelephone = isGroup ? null : messages[0].senderTelephone;
|
|
7800
|
-
if (!isGroup && senderTelephone && coveredSenderIds.has(senderTelephone)) continue;
|
|
7801
|
-
const last = messages[messages.length - 1];
|
|
7802
|
-
const resolvedName = isGroup ? null : messages.find((m) => m.senderName)?.senderName ?? null;
|
|
7803
|
-
persistedOnlyRows.push({
|
|
7804
|
-
sessionId: `persisted:${account.accountId}:${remoteJid}`,
|
|
7805
|
-
projectDir: "",
|
|
7806
|
-
title: remoteJid,
|
|
7807
|
-
senderId: senderTelephone,
|
|
7808
|
-
startedAt: messages[0].dateSent,
|
|
7809
|
-
channel: "whatsapp",
|
|
7810
|
-
role: "public",
|
|
7811
|
-
operatorName: null,
|
|
7812
|
-
whatsappName: resolvedName,
|
|
7813
|
-
lastMessageAt: last.dateSent,
|
|
7814
|
-
modelGated: false,
|
|
7815
|
-
model: null,
|
|
7816
|
-
rowType: "persisted-only",
|
|
7817
|
-
accountId: account.accountId,
|
|
7818
|
-
remoteJid
|
|
7819
|
-
});
|
|
7820
|
-
}
|
|
7821
|
-
}
|
|
7822
|
-
const allRows = [...conversations, ...persistedOnlyRows];
|
|
7823
|
-
console.log(`[wa-reader] op=full-list accountId=${account?.accountId ?? "null"} sessionRows=${conversations.length} persistedOnlyRows=${persistedOnlyRows.length}`);
|
|
7824
|
-
return c.json({ conversations: allRows });
|
|
7901
|
+
const storeRows = account ? buildStoreConversationRows(account.accountId, readAllConversations(account.accountId)) : [];
|
|
7902
|
+
const adminScope = storeRows.filter((r) => r.scope === "admin").length;
|
|
7903
|
+
const publicScope = storeRows.length - adminScope;
|
|
7904
|
+
console.log(
|
|
7905
|
+
`[wa-reader] op=list accountId=${account?.accountId ?? "null"} conversations=${storeRows.length} adminScope=${adminScope} publicScope=${publicScope}`
|
|
7906
|
+
);
|
|
7907
|
+
return c.json({ conversations: [...sessionConversations, ...storeRows] });
|
|
7825
7908
|
});
|
|
7826
7909
|
function readFrom(path2, from) {
|
|
7827
7910
|
const end = statSync4(path2).size;
|
|
@@ -8161,7 +8244,7 @@ app4.get("/directive", requireAdminSession, (c) => {
|
|
|
8161
8244
|
}
|
|
8162
8245
|
return c.text(body);
|
|
8163
8246
|
});
|
|
8164
|
-
app4.get("/
|
|
8247
|
+
app4.get("/store-stream", requireAdminSession, (c) => {
|
|
8165
8248
|
const accountIdRaw = c.req.query("accountId");
|
|
8166
8249
|
const remoteJid = c.req.query("remoteJid");
|
|
8167
8250
|
if (!accountIdRaw || !remoteJid) {
|
|
@@ -8176,16 +8259,108 @@ app4.get("/persisted-messages", requireAdminSession, async (c) => {
|
|
|
8176
8259
|
if (!isUserJid(remoteJid) && !isGroupJid(remoteJid)) {
|
|
8177
8260
|
return c.json({ error: "invalid remoteJid" }, 400);
|
|
8178
8261
|
}
|
|
8179
|
-
const
|
|
8180
|
-
const
|
|
8262
|
+
const file = conversationFilePath(accountId, remoteJid);
|
|
8263
|
+
const encoder = new TextEncoder();
|
|
8264
|
+
const connId = `${remoteJid.slice(0, 12)}-${process.hrtime.bigint().toString(36).slice(-6)}`;
|
|
8265
|
+
const startedAt = Date.now();
|
|
8266
|
+
const lastEventId = c.req.header("Last-Event-ID");
|
|
8267
|
+
const toTurn = (r) => ({
|
|
8181
8268
|
kind: "whatsapp-persisted",
|
|
8182
|
-
text:
|
|
8183
|
-
ts:
|
|
8184
|
-
fromMe:
|
|
8185
|
-
senderName:
|
|
8186
|
-
})
|
|
8187
|
-
|
|
8188
|
-
|
|
8269
|
+
text: r.body,
|
|
8270
|
+
ts: r.dateSent,
|
|
8271
|
+
fromMe: r.fromMe,
|
|
8272
|
+
senderName: r.senderName
|
|
8273
|
+
});
|
|
8274
|
+
const readable = new ReadableStream({
|
|
8275
|
+
start(controller) {
|
|
8276
|
+
const send = (turn, id) => {
|
|
8277
|
+
try {
|
|
8278
|
+
controller.enqueue(encoder.encode(`id: ${id}
|
|
8279
|
+
data: ${JSON.stringify(turn)}
|
|
8280
|
+
|
|
8281
|
+
`));
|
|
8282
|
+
} catch {
|
|
8283
|
+
}
|
|
8284
|
+
};
|
|
8285
|
+
const fileEnd0 = (() => {
|
|
8286
|
+
try {
|
|
8287
|
+
return statSync4(file).size;
|
|
8288
|
+
} catch {
|
|
8289
|
+
return 0;
|
|
8290
|
+
}
|
|
8291
|
+
})();
|
|
8292
|
+
let offset = resumeOffset(lastEventId, fileEnd0);
|
|
8293
|
+
if (offset === 0) {
|
|
8294
|
+
const records = [];
|
|
8295
|
+
try {
|
|
8296
|
+
const { buf, end } = readFrom(file, 0);
|
|
8297
|
+
offset = end;
|
|
8298
|
+
for (const line of buf.toString("utf8").split("\n")) {
|
|
8299
|
+
if (!line.trim()) continue;
|
|
8300
|
+
try {
|
|
8301
|
+
records.push(JSON.parse(line));
|
|
8302
|
+
} catch {
|
|
8303
|
+
}
|
|
8304
|
+
}
|
|
8305
|
+
} catch {
|
|
8306
|
+
offset = fileEnd0;
|
|
8307
|
+
}
|
|
8308
|
+
records.sort((a, b) => a.dateSent.localeCompare(b.dateSent));
|
|
8309
|
+
const scope = records.length ? records[records.length - 1].scope : "none";
|
|
8310
|
+
for (const m of records) send(toTurn(m), offset);
|
|
8311
|
+
console.log(
|
|
8312
|
+
`[wa-reader] op=open remoteJid=${remoteJid} scope=${scope} messages=${records.length} source=store`
|
|
8313
|
+
);
|
|
8314
|
+
}
|
|
8315
|
+
const drain = () => {
|
|
8316
|
+
try {
|
|
8317
|
+
const { buf, end } = readFrom(file, offset);
|
|
8318
|
+
if (end <= offset) return;
|
|
8319
|
+
const { lines, nextOffset } = splitNewLines(buf, offset);
|
|
8320
|
+
offset = nextOffset;
|
|
8321
|
+
let n = 0;
|
|
8322
|
+
for (const line of lines) {
|
|
8323
|
+
if (!line.trim()) continue;
|
|
8324
|
+
let rec;
|
|
8325
|
+
try {
|
|
8326
|
+
rec = JSON.parse(line);
|
|
8327
|
+
} catch {
|
|
8328
|
+
continue;
|
|
8329
|
+
}
|
|
8330
|
+
send(toTurn(rec), offset);
|
|
8331
|
+
n++;
|
|
8332
|
+
}
|
|
8333
|
+
if (n > 0) console.log(`[wa-reader] op=store-drain conn=${connId} turns=${n}`);
|
|
8334
|
+
} catch {
|
|
8335
|
+
}
|
|
8336
|
+
};
|
|
8337
|
+
let watcher = null;
|
|
8338
|
+
try {
|
|
8339
|
+
watcher = watch(file, drain);
|
|
8340
|
+
} catch {
|
|
8341
|
+
}
|
|
8342
|
+
const poll = setInterval(drain, 1e3);
|
|
8343
|
+
const heartbeat = setInterval(() => {
|
|
8344
|
+
try {
|
|
8345
|
+
controller.enqueue(encoder.encode(": ping\n\n"));
|
|
8346
|
+
} catch {
|
|
8347
|
+
}
|
|
8348
|
+
}, 2e4);
|
|
8349
|
+
c.req.raw.signal.addEventListener("abort", () => {
|
|
8350
|
+
watcher?.close();
|
|
8351
|
+
clearInterval(poll);
|
|
8352
|
+
clearInterval(heartbeat);
|
|
8353
|
+
console.log(`[wa-reader] op=store-close conn=${connId} ranMs=${Date.now() - startedAt}`);
|
|
8354
|
+
try {
|
|
8355
|
+
controller.close();
|
|
8356
|
+
} catch {
|
|
8357
|
+
}
|
|
8358
|
+
});
|
|
8359
|
+
}
|
|
8360
|
+
});
|
|
8361
|
+
return new Response(readable, {
|
|
8362
|
+
headers: { "Content-Type": "text/event-stream", "Cache-Control": "no-cache", Connection: "keep-alive" }
|
|
8363
|
+
});
|
|
8189
8364
|
});
|
|
8190
8365
|
var whatsapp_reader_default = app4;
|
|
8191
8366
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as e}from"./chunk-CAM3fms7.js";import{A as t,C as n,E as r,H as i,K as a,L as o,M as s,N as c,O as l,P as u,R as d,T as f,V as p,_ as m,g as h,j as g,m as ee,n as te,q as _,t as ne,v as re,x as v,y as ie}from"./useSubAccountSwitcher-DAgBUed_.js";async function y(){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 b=e(_(),1),x=i(),S={sm:14,md:16,lg:18},ae={sm:30,md:38,lg:46};function C({variant:e=`primary`,size:t=`md`,icon:n,iconPosition:r=`leading`,loading:i=!1,fullWidth:a=!1,disabled:o=!1,type:s=`button`,onClick:c,"aria-label":l,style:u,className:d,children:f}){let p=[`btn`,`btn--${e}`,t===`md`?``:`btn--${t}`,a?`btn--full`:``,d].filter(Boolean).join(` `),m=S[t],h={...e===`send`?{width:ae[t],height:ae[t]}:{},...u},g=Object.keys(h).length>0;return(0,x.jsxs)(`button`,{type:s,className:p,disabled:i||o,onClick:c,"aria-label":l,style:g?h:void 0,children:[(0,x.jsxs)(`span`,{className:`btn__content`,style:{visibility:i?`hidden`:`visible`},children:[n&&r===`leading`&&(0,x.jsx)(n,{size:m}),f,n&&r===`trailing`&&(0,x.jsx)(n,{size:m})]}),i&&(0,x.jsx)(`span`,{className:`btn__spinner`,children:`✱`})]})}var w=o(`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`}]]),oe=o(`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`}]]),T=o(`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`}]]),se=o(`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`}]]),ce=o(`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`}]]),le=o(`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`}]]),E=o(`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`}]]),ue=o(`plus`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`M12 5v14`,key:`s699le`}]]),de=o(`sliders-horizontal`,[[`path`,{d:`M10 5H3`,key:`1qgfaw`}],[`path`,{d:`M12 19H3`,key:`yhmn1j`}],[`path`,{d:`M14 3v4`,key:`1sua03`}],[`path`,{d:`M16 17v4`,key:`1q0r14`}],[`path`,{d:`M21 12h-9`,key:`1o4lsq`}],[`path`,{d:`M21 19h-5`,key:`1rlt1p`}],[`path`,{d:`M21 5h-7`,key:`1oszz2`}],[`path`,{d:`M8 10v4`,key:`tgpxqk`}],[`path`,{d:`M8 12H3`,key:`a7s4jb`}]]),D=o(`square`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}]]),O=o(`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`}]]),k=`maxy-shell-side-px`;function fe(){if(typeof window>`u`)return 0;let e=document.querySelector(`.platform > .artefact`)?.getBoundingClientRect();return e&&e.width>0?Math.round(e.width):0}function A(e){if(typeof window>`u`)return e;let t=window.innerWidth,n=Math.max(248,t-480-fe());return Math.min(Math.max(e,248),n)}function j(){if(typeof window>`u`)return 264;try{let e=window.localStorage.getItem(k);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 A(t)}catch{}return 264}function M({targetSelector:e=`.platform`}){let t=(0,b.useRef)(null),[n,r]=(0,b.useState)(()=>j()),i=(0,b.useRef)(n);(0,b.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,b.useCallback)(()=>{r(e=>{let t=A(e);return t===e?e:t})},[]);(0,b.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(A(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(k,String(t))}catch{}console.info(`[admin-ui] sidebar-resize px=${t}`)};window.addEventListener(`pointermove`,o),window.addEventListener(`pointerup`,s)},s=()=>{let e=A(264);r(e);try{window.localStorage.removeItem(k)}catch{}console.info(`[admin-ui] sidebar-resize px=${e}`)};return(0,x.jsx)(`div`,{ref:t,className:`side-resize-handle`,role:`separator`,"aria-orientation":`vertical`,"aria-label":`Resize sidebar`,onPointerDown:o,onDoubleClick:s})}var pe=a();function me({anchorRef:e,onClose:t,className:n,role:r,ariaLabel:i,children:a}){let o=(0,b.useRef)(null),[s,c]=(0,b.useState)({position:`fixed`,visibility:`hidden`}),l=(0,b.useCallback)(()=>{let t=e.current,n=o.current;if(!t||!n)return;let r=t.getBoundingClientRect(),i=n.getBoundingClientRect(),a=r.right-i.width;a<4&&(a=4);let s=window.innerHeight-r.bottom<i.height+8&&r.top>i.height+8?r.top-i.height:r.bottom;c({position:`fixed`,left:a,top:s,visibility:`visible`})},[e]);return(0,b.useLayoutEffect)(()=>{if(l(),typeof ResizeObserver>`u`)return;let e=new ResizeObserver(()=>l());return o.current&&e.observe(o.current),()=>e.disconnect()},[l]),(0,b.useEffect)(()=>{let n=e=>{e.key===`Escape`&&t()},r=n=>{let r=n.target;e.current?.contains(r)||o.current?.contains(r)||t()},i=n=>{let r=e.current;r&&n.target instanceof Node&&n.target.contains(r)&&t()},a=()=>t();return document.addEventListener(`keydown`,n),document.addEventListener(`pointerdown`,r),window.addEventListener(`scroll`,i,!0),window.addEventListener(`resize`,a),()=>{document.removeEventListener(`keydown`,n),document.removeEventListener(`pointerdown`,r),window.removeEventListener(`scroll`,i,!0),window.removeEventListener(`resize`,a)}},[e,t]),(0,pe.createPortal)((0,x.jsx)(`div`,{ref:o,className:n,role:r,"aria-label":i,style:s,children:a}),document.body)}function N({action:e,disabled:t,open:n,onToggle:r,onClose:i}){let a=(0,b.useRef)(null);return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`button`,{ref:a,type:`button`,className:`conv-action`,onClick:r,disabled:t,"aria-haspopup":`dialog`,"aria-expanded":n,"aria-label":e.label,title:e.title,children:e.icon}),n&&(0,x.jsx)(me,{anchorRef:a,onClose:i,className:e.panelClassName,role:`dialog`,ariaLabel:e.label,children:e.panel()})]})}function he({actions:e,disabled:t,collapsed:n}){let[r,i]=(0,b.useState)(null),[a,o]=(0,b.useState)(!1),[c,l]=(0,b.useState)(null),u=(0,b.useRef)(null);(0,b.useEffect)(()=>{i(null),o(!1),l(null)},[n]);let d=(0,b.useCallback)(()=>{o(!1),l(null)},[]);return n?(0,x.jsxs)(`div`,{className:`conv-actions`,children:[(0,x.jsx)(`button`,{ref:u,type:`button`,className:`conv-action conv-actions-overflow`,onClick:()=>o(e=>!e),disabled:t,"aria-haspopup":`menu`,"aria-expanded":a,"aria-label":`Session actions`,title:`Session actions`,children:(0,x.jsx)(s,{size:12})}),a&&(0,x.jsx)(me,{anchorRef:u,onClose:d,className:`conv-actions-menu`,role:`menu`,children:e.map(e=>e.panel?(0,x.jsxs)(`div`,{className:`conv-actions-menu-disclosure`,children:[(0,x.jsxs)(`button`,{type:`button`,role:`menuitem`,"aria-haspopup":`dialog`,"aria-expanded":c===e.key,disabled:t,onClick:()=>l(t=>t===e.key?null:e.key),children:[e.icon,(0,x.jsx)(`span`,{children:e.menuLabel})]}),c===e.key&&(0,x.jsx)(`div`,{className:`conv-actions-menu-panel`,children:e.panel()})]},e.key):(0,x.jsxs)(`button`,{type:`button`,role:`menuitem`,className:e.danger?`conv-action-danger`:void 0,"aria-busy":e.busy,disabled:t,onClick:t=>{e.onClick?.(t),d()},children:[e.icon,(0,x.jsx)(`span`,{children:e.menuLabel})]},e.key))})]}):(0,x.jsx)(`div`,{className:`conv-actions`,children:e.map(e=>e.panel?(0,x.jsx)(N,{action:e,disabled:t,open:r===e.key,onToggle:()=>i(t=>t===e.key?null:e.key),onClose:()=>i(null)},e.key):(0,x.jsx)(`button`,{type:`button`,className:e.danger?`conv-action conv-action-danger`:`conv-action`,onClick:e.onClick,disabled:t,"aria-busy":e.busy,"aria-label":e.label,title:e.title,children:e.icon},e.key))})}var P=`claude-opus-4-8[1m]`,F=`claude-sonnet-5`,I=`claude-haiku-4-5`,L={[P]:`Opus 4.8 (1M context)`,[F]:`Sonnet 5`,[I]:`Haiku 4.5`};function ge(e){return L[e]??e}var _e=[P,F,I];function R(e){return e.replace(/\[1m\]$/,``)}function z(e){return _e.find(t=>R(t)===R(e))??e}var ve=[`default`,`acceptEdits`,`plan`,`auto`,`bypassPermissions`],B=[`low`,`medium`,`high`,`xhigh`];[...ve],[...B],[...B];var ye=[P,F,I],be={default:`Ask permissions`,acceptEdits:`Accept edits`,plan:`Plan mode`,auto:`Auto mode`,bypassPermissions:`Bypass permissions`},xe=ve.map(e=>({value:e,label:be[e]??e})),V={low:`Low`,medium:`Medium`,high:`High`,xhigh:`Highest`},H=B.map(e=>({value:e,label:V[e]??e}));function Se(e){if(e){let t=ye.find(t=>R(t)===R(e));if(t)return t}return P}function Ce({row:e,adminFetch:t,onError:n}){let[r,i]=(0,b.useState)(()=>Se(e.model)),[a,o]=(0,b.useState)(``),[s,c]=(0,b.useState)(``),[u,d]=(0,b.useState)(!1),f=(0,b.useRef)(!1);(0,b.useEffect)(()=>{i(Se(e.model))},[e.model]);let p=async()=>{if(!f.current){f.current=!0,d(!0);try{let i=await t(`/api/admin/session-reseat`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({fromSessionId:e.sessionId,model:r,...a?{permissionMode:a}:{},...s?{effort:s}:{}})});if(!i.ok){n(`Could not reset ${e.title} (status ${i.status})`),console.error(`[admin-ui] dashboard-reseat-failed sessionId=${e.sessionId} status=${i.status}`),f.current=!1,d(!1);return}let o=await i.json().catch(()=>({}));o.target?window.location.assign(o.target):(n(`Reset of ${e.title} returned no target`),f.current=!1,d(!1))}catch(t){n(`Could not reset ${e.title} (network error)`),console.error(`[admin-ui] dashboard-reseat-failed sessionId=${e.sessionId} error=${t instanceof Error?t.message:String(t)}`),f.current=!1,d(!1)}}};return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`label`,{className:`reseat-field`,children:[(0,x.jsx)(`span`,{children:`Model`}),(0,x.jsx)(`select`,{"data-kind":`model`,value:r,disabled:u,onChange:e=>i(e.target.value),children:ye.map(e=>(0,x.jsx)(`option`,{value:e,children:ge(e)},e))})]}),(0,x.jsxs)(`label`,{className:`reseat-field`,children:[(0,x.jsx)(`span`,{children:`Mode`}),(0,x.jsxs)(`select`,{"data-kind":`mode`,value:a,disabled:u,onChange:e=>o(e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`Keep current`}),xe.map(e=>(0,x.jsx)(`option`,{value:e.value,children:e.label},e.value))]})]}),(0,x.jsxs)(`label`,{className:`reseat-field`,children:[(0,x.jsx)(`span`,{children:`Effort`}),(0,x.jsxs)(`select`,{"data-kind":`effort`,value:s,disabled:u,onChange:e=>c(e.target.value),children:[(0,x.jsx)(`option`,{value:``,children:`Keep current`}),H.map(e=>(0,x.jsx)(`option`,{value:e.value,children:e.label},e.value))]})]}),(0,x.jsx)(`button`,{type:`button`,className:`reseat-apply`,disabled:u,"aria-busy":u,onClick:()=>void p(),children:u?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(l,{size:12,className:`spin`,"aria-hidden":`true`}),`Resetting…`]}):`Reset`})]})}var we=[`whatsapp`,`telegram`];function U(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 W(e){return e>=1e3?`${(e/1e3).toFixed(1)}k`:String(e)}async function Te(e){if(navigator.clipboard)try{return await navigator.clipboard.writeText(e),!0}catch{}try{let t=document.createElement(`textarea`);t.value=e,t.style.position=`fixed`,t.style.opacity=`0`,document.body.appendChild(t),t.select();let n=document.execCommand(`copy`);return document.body.removeChild(t),n}catch{return!1}}function Ee({target:e,onConfirm:t,onCancel:n}){return e?(0,x.jsx)(`div`,{className:`claude-info-overlay`,onClick:n,children:(0,x.jsxs)(`div`,{className:`claude-info-modal`,onClick:e=>e.stopPropagation(),role:`alertdialog`,"aria-label":`Confirm delete session`,children:[(0,x.jsxs)(`div`,{className:`claude-info-header`,children:[(0,x.jsx)(`span`,{children:`Delete this conversation?`}),(0,x.jsx)(`button`,{className:`claude-info-close`,onClick:n,"aria-label":`Close`,children:`✕`})]}),(0,x.jsxs)(`div`,{className:`claude-info-section`,style:{padding:`12px 14px`,fontSize:`11px`,color:`var(--text-secondary)`},children:[`This permanently removes the transcript. It is not moved to Archive and cannot be recovered.`,e.live&&(0,x.jsx)(`div`,{style:{marginTop:`8px`},children:`This session is running; deleting stops it first.`})]}),(0,x.jsxs)(`div`,{className:`claude-info-section`,style:{display:`flex`,gap:`8px`,padding:`10px 14px`},children:[(0,x.jsx)(C,{variant:`danger`,size:`sm`,style:{flex:1},onClick:t,children:`Delete`}),(0,x.jsx)(C,{variant:`secondary`,size:`sm`,style:{flex:1},onClick:n,children:`Cancel`})]})]})}):null}var G=`auth-refresh-failed`;function De({error:e,onClose:t}){if(!e)return null;let n=e.reason===G,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,x.jsx)(`div`,{className:`claude-info-overlay`,onClick:t,children:(0,x.jsxs)(`div`,{className:`claude-info-modal`,onClick:e=>e.stopPropagation(),role:`alertdialog`,"aria-label":`Session could not be opened`,children:[(0,x.jsxs)(`div`,{className:`claude-info-header`,children:[(0,x.jsx)(`span`,{children:r}),(0,x.jsx)(`button`,{className:`claude-info-close`,onClick:t,"aria-label":`Close`,children:`✕`})]}),(0,x.jsxs)(`div`,{className:`claude-info-section`,style:{padding:`12px 14px`,fontSize:`11px`,color:`var(--text-secondary)`},children:[i,(0,x.jsxs)(`div`,{className:`claude-info-row`,style:{marginTop:`8px`},children:[(0,x.jsx)(`span`,{className:`claude-info-label`,children:`Reason`}),(0,x.jsx)(`span`,{className:`claude-info-value`,children:e.reason})]}),e.sessionId&&(0,x.jsxs)(`div`,{className:`claude-info-row`,children:[(0,x.jsx)(`span`,{className:`claude-info-label`,children:`Session`}),(0,x.jsxs)(`span`,{className:`claude-info-value`,children:[e.sessionId.slice(0,8),`…`]})]})]})]})})}function Oe(e){let{show:t,onClose:n,claudeInfo:r,messages:i,sessionElapsed:a,sessionId:o,cacheKey:s}=e,[c,l]=(0,b.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,ee=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,x.jsx)(`div`,{className:`claude-info-overlay`,onClick:n,children:(0,x.jsxs)(`div`,{className:`claude-info-modal`,onClick:e=>e.stopPropagation(),children:[(0,x.jsxs)(`div`,{className:`claude-info-header`,children:[(0,x.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`claude-info-icon`}),(0,x.jsx)(`span`,{children:`Claude Code`}),(0,x.jsx)(`button`,{className:`claude-info-close`,onClick:n,"aria-label":`Close`,children:`✕`})]}),(0,x.jsxs)(`div`,{className:`claude-info-section`,children:[(0,x.jsxs)(`div`,{className:`claude-info-row`,children:[(0,x.jsx)(`span`,{className:`claude-info-label`,children:`Version`}),(0,x.jsx)(`span`,{className:`claude-info-value`,children:r?r.version:`…`})]}),(0,x.jsxs)(`div`,{className:`claude-info-row`,children:[(0,x.jsx)(`span`,{className:`claude-info-label`,children:`Email`}),(0,x.jsx)(`span`,{className:`claude-info-value`,children:r?.account?.email??`…`})]})]}),(g||m||h>0)&&(0,x.jsxs)(`div`,{className:`claude-info-section`,children:[g&&(0,x.jsxs)(`div`,{className:`claude-info-row`,children:[(0,x.jsx)(`span`,{className:`claude-info-label`,children:`Plan`}),(0,x.jsx)(`span`,{className:`claude-info-value`,style:{textTransform:`capitalize`},children:g})]}),m&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`claude-info-row`,children:[(0,x.jsx)(`span`,{className:`claude-info-label`,children:`Usage`}),(0,x.jsxs)(`span`,{className:`claude-info-value`,children:[Math.round(m.utilization*100),`%`]})]}),(0,x.jsxs)(`div`,{className:`claude-info-row`,children:[(0,x.jsx)(`span`,{className:`claude-info-label`,children:`Resets in`}),(0,x.jsx)(`span`,{className:`claude-info-value`,children:ee(m.resetsAt)})]}),m.isUsingOverage&&(0,x.jsxs)(`div`,{className:`claude-info-row`,children:[(0,x.jsx)(`span`,{className:`claude-info-label`,children:`Overage`}),(0,x.jsx)(`span`,{className:`claude-info-value`,children:`Active`})]})]}),h>0&&(0,x.jsxs)(`div`,{className:`claude-info-row`,children:[(0,x.jsx)(`span`,{className:`claude-info-label`,children:`Session cost`}),(0,x.jsxs)(`span`,{className:`claude-info-value`,children:[`$`,h<.01?h.toFixed(4):h.toFixed(2)]})]})]}),(0,x.jsxs)(`div`,{className:`claude-info-section`,children:[(0,x.jsxs)(`div`,{className:`claude-info-row`,children:[(0,x.jsx)(`span`,{className:`claude-info-label`,children:`Model`}),(0,x.jsx)(`span`,{className:`claude-info-value`,children:r?.model??`…`})]}),(0,x.jsxs)(`div`,{className:`claude-info-row`,children:[(0,x.jsx)(`span`,{className:`claude-info-label`,children:`Context used`}),(0,x.jsx)(`span`,{className:`claude-info-value`,children:f>0?`${f}%`:`—`})]}),(0,x.jsxs)(`div`,{className:`claude-info-row`,children:[(0,x.jsx)(`span`,{className:`claude-info-label`,children:`Tokens`}),(0,x.jsx)(`span`,{className:`claude-info-value`,children:p>0?W(p):`—`})]}),(0,x.jsxs)(`div`,{className:`claude-info-row`,children:[(0,x.jsx)(`span`,{className:`claude-info-label`,children:`Session`}),(0,x.jsx)(`span`,{className:`claude-info-value`,children:U(a)})]}),(o||s)&&(()=>{let e=o??s??``;return(0,x.jsxs)(`div`,{className:`claude-info-row`,children:[(0,x.jsx)(`span`,{className:`claude-info-label`,children:`Session`}),(0,x.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 Te(e)?`copied`:`failed`),setTimeout(()=>l(null),1200)},children:c===`copied`?`copied ✓`:c===`failed`?`copy failed ✕`:`${e.slice(0,8)}…`})]})})()]})]})})}var ke=`https://claude.ai/code`,Ae=200,je=[500,1e3,1500,2e3,2500,3e3,3e3];function Me(e,t,n){if(e&&n.target)return{kind:`navigate`,url:n.target,sameOrigin:!0};let r=n.slug??n.bridgeSessionId??null;if(e&&r)return{kind:`navigate`,url:`${ke}/${r}`,sameOrigin:!1};let i=n.reason||n.error||`status ${t}`;return{kind:`error`,sessionId:n.sessionId??null,reason:i}}function Ne(e){if(!e)return``;let t=Date.parse(e);return Number.isFinite(t)?new Date(t).toLocaleString(void 0,{dateStyle:`medium`,timeStyle:`short`}):``}function Pe(e){let{businessName:i,cacheKey:a,role:o,userName:s,userAvatar:l,onSelectProjects:te,onSelectPeople:_,onSelectTasks:ne,onSelectAgents:ie,onCloseMobileDrawer:y,collapsed:S,selectedWhatsappId:ae,onSelectWhatsappConversation:C,initialWhatsappSurface:k=!1,onSelectData:fe,onCloseData:A,initialDataSurface:j=!1}=e,M=v(a),pe=(0,b.useCallback)(e=>({key:`reseat`,label:`Reset session ${e.title} (model, mode, effort)`,menuLabel:`Reset`,title:`Reset — move this session onto a chosen model, mode, and effort`,icon:(0,x.jsx)(de,{size:12}),panelClassName:`reseat-panel`,panel:()=>(0,x.jsx)(Ce,{row:e,adminFetch:M,onError:e=>H({message:e,failed:!0})})}),[M]),me=d.productName,N=typeof s==`string`?s:s===null?`name unavailable`:i||me,P=(N.trim().charAt(0)||`?`).toUpperCase(),[F,I]=(0,b.useState)(j?`data`:k?`whatsapp`:`sessions`),[L,ge]=(0,b.useState)([]),[_e,R]=(0,b.useState)(!1),[z,ve]=(0,b.useState)(null),[B,ye]=(0,b.useState)(!1),[be,xe]=(0,b.useState)(`file`),[V,H]=(0,b.useState)(null),[Se,U]=(0,b.useState)(null),[W,Te]=(0,b.useState)([]),[G,Oe]=(0,b.useState)(!1),[ke,Pe]=(0,b.useState)(null),[Fe,K]=(0,b.useState)(!1),[q,ze]=(0,b.useState)(!1),[J,Be]=(0,b.useState)(!1),[Ve,He]=(0,b.useState)(null),[Ue,We]=(0,b.useState)(new Set),[Ge,Y]=(0,b.useState)(null),[Ke,qe]=(0,b.useState)(new Set),[Je,Ye]=(0,b.useState)(new Set),[Xe,Ze]=(0,b.useState)(new Set),[Qe,$e]=(0,b.useState)(null),[et,X]=(0,b.useState)(``),[tt,nt]=(0,b.useState)(!1),[Z,rt]=(0,b.useState)(!1),it=(0,b.useRef)(null),at=(0,b.useRef)(0),[ot,st]=(0,b.useState)(0);(0,b.useEffect)(()=>{let e=it.current;if(!e||typeof ResizeObserver>`u`)return;let t=new ResizeObserver(e=>{let t=e[0]?.contentRect.width??0;st(e=>Math.abs(e-t)<1?e:t)});return t.observe(e),()=>t.disconnect()},[F]);let ct=ot>0&&ot<400,[lt,ut]=(0,b.useState)([]),[dt,ft]=(0,b.useState)(!1),[pt,mt]=(0,b.useState)(null),[ht,gt]=(0,b.useState)(`whatsapp`),_t=(0,b.useCallback)(e=>{if(y(),!a){console.error(`[admin-ui] artefact-download-blocked id=${e.id} reason=no-cache-key`),H({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`),H({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}`),ee(a,e.downloadPath,e.downloadRoot??`data`),H({message:`Downloading ${e.name}`,failed:!1})},[a,y]);(0,b.useEffect)(()=>{if(!V)return;let e=setTimeout(()=>H(null),2500);return()=>clearTimeout(e)},[V]);let vt=(0,b.useCallback)(async()=>{if(a){ye(!0),ve(null);try{let e=await M(`/api/admin/sidebar-artefacts`);if(!e.ok)throw Error(`status ${e.status}`);ge((await e.json()).artefacts??[]),R(!0)}catch(e){let t=e instanceof Error?e.message:String(e);ve(`Failed to load artefacts: ${t}`),console.error(`[admin-ui] sidebar-artefacts fetch failed: ${t}`)}finally{ye(!1)}}},[a,M]),Q=(0,b.useCallback)(async()=>{if(!a)return null;let e=++at.current;K(!0),Pe(null);try{let t=await M(`/api/admin/sidebar-sessions`);if(!t.ok)throw Error(`status ${t.status}`);let n=await t.json(),r=n.sessions??[];return e===at.current?(Te(r),He(n.accountId??null),Oe(!0),r):(console.info(`[admin-ui] sidebar-sessions-stale-response-dropped token=${e}`),r)}catch(t){let n=t instanceof Error?t.message:String(t);return e===at.current&&Pe(`Failed to load sessions: ${n}`),console.error(`[admin-ui] sidebar-sessions fetch failed: ${n}`),null}finally{e===at.current&&K(!1)}},[a,M]),yt=(0,b.useCallback)(async()=>{if(a){mt(null);try{let e=await M(`/api/whatsapp-reader/conversations`);if(!e.ok)throw Error(`status ${e.status}`);ut((await e.json()).conversations??[]),ft(!0)}catch(e){let t=e instanceof Error?e.message:String(e);mt(`Couldn't load conversations.`),console.error(`[admin-ui] channel-convos fetch failed: ${t}`)}}},[a,M]);(0,b.useEffect)(()=>{!a||G||Q()},[a,G,Q]),(0,b.useEffect)(()=>{if(!a)return;let e=null;return yt(),e=setInterval(()=>{yt()},Ie),()=>{e!==null&&clearInterval(e)}},[a,yt]),(0,b.useEffect)(()=>{if(!a)return;let e=null;function t(){console.info(`[admin-ui] sidebar-refresh surface=sessions trigger=poll`),Q()}function n(){e===null&&(e=setInterval(t,Le))}function r(){e!==null&&(clearInterval(e),e=null)}function i(){document.hidden?r():(t(),n())}return document.hidden||n(),document.addEventListener(`visibilitychange`,i),()=>{r(),document.removeEventListener(`visibilitychange`,i)}},[a,Q]);let bt=(0,b.useMemo)(()=>{let e=new Map;for(let t of we)e.set(t,[]);for(let t of lt)e.get(t.channel)?.push(t);for(let t of we)console.info(`[admin-ui] sidebar-nav surface=${t} count=${e.get(t).length}`);return e},[lt]),xt={whatsapp:`WhatsApp`,telegram:`Telegram`,webchat:`Webchat`},St=()=>{C(null),I(`artefacts`),console.info(`[admin-ui] sidebar-nav surface=artefacts count=${_e?L.length:0} collapsed=${S}`),vt()},$=1.5,Ct=()=>{console.info(`[admin-ui] sidebar-refresh surface=artefacts`),vt()},wt=()=>{C(null),I(`sessions`),console.info(`[admin-ui] sidebar-nav surface=sessions count=${G?W.length:0} collapsed=${S}`),G||Q()},Tt=()=>{console.info(`[admin-ui] sidebar-refresh surface=sessions trigger=manual`),Q()},Et=()=>{I(`data`),console.info(`[admin-ui] sidebar-nav surface=data collapsed=${S}`),fe(),y()},Dt=e=>{A?.(),I(`whatsapp`),gt(e),console.info(`[admin-ui] sidebar-nav surface=${e} count=${bt.get(e)?.length??0} collapsed=${S}`)},Ot=(0,b.useCallback)(async e=>{if(Ke.has(e.sessionId))return;qe(t=>{let n=new Set(t);return n.add(e.sessionId),n});let t=window.open(``,`_blank`);try{let n=await M(`/api/admin/session-rc-spawn`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sessionId:e.sessionId,name:e.title||e.sessionId,...e.accountId?{targetAccountId:e.accountId}:{}})}),r=await n.json().catch(()=>({})),i=Me(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`?(y(),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}`),U(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}`),U({sessionId:e.sessionId,reason:r})}finally{qe(t=>{let n=new Set(t);return n.delete(e.sessionId),n})}},[M,y,Ke]),kt=(0,b.useCallback)(async e=>{let t=e.slice(0,8);for(let n=1;n<=je.length;n++){await new Promise(e=>setTimeout(e,je[n-1]));let r=await Q();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}`)},[Q]),At=(0,b.useCallback)(async()=>{if(!Z){rt(!0);try{let e=await M(`/api/admin/session-rc-spawn`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({})}),t=await e.json().catch(()=>({})),n=Me(e.ok,e.status,t);console.info(`[admin-ui] sidebar-new-session-spawned status=${e.status} outcome=${n.kind} slug=${t.slug??t.bridgeSessionId??`none`}`),n.kind===`navigate`?n.sameOrigin?window.location.assign(n.url):(window.open(n.url,`_blank`),t.sessionId?kt(t.sessionId):console.error(`[admin-ui] sidebar-new-session-converge-skipped reason=no-session-id`)):(console.error(`[admin-ui] sidebar-new-session-failed status=${e.status} reason=${n.reason}`),U(n))}catch(e){let t=e instanceof Error?e.message:String(e);console.error(`[admin-ui] sidebar-new-session-failed error=${t}`),U({sessionId:null,reason:t})}finally{rt(!1)}}},[M,Z,kt]),jt=(0,b.useCallback)((e,t)=>{e.stopPropagation(),Y(t)},[]),Mt=(0,b.useCallback)(async e=>{if(!Ue.has(e.sessionId)){We(t=>{let n=new Set(t);return n.add(e.sessionId),n});try{let t=await M(`/api/admin/session-delete`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sessionId:e.sessionId})});if(!t.ok){let n=await t.json().catch(()=>({}));console.error(`[admin-ui] sidebar-session-delete-failed sessionId=${e.sessionId} status=${t.status} error=${n.error??`unknown`}`),H({message:`Delete failed: ${n.error??`status ${t.status}`}`,failed:!0});return}let n=await t.json();console.info(`[admin-ui] sidebar-session-delete sessionId=${e.sessionId} live=${e.live} confirmed=true pidKilled=${n.pidKilled??`?`} deleted=${n.deleted??`?`}`),Te(t=>t.filter(t=>t.sessionId!==e.sessionId)),Q()}catch(t){let n=t instanceof Error?t.message:String(t);console.error(`[admin-ui] sidebar-session-delete-failed sessionId=${e.sessionId} error=${n}`),H({message:`Delete failed: ${n}`,failed:!0})}finally{We(t=>{let n=new Set(t);return n.delete(e.sessionId),n})}}},[M,Ue,Q]),Nt=(0,b.useCallback)(async(e,t)=>{if(e.stopPropagation(),!Je.has(t.sessionId)){Ye(e=>{let n=new Set(e);return n.add(t.sessionId),n});try{let e=await M(`/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`}`),H({message:`Stop failed: ${n.error??`status ${e.status}`}`,failed:!0});return}console.info(`[admin-ui] sidebar-session-stop sessionId=${t.sessionId}`),Q()}catch(e){let n=e instanceof Error?e.message:String(e);console.error(`[admin-ui] sidebar-session-stop-failed sessionId=${t.sessionId} error=${n}`),H({message:`Stop failed: ${n}`,failed:!0})}finally{Ye(e=>{let n=new Set(e);return n.delete(t.sessionId),n})}}},[M,Je,Q]),Pt=(0,b.useCallback)(async(e,t,n)=>{if(e.stopPropagation(),!Xe.has(t.sessionId)){Ze(e=>{let n=new Set(e);return n.add(t.sessionId),n});try{let e=await M(`/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`}`),H({message:`${n===`archive`?`Archive`:`Unarchive`} failed: ${i}`,failed:!0});return}console.info(`[admin-ui] sidebar-session-archive sessionId=${t.sessionId} mode=${n}`),Q()}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}`),H({message:`${n===`archive`?`Archive`:`Unarchive`} failed: ${r}`,failed:!0})}finally{Ze(e=>{let n=new Set(e);return n.delete(t.sessionId),n})}}},[M,Xe,Q]),Ft=(0,b.useCallback)(async e=>{let t=et.trim();if(!t){H({message:`Title can’t be empty`,failed:!0});return}if(t.length>Ae){H({message:`Title too long (max ${Ae})`,failed:!0});return}nt(!0);try{let n=await M(`/api/admin/session-rename`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sessionId:e.sessionId,title:t})});if(!n.ok){let t=await n.json().catch(()=>({})),r=t.reason??t.error??`status ${n.status}`;console.error(`[admin-ui] sidebar-session-rename sessionId=${e.sessionId.slice(0,8)} outcome=rejected reason=${r}`),H({message:`Rename failed: ${r}`,failed:!0});return}console.info(`[admin-ui] sidebar-session-rename sessionId=${e.sessionId.slice(0,8)} outcome=ok`),$e(null),X(``),Q()}catch(t){let n=t instanceof Error?t.message:String(t);console.error(`[admin-ui] sidebar-session-rename sessionId=${e.sessionId.slice(0,8)} outcome=rejected reason=${n}`),H({message:`Rename failed: ${n}`,failed:!0})}finally{nt(!1)}},[M,et,Q]);return(0,x.jsxs)(`aside`,{className:`side`,children:[(0,x.jsx)(`div`,{className:`side-new-session-row`,children:(0,x.jsxs)(`button`,{type:`button`,className:`side-new-session`,onClick:At,disabled:Z,"aria-busy":Z,children:[(0,x.jsx)(ue,{size:14}),(0,x.jsx)(`span`,{children:Z?`Spawning…`:`New session`})]})}),(0,x.jsxs)(`nav`,{className:`side-nav`,children:[(0,x.jsxs)(`button`,{type:`button`,className:`nav-row`,onClick:()=>{console.info(`[admin-ui] sidebar-nav surface=people`),_(),y()},children:[(0,x.jsx)(O,{size:20,strokeWidth:$}),(0,x.jsx)(`span`,{className:`label`,children:`People`}),(0,x.jsx)(`span`,{className:`kbd`})]}),(0,x.jsxs)(`button`,{type:`button`,className:`nav-row`,onClick:()=>{console.info(`[admin-ui] sidebar-nav surface=agents`),ie(),y()},children:[(0,x.jsx)(T,{size:20,strokeWidth:$}),(0,x.jsx)(`span`,{className:`label`,children:`Agents`}),(0,x.jsx)(`span`,{className:`kbd`})]}),(0,x.jsxs)(`button`,{type:`button`,className:`nav-row`,onClick:()=>{console.info(`[admin-ui] sidebar-nav surface=projects`),te(),y()},children:[(0,x.jsx)(se,{size:20,strokeWidth:$}),(0,x.jsx)(`span`,{className:`label`,children:p().term}),(0,x.jsx)(`span`,{className:`kbd`})]}),(0,x.jsxs)(`button`,{type:`button`,className:`nav-row`,onClick:()=>{console.info(`[admin-ui] sidebar-nav surface=tasks`),ne(),y()},children:[(0,x.jsx)(le,{size:20,strokeWidth:$}),(0,x.jsx)(`span`,{className:`label`,children:`Tasks`}),(0,x.jsx)(`span`,{className:`kbd`})]}),(0,x.jsxs)(`button`,{type:`button`,className:`nav-row${F===`artefacts`?` active`:``}`,onClick:St,children:[(0,x.jsx)(t,{size:20,strokeWidth:$}),(0,x.jsx)(`span`,{className:`label`,children:`Artefacts`}),(0,x.jsx)(`span`,{className:`kbd`})]}),(0,x.jsxs)(`button`,{type:`button`,className:`nav-row${F===`sessions`?` active`:``}`,onClick:wt,children:[(0,x.jsx)(ce,{size:20,strokeWidth:$}),(0,x.jsx)(`span`,{className:`label`,children:`Sessions`}),(0,x.jsx)(`span`,{className:`kbd`})]}),(0,x.jsxs)(`button`,{type:`button`,className:`nav-row${F===`data`?` active`:``}`,onClick:Et,children:[(0,x.jsx)(u,{size:20,strokeWidth:$}),(0,x.jsx)(`span`,{className:`label`,children:`Data`}),(0,x.jsx)(`span`,{className:`kbd`})]}),dt&&we.filter(e=>bt.get(e).length>0).map(e=>(0,x.jsxs)(`button`,{type:`button`,className:`nav-row${F===`whatsapp`&&ht===e?` active`:``}`,onClick:()=>Dt(e),children:[(0,x.jsx)(m,{channel:e,size:16}),(0,x.jsx)(`span`,{className:`label`,children:xt[e]}),(0,x.jsx)(`span`,{className:`kbd`})]},e)),pt&&(0,x.jsx)(`div`,{className:`nav-row`,style:{color:`var(--text-tertiary)`,cursor:`default`},"aria-disabled":`true`,children:(0,x.jsx)(`span`,{className:`label`,children:pt})})]}),F===`artefacts`&&(0,x.jsxs)(`div`,{className:`side-list`,children:[(0,x.jsxs)(`div`,{className:`group-head`,children:[(0,x.jsx)(`span`,{children:`Artefacts`}),(0,x.jsxs)(`span`,{className:`group-head-meta`,children:[(0,x.jsx)(`button`,{type:`button`,className:`group-head-refresh`,title:`Refresh artefacts`,"aria-label":`Refresh artefacts`,onClick:Ct,disabled:B,children:(0,x.jsx)(f,{size:12,className:B?`spinning`:void 0})}),(0,x.jsx)(`span`,{children:B?`…`:String(L.length)})]})]}),z&&(0,x.jsx)(`div`,{className:`conv`,style:{color:`var(--text-tertiary)`,cursor:`default`},children:z}),_e&&!z&&L.length>0&&(()=>{let e=L.filter(e=>e.kind===`agent-template`).length,t=L.length-e;return(0,x.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,x.jsxs)(`button`,{type:`button`,className:`artefact-filter-chip${be===e.key?` active`:``}`,onClick:()=>xe(e.key),disabled:e.count===0&&e.key!==`all`,children:[e.label,(0,x.jsx)(`span`,{className:`artefact-filter-chip-count`,children:e.count})]},e.key))})})(),_e&&!z&&L.length===0&&(0,x.jsx)(`div`,{className:`conv`,style:{color:`var(--text-tertiary)`,cursor:`default`},children:`No artefacts yet`}),L.filter(e=>be===`all`?!0:be===`agent`?e.kind===`agent-template`:e.kind!==`agent-template`).map(e=>{let n=e.kind===`agent-template`,r=n?T:t,i=Ne(e.updatedAt),a=e.downloadPath!==null;return(0,x.jsxs)(`button`,{type:`button`,className:`conv`,onClick:()=>_t(e),disabled:!a,style:a?void 0:{cursor:`default`},title:a?`Download ${e.name}`:`${e.name} can’t be downloaded`,children:[(0,x.jsx)(r,{size:14,className:`conv-icon`,"data-kind":n?`agent`:`file`,"aria-label":n?`agent template`:`file`}),(0,x.jsxs)(`span`,{className:`conv-stack`,children:[(0,x.jsx)(`span`,{className:`conv-name-line`,children:(0,x.jsx)(`span`,{className:`conv-name`,children:e.name})}),i&&(0,x.jsx)(`span`,{className:`conv-timestamp`,children:i})]}),a&&(0,x.jsx)(c,{size:12,className:`conv-rc-icon`,"aria-hidden":`true`})]},e.id)})]}),F===`sessions`&&(()=>{let e=W.filter(e=>q?!0:!e.isSubagent).filter(e=>J?!0:!e.archived),t=W.some(e=>e.isSubagent),i=W.some(e=>e.archived);return(0,x.jsxs)(`div`,{className:`side-list`,ref:it,children:[(0,x.jsxs)(`div`,{className:`group-head`,children:[(0,x.jsx)(`span`,{children:`Sessions`}),(0,x.jsxs)(`span`,{className:`group-head-meta`,children:[(0,x.jsx)(`button`,{type:`button`,className:`group-head-refresh`,title:`Refresh sessions`,"aria-label":`Refresh sessions`,onClick:Tt,disabled:Fe,children:(0,x.jsx)(f,{size:12,className:Fe?`spinning`:void 0})}),(0,x.jsx)(`span`,{children:Fe?`…`:String(e.length)})]})]}),Ve&&(0,x.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,x.jsx)(`code`,{children:Ve})}),(t||i)&&(0,x.jsxs)(`div`,{className:`artefact-filter-chips`,children:[t&&(0,x.jsx)(`button`,{type:`button`,className:`artefact-filter-chip${q?` active`:``}`,"aria-pressed":q,onClick:()=>ze(e=>!e),title:q?`Hide subagent sessions`:`Show subagent sessions`,children:`Subagents`}),i&&(0,x.jsx)(`button`,{type:`button`,className:`artefact-filter-chip${J?` active`:``}`,"aria-pressed":J,onClick:()=>Be(e=>!e),title:J?`Hide archived sessions`:`Show archived sessions`,children:`Archived`})]}),ke&&(0,x.jsx)(`div`,{className:`conv`,style:{color:`var(--text-tertiary)`,cursor:`default`},children:ke}),G&&!ke&&e.length===0&&(0,x.jsx)(`div`,{className:`conv`,style:{color:`var(--text-tertiary)`,cursor:`default`},children:`No sessions yet`}),e.map(e=>{let t=Ne(e.startedAt),i=Ke.has(e.sessionId),a=Ue.has(e.sessionId),o=Je.has(e.sessionId),s=Xe.has(e.sessionId),c=i||a||o||s,l=[{key:`open`,label:`Resume session ${e.title} in claude.ai/code`,menuLabel:`Resume in claude.ai/code`,title:`Resume in a fresh local Remote Control PTY`,icon:(0,x.jsx)(g,{size:12}),busy:i,onClick:()=>{Ot(e)}},{key:`message`,label:`Open session ${e.title} in admin webchat`,menuLabel:`Open in webchat`,title:`Open in admin webchat (/chat) — sending resumes this session`,icon:(0,x.jsx)(E,{size:12}),onClick:()=>{window.location.assign(`/chat?session=${e.sessionId}`)}},...e.live?[{key:`stop`,label:`Stop session ${e.title}`,menuLabel:`Stop`,title:`Stop session process (keeps the conversation, can resume later)`,icon:(0,x.jsx)(D,{size:12}),busy:o,onClick:t=>{Nt(t,e)}}]:[],e.archived?{key:`unarchive`,label:`Unarchive session ${e.title}`,menuLabel:`Unarchive`,title:`Unarchive (move back to the active list)`,icon:(0,x.jsx)(w,{size:12}),busy:s,onClick:t=>{Pt(t,e,`unarchive`)}}:{key:`archive`,label:`Archive session ${e.title}`,menuLabel:`Archive`,title:`Archive (hide from the list, keeps the conversation resumable)`,icon:(0,x.jsx)(oe,{size:12}),busy:s,onClick:t=>{Pt(t,e,`archive`)}},{key:`rename`,label:`Rename session ${e.title}`,menuLabel:`Rename`,title:`Rename this session`,icon:(0,x.jsx)(r,{size:12}),busy:tt&&Qe===e.sessionId,onClick:t=>{t.stopPropagation(),$e(e.sessionId),X(e.personName??e.title)}},{key:`delete`,label:`Delete session ${e.title}`,menuLabel:`Delete`,title:`Delete session (stops the process, removes the conversation)`,icon:(0,x.jsx)(n,{size:12}),danger:!0,busy:a,onClick:t=>{jt(t,e)}},pe({sessionId:e.sessionId,model:e.model??null,title:e.personName??e.title})];return(0,x.jsxs)(`div`,{className:`conv conv-with-actions`,children:[(0,x.jsxs)(`div`,{className:`conv-main-static`,children:[(0,x.jsx)(`span`,{className:`conv-live-dot`,"data-live":e.live?`1`:`0`,"aria-label":e.live?`live session`:`ended session`}),(0,x.jsxs)(`span`,{className:`conv-stack`,children:[(0,x.jsxs)(`span`,{className:`conv-name-line`,children:[e.channel&&(0,x.jsx)(re,{channel:e.channel,size:13}),Qe===e.sessionId?(0,x.jsx)(`input`,{className:`conv-name conv-name-edit`,autoFocus:!0,value:et,disabled:tt,"aria-label":`New title for session ${e.title}`,onChange:e=>X(e.target.value),onClick:e=>e.stopPropagation(),onKeyDown:t=>{t.key===`Enter`?(t.preventDefault(),Ft(e)):t.key===`Escape`&&(t.preventDefault(),$e(null),X(``))},onBlur:()=>{Qe===e.sessionId&&!tt&&($e(null),X(``))}}):(0,x.jsx)(`span`,{className:`conv-name`,title:e.personName??e.title,children:e.personName??e.title})]}),(0,x.jsxs)(`span`,{className:`conv-timestamp`,children:[(0,x.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,x.jsxs)(`span`,{children:[` · `,t]})]})]})]}),(0,x.jsx)(he,{actions:l,disabled:c,collapsed:ct})]},e.sessionId)})]})})(),F===`whatsapp`&&(0,x.jsxs)(`div`,{className:`side-list`,children:[(0,x.jsxs)(`div`,{className:`group-head`,children:[(0,x.jsx)(`span`,{children:xt[ht]}),(0,x.jsxs)(`span`,{className:`group-head-meta`,children:[(0,x.jsx)(`button`,{type:`button`,className:`group-head-refresh`,title:`Refresh conversations`,"aria-label":`Refresh conversations`,onClick:()=>{yt()},children:(0,x.jsx)(f,{size:12})}),(0,x.jsx)(`span`,{children:String(bt.get(ht).length)})]})]}),bt.get(ht).map(e=>{let t=Ne(e.lastMessageAt);return(0,x.jsxs)(`div`,{className:`conv conv-with-actions${ae===e.sessionId?` active`:``}`,children:[(0,x.jsxs)(`button`,{type:`button`,className:`conv-main-static conv-main-btn`,onClick:()=>{C(e),y()},title:e.title,children:[(0,x.jsx)(m,{channel:e.channel,size:14}),(0,x.jsxs)(`span`,{className:`conv-stack`,children:[(0,x.jsxs)(`span`,{className:`conv-name-line`,children:[(0,x.jsx)(`span`,{className:`conv-name`,children:h(e)}),e.role===`public`&&(0,x.jsx)(`span`,{className:`conv-tag conv-tag-public`,children:`Public`})]}),t&&(0,x.jsx)(`span`,{className:`conv-timestamp`,children:t})]})]}),(0,x.jsx)(he,{actions:[pe({sessionId:e.sessionId,model:e.model,title:e.title})],disabled:!1,collapsed:ct})]},e.sessionId)})]}),(0,x.jsx)(Re,{}),(0,x.jsxs)(`div`,{className:`side-foot`,children:[(0,x.jsx)(`div`,{className:`avatar`,children:l?(0,x.jsx)(`img`,{src:l,alt:N}):P}),(0,x.jsxs)(`div`,{className:`who`,children:[(0,x.jsx)(`span`,{className:`name`,children:N}),(0,x.jsx)(`span`,{className:`role`,children:o??`operator`})]})]}),V&&(0,x.jsx)(`div`,{className:`copy-toast${V.failed?` copy-toast-failed`:``}`,role:`status`,children:V.message}),(0,x.jsx)(De,{error:Se,onClose:()=>U(null)}),(0,x.jsx)(Ee,{target:Ge,onCancel:()=>Y(null),onConfirm:()=>{let e=Ge;Y(null),e&&Mt(e)}})]})}var Fe=5e3,Ie=3e4,Le=3e4;function Re(){let[e,t]=(0,b.useState)(null);if((0,b.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()},Fe))}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,x.jsxs)(`div`,{className:f.join(` `),role:`status`,"aria-label":`host CPU and RAM`,children:[(0,x.jsxs)(`div`,{className:`system-stats__metric`,children:[(0,x.jsxs)(`span`,{className:i?`system-stats__fig system-stats__fig--warn`:`system-stats__fig`,children:[`CPU `,u(n)]}),(0,x.jsx)(`div`,{className:`system-stats__bar`,children:(0,x.jsx)(`div`,{className:`system-stats__bar-fill`,style:d(n)})})]}),(0,x.jsxs)(`div`,{className:`system-stats__metric`,children:[(0,x.jsxs)(`span`,{className:o?`system-stats__fig system-stats__fig--warn`:`system-stats__fig`,children:[`RAM `,u(r)]}),(0,x.jsx)(`div`,{className:`system-stats__bar`,children:(0,x.jsx)(`div`,{className:`system-stats__bar-fill`,style:d(r)})})]})]})}var K=`admin-sidebar-collapsed`,q=`admin-sidebar-drawer-open`;function ze(){if(typeof window>`u`)return!1;try{return window.sessionStorage.getItem(K)===`1`}catch{return!1}}function J(e){if(!(typeof window>`u`))try{e?window.sessionStorage.setItem(K,`1`):window.sessionStorage.removeItem(K)}catch{}}function Be(){if(typeof window>`u`)return!1;try{return window.sessionStorage.getItem(q)===`1`}catch{return!1}}function Ve(e){if(!(typeof window>`u`))try{e?window.sessionStorage.setItem(q,`1`):window.sessionStorage.removeItem(q)}catch{}}var He=720;function Ue(e,t){return e===`/`?{via:`in-place`}:{via:`navigate`,href:`/?wa=${encodeURIComponent(t.sessionId)}&projectDir=${encodeURIComponent(t.projectDir)}`}}function We(e){return e===`/`?{via:`in-place`}:{via:`navigate`,href:`/?data=1`}}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,model:null,rowType:`session`}}function Y(e,t){return e===`/`?new URLSearchParams(t).has(`data`):!1}function Ke(e,t){return t===`operator`&&e===`chat`||e===`dashboard`?`/`:e===`data`?`/data`:e===`graph`?`/graph`:e===`calendar`?`/calendar`:e===`chat`?`/chat`:`/browser`}function qe(e){let{cacheKey:t,businessName:n,variant:r=`admin`,onLogout:i,onDisconnect:a,disconnecting:o,userName:s,userAvatar:c,role:l,onOpenConversations:u,children:d,footer:f}=e,{subAccounts:m,activeAccountId:h,switching:g,switchAccount:ee}=ne(t),[_,re]=(0,b.useState)(()=>ze()),[v,y]=(0,b.useState)(()=>Be()),[S,ae]=(0,b.useState)(()=>typeof window<`u`&&window.matchMedia(`(max-width: ${He}px)`).matches),[C,w]=(0,b.useState)(()=>typeof window>`u`||Y(window.location.pathname,window.location.search)?null:Ge(window.location.pathname,window.location.search)),[oe]=(0,b.useState)(()=>C!==null),[T,se]=(0,b.useState)(()=>typeof window>`u`?!1:Y(window.location.pathname,window.location.search)),[ce]=(0,b.useState)(()=>T);(0,b.useEffect)(()=>{if(typeof window>`u`)return;let e=window.matchMedia(`(max-width: ${He}px)`),t=e=>ae(e.matches);return e.addEventListener(`change`,t),()=>e.removeEventListener(`change`,t)},[]);let le=(0,b.useCallback)(e=>{J(e),re(e)},[]),E=(0,b.useCallback)(e=>{Ve(e),y(e)},[]);(0,b.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=${_} drawer=${v}`)},[]),(0,b.useEffect)(()=>{typeof window>`u`||!C||(console.info(`[admin-ui] wa-hydrate route=/ sessionId=${C.sessionId.slice(0,8)}`),window.history.replaceState(null,``,`/`))},[]),(0,b.useEffect)(()=>{typeof window>`u`||!T||(console.info(`[admin-ui] data-hydrate route=/`),window.history.replaceState(null,``,`/`))},[]);let ue=(0,b.useCallback)(e=>{if(se(!1),e===null){w(null);return}let t=typeof window<`u`?window.location.pathname:`/`,n=Ue(t,e);console.info(`[admin-ui] wa-open route=${t} via=${n.via} sessionId=${e.sessionId.slice(0,8)}`),n.via===`in-place`?w(e):window.location.href=n.href},[]),de=(0,b.useCallback)(()=>{let e=typeof window<`u`?window.location.pathname:`/`,t=We(e);if(console.info(`[admin-ui] data-open route=${e} via=${t.via}`),t.via===`navigate`){window.location.href=t.href;return}w(null),se(!0)},[]),D=S?v:!_,O=(0,b.useCallback)(()=>{if(!(typeof window>`u`))if(window.matchMedia(`(max-width: ${He}px)`).matches){let e=v;console.info(`[admin-ui] header-sidebar-toggle from=${e?`open`:`closed`} mode=drawer`),E(!e)}else{let e=_;console.info(`[admin-ui] header-sidebar-toggle from=${e?`closed`:`open`} mode=collapse`),le(!e)}},[_,v,le,E]),k=(0,b.useCallback)(e=>{let t=Ke(e,r);console.info(`[admin-ui] header-menu-nav target=${e} dest=${t}`),window.location.href=t},[r]),[fe,A]=(0,b.useState)(`chat`),[j,pe]=(0,b.useState)([]);(0,b.useEffect)(()=>{if(r!==`operator`||!t)return;let e=!1;return fetch(`/api/whatsapp-reader/conversations?session_key=${encodeURIComponent(t)}&includePersistedOnly=1`).then(e=>e.ok?e.json():{conversations:[]}).then(t=>{e||pe(t.conversations??[])}).catch(()=>{}),()=>{e=!0}},[r,t]);let me=(0,b.useMemo)(()=>[...new Set(j.map(e=>e.channel))],[j]),N={collapsed:_,mobileDrawerOpen:v,sidebarOpen:D,onToggleSidebar:O,setMobileDrawerOpen:E,selectedWhatsapp:C,onClearWhatsapp:()=>w(null),dataOpen:T};return r===`operator`?(0,x.jsxs)(`div`,{className:`admin-shell admin-page admin-shell-root`,children:[(0,x.jsx)(ie,{businessName:n,variant:r,onNavigate:k,conversationsCount:j.length,conversationsChannels:me,onOpenConversations:()=>A(`conversations`),onToggleSidebar:O,sidebarOpen:D,onLogout:i,onDisconnect:a,disconnecting:o,cacheKey:t,subAccounts:m,activeAccountId:h,switchingAccount:g,onSwitchAccount:ee}),(0,x.jsx)(`div`,{className:`platform platform-operator`,children:fe===`conversations`?(0,x.jsx)(te,{conversations:j,sessionKey:t??``,onBack:()=>A(`chat`)}):typeof d==`function`?d(N):d}),f]}):(0,x.jsxs)(`div`,{className:`admin-shell admin-page admin-shell-root`,children:[(0,x.jsx)(ie,{businessName:n,variant:r,onNavigate:k,onOpenConversations:u,onToggleSidebar:O,sidebarOpen:D,onLogout:i,onDisconnect:a,disconnecting:o,cacheKey:t,subAccounts:m,activeAccountId:h,switchingAccount:g,onSwitchAccount:ee}),(0,x.jsxs)(`div`,{className:`platform${v?` menu-open`:``}${_?` sidebar-collapsed`:``}`,"data-artefact":`closed`,children:[(0,x.jsx)(Pe,{businessName:n,cacheKey:t,role:l??null,userName:s,userAvatar:c??null,onSelectProjects:()=>{window.location.href=`/graph?label=${p().label}`},onSelectPeople:()=>{window.location.href=`/graph?label=Person`},onSelectTasks:()=>{window.location.href=`/graph?label=Task`},onSelectAgents:()=>{window.location.href=`/graph?label=Agent`},onCloseMobileDrawer:()=>E(!1),collapsed:_,mobileDrawerOpen:v,selectedWhatsappId:C?.sessionId??null,onSelectWhatsappConversation:ue,initialWhatsappSurface:oe,onSelectData:de,onCloseData:()=>se(!1),initialDataSurface:ce}),!S&&(0,x.jsx)(M,{}),typeof d==`function`?d(N):d]}),v&&(0,x.jsx)(`div`,{className:`sidebar-backdrop menu-open`,"aria-hidden":`true`,onClick:()=>E(!1)}),f]})}export{w as _,I as a,z as c,D as d,de as f,oe as g,T as h,Te as i,ge as l,le as m,Me as n,P as o,ue as p,Oe as r,F as s,qe as t,O as u,C as v,y};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as e}from"./chunk-CAM3fms7.js";import{G as t,H as n,b as r,o as i,q as a}from"./useSubAccountSwitcher-DAgBUed_.js";import{n as o,t as s}from"./AdminLoginScreens-B9u1V35g.js";import"./admin-types-DJoj6VJv.js";import{r as c,t as l}from"./AdminShell-C2UXTLSB.js";import"./Checkbox-B2g2SCpw.js";import{n as u}from"./page-DBkTNfei.js";import"./graph-labels-DFdBydWC.js";var d=t(),f=e(a(),1),p=n();function m({onOpen:e}){return(0,p.jsx)(`footer`,{className:`admin-footer`,children:(0,p.jsxs)(`div`,{className:`powered-by`,role:`button`,tabIndex:0,onClick:e,onKeyDown:t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),e())},"aria-label":`Powered by Claude Code — show details`,children:[(0,p.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`powered-by-icon`}),(0,p.jsx)(`span`,{children:`Powered by Claude Code`})]})})}function h(){let e=o(),[t,n]=(0,f.useState)(!1);(0,f.useEffect)(()=>{if(!t)return;let e=e=>{e.key===`Escape`&&n(!1)};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[t]);let a=(0,f.useCallback)(async()=>{let t=e.claudeInfo!=null;if(n(!0),t){console.info(`[admin-ui] claude-info-open cached=true ms=0`);return}let r=Date.now();try{let t=await fetch(`/api/admin/claude-info`);if(t.ok){let n=await t.json();e.setClaudeInfo(n)}console.info(`[admin-ui] claude-info-open cached=false ms=${Date.now()-r}`)}catch(e){console.error(`[admin-ui] claude-info-fetch-failed ms=${Date.now()-r} error="${e instanceof Error?e.message:String(e)}"`)}},[e]),d=(0,f.useCallback)(({code:t,path:n})=>{console.warn(`[admin-auth] outcome=chat-tab-logout-on-401 code=${t} path=${n}`),e.handleLogout()},[e]);return e.appState===`chat`?(0,p.jsx)(r,{cacheKey:e.cacheKey,onSessionExpired:d,surface:`chat`,children:(0,p.jsx)(l,{cacheKey:e.cacheKey,businessName:e.businessName,sessionId:e.sessionId,onLogout:e.handleLogout,onDisconnect:e.handleDisconnect,disconnecting:e.disconnecting,userName:e.userName,userAvatar:e.userAvatar,role:e.role,footer:(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(m,{onOpen:a}),(0,p.jsx)(c,{show:t,onClose:()=>n(!1),claudeInfo:e.claudeInfo,messages:[],sessionElapsed:0,sessionId:e.sessionId,cacheKey:e.cacheKey})]}),children:t=>(0,p.jsx)(p.Fragment,{children:t.dataOpen&&e.cacheKey?(0,p.jsx)(u,{cacheKey:e.cacheKey}):t.selectedWhatsapp&&e.cacheKey?(0,p.jsx)(i,{sessionId:t.selectedWhatsapp.sessionId,projectDir:t.selectedWhatsapp.projectDir,sessionKey:e.cacheKey,cleanViewToggle:!0},t.selectedWhatsapp.sessionId):(0,p.jsx)(`main`,{})})})}):(0,p.jsx)(s,{auth:e})}(0,d.createRoot)(document.getElementById(`root`)).render((0,p.jsx)(h,{}));
|