@rubytech/create-maxy-code 0.1.441 → 0.1.442
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +99 -1
- package/package.json +1 -1
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +37 -2
- package/payload/platform/plugins/docs/references/admin-ui.md +1 -1
- package/payload/platform/plugins/docs/references/troubleshooting.md +35 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/device-flow.test.js +37 -4
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/device-flow.test.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/auth/device-flow.d.ts +27 -3
- package/payload/platform/plugins/outlook/mcp/dist/auth/device-flow.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/auth/device-flow.js +52 -11
- package/payload/platform/plugins/outlook/mcp/dist/auth/device-flow.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/index.js +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.d.ts +5 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.js +32 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.js.map +1 -1
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js +20 -22
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +3 -1
- package/payload/platform/scripts/logs-read.sh +24 -6
- package/payload/platform/scripts/logs-read.test.sh +42 -0
- package/payload/platform/scripts/rss-sampler.sh +107 -0
- package/payload/server/public/assets/{AdminLoginScreens-CukwQufW.js → AdminLoginScreens-BJVwtpLH.js} +1 -1
- package/payload/server/public/assets/{AdminShell-BwEBH6tT.js → AdminShell-CMu8_Xwn.js} +1 -1
- package/payload/server/public/assets/{Checkbox-B629mOPp.js → Checkbox-CzD0ORqA.js} +1 -1
- package/payload/server/public/assets/{admin-CdFRCUUZ.js → admin-D0yk2LMq.js} +1 -1
- package/payload/server/public/assets/{browser-BWR59IkB.js → browser-CvfbgznO.js} +1 -1
- package/payload/server/public/assets/{calendar-kuTcxX1t.js → calendar-fw4WethJ.js} +1 -1
- package/payload/server/public/assets/chat-DhD-NES_.js +1 -0
- package/payload/server/public/assets/chevron-left-B3xSeEDR.js +1 -0
- package/payload/server/public/assets/data-CUnDzDox.js +1 -0
- package/payload/server/public/assets/{file-download-4mKJxUi-.js → file-download-Px4s0Bhp.js} +1 -1
- package/payload/server/public/assets/{graph-CboWM2_-.js → graph-DbT8nA6R.js} +1 -1
- package/payload/server/public/assets/{graph-labels-B8YAdo3Z.js → graph-labels-C1YIyLiA.js} +1 -1
- package/payload/server/public/assets/{maximize-2-CxstTgoK.js → maximize-2-BwphzI9S.js} +1 -1
- package/payload/server/public/assets/{operator-oSaB1mya.js → operator-zcIfeB14.js} +1 -1
- package/payload/server/public/assets/{page-DMeJHVfA.js → page-6fCnIb45.js} +2 -2
- package/payload/server/public/assets/page-CfQFAJia.js +1 -0
- package/payload/server/public/assets/{public-C54tl6V4.js → public-C0ehZCdE.js} +1 -1
- package/payload/server/public/assets/{rotate-ccw-COGQTi7n.js → rotate-ccw-C7BqkMec.js} +1 -1
- package/payload/server/public/assets/{tasks-B97VpwEJ.js → tasks-DlgiCafL.js} +1 -1
- package/payload/server/public/assets/{time-entry-format-C09rDHo9.js → time-entry-format-CyNYVDkq.js} +1 -1
- package/payload/server/public/assets/{useCopyFeedback-DHoYHiK9.js → useCopyFeedback-ByGUMN94.js} +1 -1
- package/payload/server/public/assets/useSubAccountSwitcher-1izQvPiD.css +1 -0
- package/payload/server/public/assets/useVoiceRecorder-XgpWvXpk.js +2 -0
- package/payload/server/public/browser.html +5 -5
- package/payload/server/public/calendar.html +6 -6
- package/payload/server/public/chat.html +12 -12
- package/payload/server/public/data.html +10 -10
- package/payload/server/public/graph.html +11 -11
- package/payload/server/public/index.html +13 -13
- package/payload/server/public/operator.html +14 -14
- package/payload/server/public/public.html +12 -12
- package/payload/server/public/tasks.html +5 -5
- package/payload/server/server.js +431 -182
- package/payload/server/public/assets/chat-ejnq2rck.js +0 -1
- package/payload/server/public/assets/chevron-left-u4tjq7fI.js +0 -1
- package/payload/server/public/assets/data-dZbOyLdT.js +0 -1
- package/payload/server/public/assets/page-DEkI-Gl1.js +0 -1
- package/payload/server/public/assets/useSubAccountSwitcher-Dzmd7Aip.css +0 -1
- package/payload/server/public/assets/useVoiceRecorder-b7HzTFs0.js +0 -2
- /package/payload/server/public/assets/{useSubAccountSwitcher-DLJFISqf.js → useSubAccountSwitcher-s6WlRn52.js} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -1413,7 +1413,7 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
1413
1413
|
};
|
|
1414
1414
|
|
|
1415
1415
|
// server/index.ts
|
|
1416
|
-
import { readFileSync as
|
|
1416
|
+
import { readFileSync as readFileSync36, existsSync as existsSync35, watchFile } from "fs";
|
|
1417
1417
|
import { spawn as spawn3 } from "child_process";
|
|
1418
1418
|
import { createHash as createHash7 } from "crypto";
|
|
1419
1419
|
import { resolve as resolve33, join as join36, basename as basename12 } from "path";
|
|
@@ -1793,7 +1793,7 @@ async function ensureAuth() {
|
|
|
1793
1793
|
}
|
|
1794
1794
|
|
|
1795
1795
|
// server/routes/health.ts
|
|
1796
|
-
import { existsSync as existsSync5, readFileSync as
|
|
1796
|
+
import { existsSync as existsSync5, readFileSync as readFileSync10 } from "fs";
|
|
1797
1797
|
import { createConnection as createConnection2 } from "net";
|
|
1798
1798
|
|
|
1799
1799
|
// app/lib/network.ts
|
|
@@ -3843,7 +3843,7 @@ import {
|
|
|
3843
3843
|
// app/lib/attachments.ts
|
|
3844
3844
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
3845
3845
|
import { mkdir, writeFile } from "fs/promises";
|
|
3846
|
-
import { realpathSync as realpathSync2, existsSync as existsSync4 } from "fs";
|
|
3846
|
+
import { realpathSync as realpathSync2, existsSync as existsSync4, readFileSync as readFileSync8, readdirSync as readdirSync3 } from "fs";
|
|
3847
3847
|
import { resolve as resolve6, extname } from "path";
|
|
3848
3848
|
|
|
3849
3849
|
// app/lib/data-path.ts
|
|
@@ -3926,11 +3926,15 @@ function resolveScratchpadPath(raw, scratchpadRootAbs) {
|
|
|
3926
3926
|
import { unzipSync, strFromU8 } from "fflate";
|
|
3927
3927
|
var DOCX = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
|
3928
3928
|
var ODT = "application/vnd.oasis.opendocument.text";
|
|
3929
|
+
var XLSX = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
|
3930
|
+
var ODS = "application/vnd.oasis.opendocument.spreadsheet";
|
|
3929
3931
|
var CONVERTIBLE_DOC_MIME = /* @__PURE__ */ new Set([
|
|
3930
3932
|
DOCX,
|
|
3931
3933
|
ODT,
|
|
3932
3934
|
"text/rtf",
|
|
3933
|
-
"application/rtf"
|
|
3935
|
+
"application/rtf",
|
|
3936
|
+
XLSX,
|
|
3937
|
+
ODS
|
|
3934
3938
|
]);
|
|
3935
3939
|
function bareMime(mimeType) {
|
|
3936
3940
|
return mimeType.split(";")[0].trim().toLowerCase();
|
|
@@ -3964,6 +3968,80 @@ function odtToText(buffer) {
|
|
|
3964
3968
|
const stripped = withBreaks.replace(/<[^>]+>/g, "");
|
|
3965
3969
|
return unescapeXml(stripped).replace(/\n{3,}/g, "\n\n").trim();
|
|
3966
3970
|
}
|
|
3971
|
+
function sheetOrdinal(name) {
|
|
3972
|
+
const m = name.match(/sheet(\d+)\.xml$/);
|
|
3973
|
+
return m ? parseInt(m[1], 10) : 0;
|
|
3974
|
+
}
|
|
3975
|
+
function xlsxToText(buffer) {
|
|
3976
|
+
const files = unzipSync(new Uint8Array(buffer));
|
|
3977
|
+
const shared = [];
|
|
3978
|
+
const sharedBytes = files["xl/sharedStrings.xml"];
|
|
3979
|
+
if (sharedBytes) {
|
|
3980
|
+
for (const si of strFromU8(sharedBytes).split("</si>")) {
|
|
3981
|
+
if (!si.includes("<si")) continue;
|
|
3982
|
+
const base = si.replace(/<rPh\b[\s\S]*?<\/rPh>/g, "");
|
|
3983
|
+
let s = "";
|
|
3984
|
+
for (const m of base.matchAll(/<t\b[^>]*>([\s\S]*?)<\/t>/g)) s += m[1];
|
|
3985
|
+
shared.push(unescapeXml(s));
|
|
3986
|
+
}
|
|
3987
|
+
}
|
|
3988
|
+
const sheetKeys = Object.keys(files).filter((n) => /^xl\/worksheets\/sheet\d+\.xml$/.test(n)).sort((a, b) => sheetOrdinal(a) - sheetOrdinal(b));
|
|
3989
|
+
const sheets = [];
|
|
3990
|
+
for (const key of sheetKeys) {
|
|
3991
|
+
const xml = strFromU8(files[key]);
|
|
3992
|
+
const rows = [];
|
|
3993
|
+
for (const rowXml of xml.split("</row>")) {
|
|
3994
|
+
if (!rowXml.includes("<row")) continue;
|
|
3995
|
+
const cells = [];
|
|
3996
|
+
for (const c of rowXml.matchAll(/<c\b([^>]*)>([\s\S]*?)<\/c>/g)) {
|
|
3997
|
+
const attrs = c[1];
|
|
3998
|
+
const body = c[2];
|
|
3999
|
+
if (/\bt="inlineStr"/.test(attrs)) {
|
|
4000
|
+
let s = "";
|
|
4001
|
+
for (const m of body.matchAll(/<t\b[^>]*>([\s\S]*?)<\/t>/g)) s += m[1];
|
|
4002
|
+
cells.push(unescapeXml(s));
|
|
4003
|
+
continue;
|
|
4004
|
+
}
|
|
4005
|
+
const v = body.match(/<v\b[^>]*>([\s\S]*?)<\/v>/);
|
|
4006
|
+
if (!v) {
|
|
4007
|
+
cells.push("");
|
|
4008
|
+
continue;
|
|
4009
|
+
}
|
|
4010
|
+
if (/\bt="s"/.test(attrs)) {
|
|
4011
|
+
const idx = parseInt(v[1], 10);
|
|
4012
|
+
cells.push(Number.isInteger(idx) && idx >= 0 && idx < shared.length ? shared[idx] : "");
|
|
4013
|
+
} else {
|
|
4014
|
+
cells.push(unescapeXml(v[1]));
|
|
4015
|
+
}
|
|
4016
|
+
}
|
|
4017
|
+
while (cells.length && cells[cells.length - 1] === "") cells.pop();
|
|
4018
|
+
if (cells.length) rows.push(cells.join(" "));
|
|
4019
|
+
}
|
|
4020
|
+
if (rows.length) sheets.push(rows.join("\n"));
|
|
4021
|
+
}
|
|
4022
|
+
return sheets.join("\n\n");
|
|
4023
|
+
}
|
|
4024
|
+
function odsToText(buffer) {
|
|
4025
|
+
const xml = unzipEntry(buffer, "content.xml");
|
|
4026
|
+
const tables = [];
|
|
4027
|
+
for (const tableXml of xml.split(/<table:table(?=[\s>])/).slice(1)) {
|
|
4028
|
+
const rows = [];
|
|
4029
|
+
for (const rowXml of tableXml.split(/<table:table-row\b/).slice(1)) {
|
|
4030
|
+
const cells = rowXml.split(/<table:(?:covered-)?table-cell\b/).slice(1).map((frag) => {
|
|
4031
|
+
const withBreaks = frag.replace(/<text:line-break\b[^>]*\/?>/g, "\n").replace(/<text:tab\b[^>]*\/?>/g, " ");
|
|
4032
|
+
let s = "";
|
|
4033
|
+
for (const m of withBreaks.matchAll(/<text:p\b[^>]*>([\s\S]*?)<\/text:p>/g)) {
|
|
4034
|
+
s += (s ? "\n" : "") + m[1].replace(/<[^>]+>/g, "");
|
|
4035
|
+
}
|
|
4036
|
+
return unescapeXml(s);
|
|
4037
|
+
});
|
|
4038
|
+
while (cells.length && cells[cells.length - 1] === "") cells.pop();
|
|
4039
|
+
if (cells.length) rows.push(cells.join(" "));
|
|
4040
|
+
}
|
|
4041
|
+
if (rows.length) tables.push(rows.join("\n"));
|
|
4042
|
+
}
|
|
4043
|
+
return tables.join("\n\n");
|
|
4044
|
+
}
|
|
3967
4045
|
var RTF_DROP_DEST = /^\\(?:\*|fonttbl|colortbl|stylesheet|listtable|info|pict)\b/;
|
|
3968
4046
|
function stripRtfDestinations(s) {
|
|
3969
4047
|
let out = "";
|
|
@@ -4004,6 +4082,8 @@ function docToText(buffer, mimeType) {
|
|
|
4004
4082
|
const mime = bareMime(mimeType);
|
|
4005
4083
|
if (mime === DOCX) return docxToText(buffer);
|
|
4006
4084
|
if (mime === ODT) return odtToText(buffer);
|
|
4085
|
+
if (mime === XLSX) return xlsxToText(buffer);
|
|
4086
|
+
if (mime === ODS) return odsToText(buffer);
|
|
4007
4087
|
if (mime === "text/rtf" || mime === "application/rtf") return rtfToText(buffer.toString("latin1"));
|
|
4008
4088
|
return null;
|
|
4009
4089
|
}
|
|
@@ -4033,6 +4113,21 @@ var SUPPORTED_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
|
4033
4113
|
"application/vnd.oasis.opendocument.text",
|
|
4034
4114
|
"text/rtf",
|
|
4035
4115
|
"application/rtf",
|
|
4116
|
+
// Task 1607 — spreadsheets + presentations operators send. These land
|
|
4117
|
+
// download-only in the reader; the Read tool cannot parse the binary
|
|
4118
|
+
// containers and agent-readable text extraction for them is task 1608.
|
|
4119
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
4120
|
+
// xlsx
|
|
4121
|
+
"application/vnd.ms-excel",
|
|
4122
|
+
// xls
|
|
4123
|
+
"application/vnd.oasis.opendocument.spreadsheet",
|
|
4124
|
+
// ods
|
|
4125
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
4126
|
+
// pptx
|
|
4127
|
+
"application/vnd.ms-powerpoint",
|
|
4128
|
+
// ppt
|
|
4129
|
+
"application/vnd.oasis.opendocument.presentation",
|
|
4130
|
+
// odp
|
|
4036
4131
|
// Task 1240 — voice recordings persist as playable clips in the admin bubble.
|
|
4037
4132
|
// These match AUDIO_MIME_TYPES in app/lib/stt/audio-mime.ts exactly.
|
|
4038
4133
|
"audio/ogg",
|
|
@@ -4049,6 +4144,7 @@ var MAX_FILES_PER_MESSAGE = 5;
|
|
|
4049
4144
|
var MAX_DATA_UPLOAD_BYTES = 2 * 1024 * 1024 * 1024;
|
|
4050
4145
|
var MAX_ZIP_UNCOMPRESSED_BYTES = 100 * 1024 * 1024;
|
|
4051
4146
|
var EXTRACTED_TEXT_SUFFIX = ".extracted.txt";
|
|
4147
|
+
var ATTACHMENT_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
4052
4148
|
function assertSupportedMime(mimeType) {
|
|
4053
4149
|
const bare = mimeType.split(";")[0].trim().toLowerCase();
|
|
4054
4150
|
if (!SUPPORTED_MIME_TYPES.has(bare)) {
|
|
@@ -4057,22 +4153,47 @@ function assertSupportedMime(mimeType) {
|
|
|
4057
4153
|
);
|
|
4058
4154
|
}
|
|
4059
4155
|
}
|
|
4060
|
-
function
|
|
4061
|
-
|
|
4156
|
+
function isInlineSafeMime(mimeType) {
|
|
4157
|
+
const bare = mimeType.split(";")[0].trim().toLowerCase();
|
|
4158
|
+
if (bare === "image/svg+xml") return false;
|
|
4159
|
+
return bare.startsWith("image/") || bare === "application/pdf" || bare.startsWith("audio/") || bare === "video/mp4";
|
|
4062
4160
|
}
|
|
4063
4161
|
async function storeMediaBuffer(accountId, attachmentId, filename, mimeType, buffer) {
|
|
4064
|
-
assertSupportedMime(mimeType);
|
|
4065
4162
|
if (buffer.byteLength > MAX_FILE_SIZE_BYTES) {
|
|
4066
4163
|
throw new Error(
|
|
4067
4164
|
`Media exceeds the 50 MB limit (${(buffer.byteLength / 1024 / 1024).toFixed(1)} MB).`
|
|
4068
4165
|
);
|
|
4069
4166
|
}
|
|
4070
|
-
return writeAttachment(accountId, "", filename, mimeType, buffer.byteLength, buffer, attachmentId
|
|
4167
|
+
return writeAttachment(accountId, "", filename, mimeType, buffer.byteLength, buffer, attachmentId);
|
|
4071
4168
|
}
|
|
4072
4169
|
function attachmentExists(accountId, attachmentId) {
|
|
4073
4170
|
return existsSync4(resolve6(uploadsDirFor(accountId, "", attachmentId), `${attachmentId}.meta.json`));
|
|
4074
4171
|
}
|
|
4075
|
-
|
|
4172
|
+
function resolveStoredAttachment(accountId, attachmentId) {
|
|
4173
|
+
if (!ATTACHMENT_ID_RE.test(attachmentId)) return null;
|
|
4174
|
+
const dir = uploadsDirFor(accountId, "", attachmentId);
|
|
4175
|
+
let meta;
|
|
4176
|
+
try {
|
|
4177
|
+
meta = JSON.parse(readFileSync8(resolve6(dir, `${attachmentId}.meta.json`), "utf8"));
|
|
4178
|
+
} catch {
|
|
4179
|
+
return null;
|
|
4180
|
+
}
|
|
4181
|
+
if (!meta || typeof meta !== "object") return null;
|
|
4182
|
+
const { filename, mimeType } = meta;
|
|
4183
|
+
if (typeof filename !== "string" || typeof mimeType !== "string") return null;
|
|
4184
|
+
let entries;
|
|
4185
|
+
try {
|
|
4186
|
+
entries = readdirSync3(dir, { withFileTypes: true });
|
|
4187
|
+
} catch {
|
|
4188
|
+
return null;
|
|
4189
|
+
}
|
|
4190
|
+
const dataFile = entries.find((e) => e.isFile() && !e.name.endsWith(".meta.json") && !e.name.endsWith(EXTRACTED_TEXT_SUFFIX));
|
|
4191
|
+
if (!dataFile) return null;
|
|
4192
|
+
const readableSibling = `${attachmentId}${EXTRACTED_TEXT_SUFFIX}`;
|
|
4193
|
+
const readableTextPath = entries.some((e) => e.isFile() && e.name === readableSibling) ? resolve6(dir, readableSibling) : void 0;
|
|
4194
|
+
return { attachmentId, filename, mimeType, path: resolve6(dir, dataFile.name), readableTextPath };
|
|
4195
|
+
}
|
|
4196
|
+
async function writeAttachment(accountId, subPath, filename, mimeType, sizeBytes, buffer, explicitId) {
|
|
4076
4197
|
const attachmentId = explicitId ?? randomUUID3();
|
|
4077
4198
|
const dir = uploadsDirFor(accountId, subPath, attachmentId);
|
|
4078
4199
|
await mkdir(dir, { recursive: true });
|
|
@@ -4090,11 +4211,23 @@ async function writeAttachment(accountId, subPath, filename, mimeType, sizeBytes
|
|
|
4090
4211
|
await writeFile(storagePath, buffer);
|
|
4091
4212
|
await writeFile(metaPath, JSON.stringify(meta, null, 2));
|
|
4092
4213
|
let readableTextPath;
|
|
4093
|
-
|
|
4094
|
-
|
|
4214
|
+
const bare = mimeType.split(";")[0].trim().toLowerCase();
|
|
4215
|
+
if (CONVERTIBLE_DOC_MIME.has(bare)) {
|
|
4216
|
+
let text = null;
|
|
4217
|
+
try {
|
|
4218
|
+
text = docToText(buffer, mimeType);
|
|
4219
|
+
} catch {
|
|
4220
|
+
text = null;
|
|
4221
|
+
}
|
|
4222
|
+
console.error(`[doc-to-text] op=convert mime=${bare} ok=${text !== null} chars=${text?.length ?? 0}`);
|
|
4095
4223
|
if (text) {
|
|
4096
|
-
|
|
4097
|
-
|
|
4224
|
+
const siblingPath = resolve6(dir, `${attachmentId}${EXTRACTED_TEXT_SUFFIX}`);
|
|
4225
|
+
try {
|
|
4226
|
+
await writeFile(siblingPath, text);
|
|
4227
|
+
readableTextPath = siblingPath;
|
|
4228
|
+
} catch (err) {
|
|
4229
|
+
console.error(`[doc-to-text] op=sibling-write mime=${bare} ok=false reason=${String(err).slice(0, 80)}`);
|
|
4230
|
+
}
|
|
4098
4231
|
}
|
|
4099
4232
|
}
|
|
4100
4233
|
return { attachmentId, filename, storagePath, metaPath, mimeType, sizeBytes, readableTextPath };
|
|
@@ -4141,6 +4274,13 @@ var MIME_BY_EXT = {
|
|
|
4141
4274
|
".odt": "application/vnd.oasis.opendocument.text",
|
|
4142
4275
|
".rtf": "text/rtf",
|
|
4143
4276
|
".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
4277
|
+
// Task 1607 — legacy + OpenDocument office extensions, so a device-stored file
|
|
4278
|
+
// attached to a WhatsApp reply (detectMimeType → isMimeAdmitted, whatsapp-reader.ts)
|
|
4279
|
+
// resolves to the mime now admitted in SUPPORTED_MIME_TYPES rather than octet-stream.
|
|
4280
|
+
".xls": "application/vnd.ms-excel",
|
|
4281
|
+
".ods": "application/vnd.oasis.opendocument.spreadsheet",
|
|
4282
|
+
".ppt": "application/vnd.ms-powerpoint",
|
|
4283
|
+
".odp": "application/vnd.oasis.opendocument.presentation",
|
|
4144
4284
|
".ics": "text/calendar"
|
|
4145
4285
|
};
|
|
4146
4286
|
function detectMimeType(filePath) {
|
|
@@ -4978,20 +5118,6 @@ function attachSelfIdRefreshOnCredsUpdate(conn) {
|
|
|
4978
5118
|
function reloadConfig(accountConfig) {
|
|
4979
5119
|
loadConfig(accountConfig);
|
|
4980
5120
|
}
|
|
4981
|
-
function getMessages(accountId, jid, limit) {
|
|
4982
|
-
const entries = messageStore.get(messageStoreKey(accountId, jid)) ?? [];
|
|
4983
|
-
return limit ? entries.slice(-limit) : entries.slice();
|
|
4984
|
-
}
|
|
4985
|
-
function listConversationJids(accountId) {
|
|
4986
|
-
const prefix = messageStoreKey(accountId, "");
|
|
4987
|
-
const jids = [];
|
|
4988
|
-
for (const key of messageStore.keys()) {
|
|
4989
|
-
if (key.startsWith(prefix)) {
|
|
4990
|
-
jids.push(key.slice(prefix.length));
|
|
4991
|
-
}
|
|
4992
|
-
}
|
|
4993
|
-
return jids;
|
|
4994
|
-
}
|
|
4995
5121
|
function listStoreAccountKeys() {
|
|
4996
5122
|
const accounts = /* @__PURE__ */ new Set();
|
|
4997
5123
|
for (const key of messageStore.keys()) {
|
|
@@ -5205,7 +5331,7 @@ function monitorInbound(conn) {
|
|
|
5205
5331
|
if (!msg.message) continue;
|
|
5206
5332
|
let receiptDeferredToWorker = false;
|
|
5207
5333
|
const extracted = extractMessage(msg);
|
|
5208
|
-
const mediaServable = !!(extracted.mediaType && extracted.mimetype
|
|
5334
|
+
const mediaServable = !!(extracted.mediaType && extracted.mimetype);
|
|
5209
5335
|
if (extracted.text || mediaServable) {
|
|
5210
5336
|
const isGroup = isGroupJid(remoteJid);
|
|
5211
5337
|
const senderJid = isGroup ? msg.key.participant ?? remoteJid : remoteJid;
|
|
@@ -5602,7 +5728,7 @@ async function handleInboundMessage(conn, msg) {
|
|
|
5602
5728
|
// app/lib/vnc.ts
|
|
5603
5729
|
import { spawnSync, execFileSync } from "child_process";
|
|
5604
5730
|
import { createConnection } from "net";
|
|
5605
|
-
import { mkdirSync as mkdirSync2, readFileSync as
|
|
5731
|
+
import { mkdirSync as mkdirSync2, readFileSync as readFileSync9, writeFileSync as writeFileSync3 } from "fs";
|
|
5606
5732
|
import { resolve as resolve7 } from "path";
|
|
5607
5733
|
var PLATFORM_ROOT4 = process.env.MAXY_PLATFORM_ROOT ?? resolve7(process.cwd(), "..");
|
|
5608
5734
|
var VNC_SCRIPT = resolve7(PLATFORM_ROOT4, "scripts/vnc.sh");
|
|
@@ -5660,7 +5786,7 @@ function discoverNativeDisplay() {
|
|
|
5660
5786
|
const leaderPid = leaderResult.stdout?.trim();
|
|
5661
5787
|
if (leaderPid) {
|
|
5662
5788
|
try {
|
|
5663
|
-
const environ =
|
|
5789
|
+
const environ = readFileSync9(`/proc/${leaderPid}/environ`, "utf8");
|
|
5664
5790
|
const match = environ.split("\0").find((e) => e.startsWith("WAYLAND_DISPLAY="));
|
|
5665
5791
|
if (match) waylandDisplay = match.split("=")[1];
|
|
5666
5792
|
} catch {
|
|
@@ -5928,7 +6054,7 @@ app.get("/", async (c) => {
|
|
|
5928
6054
|
let pinConfigured = false;
|
|
5929
6055
|
try {
|
|
5930
6056
|
if (existsSync5(USERS_FILE)) {
|
|
5931
|
-
const raw =
|
|
6057
|
+
const raw = readFileSync10(USERS_FILE, "utf-8").trim();
|
|
5932
6058
|
if (raw) {
|
|
5933
6059
|
const users = JSON.parse(raw);
|
|
5934
6060
|
pinConfigured = Array.isArray(users) && users.length > 0;
|
|
@@ -6600,13 +6726,13 @@ async function sendTelegramText(botToken, chatId, text) {
|
|
|
6600
6726
|
|
|
6601
6727
|
// server/routes/whatsapp.ts
|
|
6602
6728
|
import { join as join10, resolve as resolve10 } from "path";
|
|
6603
|
-
import { readdirSync as
|
|
6729
|
+
import { readdirSync as readdirSync5, readFileSync as readFileSync12, existsSync as existsSync7 } from "fs";
|
|
6604
6730
|
|
|
6605
6731
|
// app/lib/whatsapp/login.ts
|
|
6606
6732
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
6607
6733
|
|
|
6608
6734
|
// app/lib/whatsapp/config-persist.ts
|
|
6609
|
-
import { readFileSync as
|
|
6735
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync4, existsSync as existsSync6 } from "fs";
|
|
6610
6736
|
import { resolve as resolve8, join as join8, dirname as dirname2, basename as basename2 } from "path";
|
|
6611
6737
|
var TAG17 = "[whatsapp:config]";
|
|
6612
6738
|
function configPath(accountDir) {
|
|
@@ -6615,7 +6741,7 @@ function configPath(accountDir) {
|
|
|
6615
6741
|
function readConfig(accountDir) {
|
|
6616
6742
|
const path2 = configPath(accountDir);
|
|
6617
6743
|
if (!existsSync6(path2)) throw new Error(`account.json not found at ${path2}`);
|
|
6618
|
-
return JSON.parse(
|
|
6744
|
+
return JSON.parse(readFileSync11(path2, "utf-8"));
|
|
6619
6745
|
}
|
|
6620
6746
|
function writeConfig(accountDir, config) {
|
|
6621
6747
|
const path2 = configPath(accountDir);
|
|
@@ -7536,13 +7662,13 @@ function serializeWhatsAppSchema() {
|
|
|
7536
7662
|
}
|
|
7537
7663
|
|
|
7538
7664
|
// app/lib/whatsapp/status-reconcile.ts
|
|
7539
|
-
import { readdirSync as
|
|
7665
|
+
import { readdirSync as readdirSync4 } from "fs";
|
|
7540
7666
|
import { join as join9 } from "path";
|
|
7541
7667
|
var TAG20 = "[whatsapp:reconcile]";
|
|
7542
7668
|
var HALF_REGISTERED_MIN_AGE_MS = 5 * 6e4;
|
|
7543
7669
|
function listCredsAccountIds(credsRoot) {
|
|
7544
7670
|
try {
|
|
7545
|
-
return
|
|
7671
|
+
return readdirSync4(credsRoot, { withFileTypes: true }).filter((e) => e.isDirectory() && hasCredsSync(join9(credsRoot, e.name))).map((e) => e.name);
|
|
7546
7672
|
} catch {
|
|
7547
7673
|
return [];
|
|
7548
7674
|
}
|
|
@@ -7689,6 +7815,15 @@ function authorizeRecallRead(input) {
|
|
|
7689
7815
|
// server/routes/whatsapp.ts
|
|
7690
7816
|
var TAG21 = "[whatsapp:api]";
|
|
7691
7817
|
var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
7818
|
+
function recallAttachment(storeAccountId, attachmentId) {
|
|
7819
|
+
if (!attachmentId) return void 0;
|
|
7820
|
+
const a = resolveStoredAttachment(storeAccountId, attachmentId);
|
|
7821
|
+
if (!a) {
|
|
7822
|
+
console.error(`[whatsapp-read-tool] op=attachment-miss attachmentId=${attachmentId.slice(0, 8)} storeAccount=${storeAccountId}`);
|
|
7823
|
+
return void 0;
|
|
7824
|
+
}
|
|
7825
|
+
return a;
|
|
7826
|
+
}
|
|
7692
7827
|
function projectionFor(requestedAccountId) {
|
|
7693
7828
|
const validAccounts = listValidAccounts();
|
|
7694
7829
|
if (validAccounts.length <= 1) return { storeAccountId: requestedAccountId, managerPhones: null };
|
|
@@ -7880,13 +8015,13 @@ app2.post("/config", async (c) => {
|
|
|
7880
8015
|
const agents = [];
|
|
7881
8016
|
if (existsSync7(agentsDir)) {
|
|
7882
8017
|
try {
|
|
7883
|
-
const entries =
|
|
8018
|
+
const entries = readdirSync5(agentsDir, { withFileTypes: true });
|
|
7884
8019
|
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
7885
8020
|
if (!entry.isDirectory() || entry.name === "admin") continue;
|
|
7886
8021
|
const configPath2 = resolve10(agentsDir, entry.name, "config.json");
|
|
7887
8022
|
if (!existsSync7(configPath2)) continue;
|
|
7888
8023
|
try {
|
|
7889
|
-
const config = JSON.parse(
|
|
8024
|
+
const config = JSON.parse(readFileSync12(configPath2, "utf-8"));
|
|
7890
8025
|
agents.push({ slug: entry.name, displayName: config.displayName ?? entry.name });
|
|
7891
8026
|
} catch {
|
|
7892
8027
|
console.error(`${TAG21} config action=list-public-agents error="failed to parse config.json for agent ${entry.name}" \u2014 skipping`);
|
|
@@ -8031,20 +8166,23 @@ app2.get("/conversations", (c) => {
|
|
|
8031
8166
|
const requestedAccountId = validateAccountId(c.req.query("accountId") ?? null);
|
|
8032
8167
|
const denial = callerScopeDenial(c, requestedAccountId);
|
|
8033
8168
|
if (denial) return denial;
|
|
8034
|
-
const
|
|
8035
|
-
const
|
|
8036
|
-
const
|
|
8037
|
-
|
|
8038
|
-
|
|
8169
|
+
const projection = projectionFor(requestedAccountId);
|
|
8170
|
+
const storeAccountId = resolveReadStoreKey(projection.storeAccountId);
|
|
8171
|
+
const projecting = projection.managerPhones != null;
|
|
8172
|
+
const managerPhonesBound = projection.managerPhones?.length ?? 0;
|
|
8173
|
+
const allConversations = readAllConversations(storeAccountId);
|
|
8174
|
+
const scoped = projection.managerPhones ? filterConversationsForSubAccount(allConversations, projection.managerPhones) : allConversations;
|
|
8175
|
+
const conversations = [...scoped.entries()].map(([jid, messages]) => {
|
|
8176
|
+
const last = messages.length > 0 ? messages[messages.length - 1] : null;
|
|
8039
8177
|
return {
|
|
8040
8178
|
jid,
|
|
8041
8179
|
type: isGroupJid(jid) ? "group" : "dm",
|
|
8042
|
-
lastMessageTimestamp:
|
|
8180
|
+
lastMessageTimestamp: last ? Math.floor(Date.parse(last.dateSent) / 1e3) : null,
|
|
8043
8181
|
messageCount: messages.length
|
|
8044
8182
|
};
|
|
8045
8183
|
});
|
|
8046
8184
|
conversations.sort((a, b) => (b.lastMessageTimestamp ?? 0) - (a.lastMessageTimestamp ?? 0));
|
|
8047
|
-
console.error(`${TAG21} conversations requested=${requestedAccountId} account=${
|
|
8185
|
+
console.error(`${TAG21} conversations requested=${requestedAccountId} account=${storeAccountId} projected=${projecting} storeAccount=${projecting ? storeAccountId : "self"} managerPhonesBound=${managerPhonesBound} storeKeyFound=${allConversations.size > 0} count=${conversations.length}`);
|
|
8048
8186
|
return c.json({ conversations });
|
|
8049
8187
|
} catch (err) {
|
|
8050
8188
|
console.error(`${TAG21} conversations error: ${String(err)}`);
|
|
@@ -8056,7 +8194,6 @@ app2.get("/messages", (c) => {
|
|
|
8056
8194
|
const requestedAccountId = validateAccountId(c.req.query("accountId") ?? null);
|
|
8057
8195
|
const denial = callerScopeDenial(c, requestedAccountId);
|
|
8058
8196
|
if (denial) return denial;
|
|
8059
|
-
const accountId = resolveReadStoreKey(requestedAccountId);
|
|
8060
8197
|
const jid = c.req.query("jid");
|
|
8061
8198
|
if (!jid) {
|
|
8062
8199
|
return c.json({ error: "Missing required parameter: jid" }, 400);
|
|
@@ -8064,9 +8201,33 @@ app2.get("/messages", (c) => {
|
|
|
8064
8201
|
const limitParam = c.req.query("limit");
|
|
8065
8202
|
const limit = limitParam ? parseInt(limitParam, 10) : void 0;
|
|
8066
8203
|
const effectiveLimit = limit && !Number.isNaN(limit) && limit > 0 ? limit : void 0;
|
|
8067
|
-
const
|
|
8068
|
-
const
|
|
8069
|
-
|
|
8204
|
+
const projection = projectionFor(requestedAccountId);
|
|
8205
|
+
const storeAccountId = resolveReadStoreKey(projection.storeAccountId);
|
|
8206
|
+
const projecting = projection.managerPhones != null;
|
|
8207
|
+
const managerPhonesBound = projection.managerPhones?.length ?? 0;
|
|
8208
|
+
const storeMessages = readConversation(storeAccountId, jid);
|
|
8209
|
+
const counterpartyBound = !projecting || counterpartyBoundToSubAccount(
|
|
8210
|
+
projection.managerPhones,
|
|
8211
|
+
conversationCounterpartyPhone(jid, storeMessages[0]?.senderTelephone ?? "")
|
|
8212
|
+
);
|
|
8213
|
+
const bounded = counterpartyBound ? storeMessages : [];
|
|
8214
|
+
const limited = effectiveLimit ? bounded.slice(-effectiveLimit) : bounded;
|
|
8215
|
+
let withAttachments = 0;
|
|
8216
|
+
const messages = limited.map((m) => {
|
|
8217
|
+
const attachment = recallAttachment(storeAccountId, m.attachmentId);
|
|
8218
|
+
if (attachment) withAttachments += 1;
|
|
8219
|
+
return {
|
|
8220
|
+
id: m.messageId,
|
|
8221
|
+
sender: m.senderTelephone,
|
|
8222
|
+
senderName: m.senderName ?? void 0,
|
|
8223
|
+
body: m.body,
|
|
8224
|
+
timestamp: Math.floor(Date.parse(m.dateSent) / 1e3),
|
|
8225
|
+
fromMe: m.fromMe,
|
|
8226
|
+
quoted: m.quotedId ? { id: m.quotedId, sender: m.quotedSender ?? void 0 } : void 0,
|
|
8227
|
+
attachment
|
|
8228
|
+
};
|
|
8229
|
+
});
|
|
8230
|
+
console.error(`${TAG21} messages requested=${requestedAccountId} account=${storeAccountId} jid=${jid} projected=${projecting} storeAccount=${projecting ? storeAccountId : "self"} managerPhonesBound=${managerPhonesBound} storeKeyFound=${storeMessages.length > 0} limit=${effectiveLimit ?? "all"} returned=${messages.length} withAttachments=${withAttachments}`);
|
|
8070
8231
|
return c.json({ messages });
|
|
8071
8232
|
} catch (err) {
|
|
8072
8233
|
console.error(`${TAG21} messages error: ${String(err)}`);
|
|
@@ -8090,6 +8251,7 @@ app2.get("/conversation-graph-state", async (c) => {
|
|
|
8090
8251
|
const rows2 = [];
|
|
8091
8252
|
const nameCache = /* @__PURE__ */ new Map();
|
|
8092
8253
|
let unresolvedSenders = 0;
|
|
8254
|
+
let withAttachments2 = 0;
|
|
8093
8255
|
let session = null;
|
|
8094
8256
|
try {
|
|
8095
8257
|
session = getSession();
|
|
@@ -8105,6 +8267,8 @@ app2.get("/conversation-graph-state", async (c) => {
|
|
|
8105
8267
|
nameCache.set(m.senderTelephone, resolved);
|
|
8106
8268
|
if (!resolved) unresolvedSenders += 1;
|
|
8107
8269
|
}
|
|
8270
|
+
const attachment = recallAttachment(projection2.storeAccountId, m.attachmentId);
|
|
8271
|
+
if (attachment) withAttachments2 += 1;
|
|
8108
8272
|
rows2.push({
|
|
8109
8273
|
remoteJid: remoteJid2,
|
|
8110
8274
|
messageId: m.messageId,
|
|
@@ -8112,7 +8276,8 @@ app2.get("/conversation-graph-state", async (c) => {
|
|
|
8112
8276
|
fromMe: m.fromMe,
|
|
8113
8277
|
senderTelephone: m.senderTelephone,
|
|
8114
8278
|
senderName: nameCache.get(m.senderTelephone) ?? m.senderName,
|
|
8115
|
-
body: m.body
|
|
8279
|
+
body: m.body,
|
|
8280
|
+
attachment
|
|
8116
8281
|
});
|
|
8117
8282
|
}
|
|
8118
8283
|
}
|
|
@@ -8120,7 +8285,7 @@ app2.get("/conversation-graph-state", async (c) => {
|
|
|
8120
8285
|
if (session) await session.close();
|
|
8121
8286
|
}
|
|
8122
8287
|
const ms2 = Date.now() - t0;
|
|
8123
|
-
console.error(`[whatsapp-read-tool] op=query scope=${requestedAccountId} storeAccount=${projection2.storeAccountId} managerPhonesBound=${managerPhonesBound} resultCount=${rows2.length} unresolvedSenders=${unresolvedSenders} ms=${ms2}`);
|
|
8288
|
+
console.error(`[whatsapp-read-tool] op=query scope=${requestedAccountId} storeAccount=${projection2.storeAccountId} managerPhonesBound=${managerPhonesBound} resultCount=${rows2.length} unresolvedSenders=${unresolvedSenders} withAttachments=${withAttachments2} ms=${ms2}`);
|
|
8124
8289
|
return c.json({ accountId: requestedAccountId, rows: rows2, unresolvedSenders, ms: ms2, managerPhonesBound });
|
|
8125
8290
|
}
|
|
8126
8291
|
let remoteJid;
|
|
@@ -8144,15 +8309,21 @@ app2.get("/conversation-graph-state", async (c) => {
|
|
|
8144
8309
|
);
|
|
8145
8310
|
const messages = counterpartyBound ? storeMessages : [];
|
|
8146
8311
|
const sessionId = messages[0]?.sessionId ?? null;
|
|
8147
|
-
|
|
8148
|
-
|
|
8149
|
-
|
|
8150
|
-
|
|
8151
|
-
|
|
8152
|
-
|
|
8153
|
-
|
|
8312
|
+
let withAttachments = 0;
|
|
8313
|
+
const rows = messages.map((m) => {
|
|
8314
|
+
const attachment = recallAttachment(projection.storeAccountId, m.attachmentId);
|
|
8315
|
+
if (attachment) withAttachments += 1;
|
|
8316
|
+
return {
|
|
8317
|
+
messageId: m.messageId,
|
|
8318
|
+
dateSent: m.dateSent,
|
|
8319
|
+
fromMe: m.fromMe,
|
|
8320
|
+
senderTelephone: m.senderTelephone,
|
|
8321
|
+
body: m.body,
|
|
8322
|
+
attachment
|
|
8323
|
+
};
|
|
8324
|
+
});
|
|
8154
8325
|
const ms = Date.now() - t0;
|
|
8155
|
-
console.error(`[whatsapp-read-tool] op=query mode=single scope=${accountId} storeAccount=${projection.storeAccountId} graphRows=${rows.length} sessionId=${sessionId ?? "null"} ms=${ms}`);
|
|
8326
|
+
console.error(`[whatsapp-read-tool] op=query mode=single scope=${accountId} storeAccount=${projection.storeAccountId} graphRows=${rows.length} sessionId=${sessionId ?? "null"} withAttachments=${withAttachments} ms=${ms}`);
|
|
8156
8327
|
return c.json({
|
|
8157
8328
|
cacheKey,
|
|
8158
8329
|
sessionId,
|
|
@@ -8201,15 +8372,15 @@ app2.get("/group-info", async (c) => {
|
|
|
8201
8372
|
var whatsapp_default = app2;
|
|
8202
8373
|
|
|
8203
8374
|
// server/routes/whatsapp-reader.ts
|
|
8204
|
-
import { readFileSync as
|
|
8375
|
+
import { readFileSync as readFileSync16, watch, statSync as statSync5, openSync, readSync, closeSync, existsSync as existsSync10, readdirSync as readdirSync10, realpathSync as realpathSync4 } from "fs";
|
|
8205
8376
|
import { basename as basename4, dirname as dirname4, isAbsolute, join as join15, relative as relative2, resolve as resolve12, sep as sep3 } from "path";
|
|
8206
8377
|
|
|
8207
8378
|
// server/routes/admin/sidebar-sessions.ts
|
|
8208
|
-
import { readdirSync as
|
|
8379
|
+
import { readdirSync as readdirSync8, readFileSync as readFileSync14, statSync as statSync4 } from "fs";
|
|
8209
8380
|
import { dirname as dirname3, join as join13, resolve as resolve11 } from "path";
|
|
8210
8381
|
|
|
8211
8382
|
// ../services/claude-session-manager/src/jsonl-path.ts
|
|
8212
|
-
import { existsSync as existsSync8, readdirSync as
|
|
8383
|
+
import { existsSync as existsSync8, readdirSync as readdirSync6 } from "fs";
|
|
8213
8384
|
import { homedir } from "os";
|
|
8214
8385
|
import { join as join11 } from "path";
|
|
8215
8386
|
function findExistingJsonlForSessionId(claudeConfigDir2, sessionId) {
|
|
@@ -8217,7 +8388,7 @@ function findExistingJsonlForSessionId(claudeConfigDir2, sessionId) {
|
|
|
8217
8388
|
if (!existsSync8(projectsRoot)) return null;
|
|
8218
8389
|
let slugs;
|
|
8219
8390
|
try {
|
|
8220
|
-
slugs =
|
|
8391
|
+
slugs = readdirSync6(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
8221
8392
|
} catch {
|
|
8222
8393
|
return null;
|
|
8223
8394
|
}
|
|
@@ -8233,14 +8404,14 @@ function findExistingJsonlForSessionId(claudeConfigDir2, sessionId) {
|
|
|
8233
8404
|
|
|
8234
8405
|
// app/lib/admin-identity/pin-validator.ts
|
|
8235
8406
|
import { createHash as createHash3 } from "crypto";
|
|
8236
|
-
import { existsSync as existsSync9, readFileSync as
|
|
8407
|
+
import { existsSync as existsSync9, readFileSync as readFileSync13, readdirSync as readdirSync7, statSync as statSync3 } from "fs";
|
|
8237
8408
|
import { join as join12 } from "path";
|
|
8238
8409
|
function hashPin(pin) {
|
|
8239
8410
|
return createHash3("sha256").update(pin).digest("hex");
|
|
8240
8411
|
}
|
|
8241
8412
|
function readUsersFile(usersFilePath) {
|
|
8242
8413
|
if (!existsSync9(usersFilePath)) return null;
|
|
8243
|
-
const raw =
|
|
8414
|
+
const raw = readFileSync13(usersFilePath, "utf-8").trim();
|
|
8244
8415
|
if (!raw) return [];
|
|
8245
8416
|
return JSON.parse(raw);
|
|
8246
8417
|
}
|
|
@@ -8359,7 +8530,7 @@ function enumerateJsonls(projectsRoot) {
|
|
|
8359
8530
|
const out = [];
|
|
8360
8531
|
let slugs;
|
|
8361
8532
|
try {
|
|
8362
|
-
slugs =
|
|
8533
|
+
slugs = readdirSync8(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
8363
8534
|
} catch (err) {
|
|
8364
8535
|
if (err.code === "ENOENT") return out;
|
|
8365
8536
|
throw err;
|
|
@@ -8368,7 +8539,7 @@ function enumerateJsonls(projectsRoot) {
|
|
|
8368
8539
|
const slugDir = join13(projectsRoot, slug);
|
|
8369
8540
|
let entries;
|
|
8370
8541
|
try {
|
|
8371
|
-
entries =
|
|
8542
|
+
entries = readdirSync8(slugDir, { withFileTypes: true });
|
|
8372
8543
|
} catch (err) {
|
|
8373
8544
|
const code = err.code ?? "unknown";
|
|
8374
8545
|
console.error(`[admin-sessions-list] slug-skipped slug=${slug} code=${code}`);
|
|
@@ -8381,7 +8552,7 @@ function enumerateJsonls(projectsRoot) {
|
|
|
8381
8552
|
const subDir = join13(slugDir, entry.name);
|
|
8382
8553
|
let subEntries;
|
|
8383
8554
|
try {
|
|
8384
|
-
subEntries =
|
|
8555
|
+
subEntries = readdirSync8(subDir, { withFileTypes: true });
|
|
8385
8556
|
} catch (err) {
|
|
8386
8557
|
const code = err.code ?? "unknown";
|
|
8387
8558
|
console.error(`[admin-sessions-list] subagents-skipped slug=${slug} code=${code}`);
|
|
@@ -8396,7 +8567,7 @@ function enumerateJsonls(projectsRoot) {
|
|
|
8396
8567
|
const archiveDir = join13(slugDir, entry.name);
|
|
8397
8568
|
let archiveEntries;
|
|
8398
8569
|
try {
|
|
8399
|
-
archiveEntries =
|
|
8570
|
+
archiveEntries = readdirSync8(archiveDir, { withFileTypes: true });
|
|
8400
8571
|
} catch (err) {
|
|
8401
8572
|
const code = err.code ?? "unknown";
|
|
8402
8573
|
console.error(`[admin-sessions-list] archive-skipped slug=${slug} code=${code}`);
|
|
@@ -8440,7 +8611,7 @@ function loadUserTitles(accountDir) {
|
|
|
8440
8611
|
const path2 = join13(accountDir, "session-titles.json");
|
|
8441
8612
|
let raw;
|
|
8442
8613
|
try {
|
|
8443
|
-
raw =
|
|
8614
|
+
raw = readFileSync14(path2, "utf8");
|
|
8444
8615
|
} catch {
|
|
8445
8616
|
return out;
|
|
8446
8617
|
}
|
|
@@ -8466,7 +8637,7 @@ function readSidecarMeta(metaPath) {
|
|
|
8466
8637
|
const empty = { bridgeIds: [], role: null, channel: null, senderId: null, startedAt: null, personId: null, adminUserId: null, visitorId: null, agentSlug: null, accountId: null };
|
|
8467
8638
|
let raw;
|
|
8468
8639
|
try {
|
|
8469
|
-
raw =
|
|
8640
|
+
raw = readFileSync14(metaPath, "utf8");
|
|
8470
8641
|
} catch {
|
|
8471
8642
|
return empty;
|
|
8472
8643
|
}
|
|
@@ -8608,7 +8779,7 @@ app3.get("/", requireAdminSession, async (c) => {
|
|
|
8608
8779
|
let body;
|
|
8609
8780
|
let mtimeMs;
|
|
8610
8781
|
try {
|
|
8611
|
-
body =
|
|
8782
|
+
body = readFileSync14(path2, "utf8");
|
|
8612
8783
|
mtimeMs = statSync4(path2).mtimeMs;
|
|
8613
8784
|
} catch {
|
|
8614
8785
|
continue;
|
|
@@ -8968,7 +9139,7 @@ function parseTranscript(lines, queuedPendingSuppress = /* @__PURE__ */ new Map(
|
|
|
8968
9139
|
}
|
|
8969
9140
|
|
|
8970
9141
|
// app/lib/whatsapp-reader/enrich-attachments.ts
|
|
8971
|
-
import { readFileSync as
|
|
9142
|
+
import { readFileSync as readFileSync15, readdirSync as readdirSync9 } from "fs";
|
|
8972
9143
|
import { join as join14 } from "path";
|
|
8973
9144
|
var ADMIN_UPLOAD_PATH = /\/uploads\/(?!public\/)([0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})\//gi;
|
|
8974
9145
|
function adminAttachmentIds(text) {
|
|
@@ -8990,7 +9161,7 @@ function adminAttachmentsFromText(text, uploadsBase) {
|
|
|
8990
9161
|
function readSidecar(dir, attachmentId) {
|
|
8991
9162
|
let parsed;
|
|
8992
9163
|
try {
|
|
8993
|
-
parsed = JSON.parse(
|
|
9164
|
+
parsed = JSON.parse(readFileSync15(join14(dir, `${attachmentId}.meta.json`), "utf8"));
|
|
8994
9165
|
} catch {
|
|
8995
9166
|
return null;
|
|
8996
9167
|
}
|
|
@@ -9013,7 +9184,7 @@ function readAttachmentMeta(dir) {
|
|
|
9013
9184
|
function listSessionAttachmentsInDir(dir) {
|
|
9014
9185
|
let entries;
|
|
9015
9186
|
try {
|
|
9016
|
-
entries =
|
|
9187
|
+
entries = readdirSync9(dir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
9017
9188
|
} catch {
|
|
9018
9189
|
return [];
|
|
9019
9190
|
}
|
|
@@ -9060,7 +9231,7 @@ function pickActivity(entries, grown, nowMs, concurrencyWindowMs) {
|
|
|
9060
9231
|
}
|
|
9061
9232
|
|
|
9062
9233
|
// app/admin-types.ts
|
|
9063
|
-
var ACCEPT_MIME = "image/jpeg,image/png,image/gif,image/webp,application/pdf,text/plain,text/markdown,text/csv,text/html,text/calendar,application/zip,application/x-zip-compressed,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.oasis.opendocument.text,text/rtf,application/rtf,audio/ogg,audio/opus,audio/mp4,audio/x-m4a,audio/mpeg,audio/webm,audio/wav,video/mp4,.docx,.odt,.rtf,.opus,.ogg,.m4a,.mp4,.mp3,.wav,.webm";
|
|
9234
|
+
var ACCEPT_MIME = "image/jpeg,image/png,image/gif,image/webp,application/pdf,text/plain,text/markdown,text/csv,text/html,text/calendar,application/zip,application/x-zip-compressed,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.oasis.opendocument.text,text/rtf,application/rtf,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel,application/vnd.oasis.opendocument.spreadsheet,application/vnd.openxmlformats-officedocument.presentationml.presentation,application/vnd.ms-powerpoint,application/vnd.oasis.opendocument.presentation,audio/ogg,audio/opus,audio/mp4,audio/x-m4a,audio/mpeg,audio/webm,audio/wav,video/mp4,.docx,.odt,.rtf,.xlsx,.xls,.ods,.pptx,.ppt,.odp,.opus,.ogg,.m4a,.mp4,.mp3,.wav,.webm";
|
|
9064
9235
|
var SUPPORTED_MIME_SET = new Set(ACCEPT_MIME.split(",").filter((t) => !t.startsWith(".")));
|
|
9065
9236
|
var MAX_ATTACHMENTS = 5;
|
|
9066
9237
|
var MAX_FILE_BYTES = 50 * 1024 * 1024;
|
|
@@ -9099,7 +9270,7 @@ app4.get("/conversations", requireAdminSession, async (c) => {
|
|
|
9099
9270
|
}
|
|
9100
9271
|
let body = "";
|
|
9101
9272
|
try {
|
|
9102
|
-
body =
|
|
9273
|
+
body = readFileSync16(path2, "utf8");
|
|
9103
9274
|
} catch {
|
|
9104
9275
|
}
|
|
9105
9276
|
const { title } = resolveTitle(body, sessionId, userTitles);
|
|
@@ -9268,7 +9439,7 @@ function openTaskKey(turns) {
|
|
|
9268
9439
|
}
|
|
9269
9440
|
function readSubagentMeta(dir, hex) {
|
|
9270
9441
|
try {
|
|
9271
|
-
const m = JSON.parse(
|
|
9442
|
+
const m = JSON.parse(readFileSync16(join15(dir, `agent-${hex}.meta.json`), "utf8"));
|
|
9272
9443
|
if (typeof m.agentType === "string" && typeof m.description === "string" && typeof m.toolUseId === "string") {
|
|
9273
9444
|
return { agentType: m.agentType, description: m.description, toolUseId: m.toolUseId };
|
|
9274
9445
|
}
|
|
@@ -9291,7 +9462,7 @@ function runActivityTick(c) {
|
|
|
9291
9462
|
c.parentGrewThisTick = false;
|
|
9292
9463
|
let names = [];
|
|
9293
9464
|
try {
|
|
9294
|
-
names =
|
|
9465
|
+
names = readdirSync10(c.subagentsDir).filter((n) => AGENT_JSONL_RE.test(n));
|
|
9295
9466
|
} catch {
|
|
9296
9467
|
}
|
|
9297
9468
|
const entries = [];
|
|
@@ -9486,7 +9657,7 @@ app4.get("/directives", requireAdminSession, (c) => {
|
|
|
9486
9657
|
if (!dir || !existsSync10(dir)) return c.json({ entries: [] });
|
|
9487
9658
|
let names;
|
|
9488
9659
|
try {
|
|
9489
|
-
names =
|
|
9660
|
+
names = readdirSync10(dir).filter((n) => DIRECTIVE_NAME_RE.test(n));
|
|
9490
9661
|
} catch {
|
|
9491
9662
|
return c.json({ entries: [] });
|
|
9492
9663
|
}
|
|
@@ -9515,7 +9686,7 @@ app4.get("/directive", requireAdminSession, (c) => {
|
|
|
9515
9686
|
if (!path2.startsWith(dir + sep3)) return c.json({ error: "bad reference" }, 400);
|
|
9516
9687
|
let body;
|
|
9517
9688
|
try {
|
|
9518
|
-
body =
|
|
9689
|
+
body = readFileSync16(path2, "utf8");
|
|
9519
9690
|
} catch {
|
|
9520
9691
|
return c.json({ error: "not found" }, 404);
|
|
9521
9692
|
}
|
|
@@ -9872,7 +10043,7 @@ app4.post("/reply", requireAdminSession, async (c) => {
|
|
|
9872
10043
|
}
|
|
9873
10044
|
for (let i = 0; i < resolvedRefs.length; i++) {
|
|
9874
10045
|
const { absolute, mime } = resolvedRefs[i];
|
|
9875
|
-
const file = new File([
|
|
10046
|
+
const file = new File([readFileSync16(absolute)], basename4(absolute), { type: mime });
|
|
9876
10047
|
const out = await sendStagedFile(file, `ref=${i}`);
|
|
9877
10048
|
if (!out.ok) {
|
|
9878
10049
|
exit("error");
|
|
@@ -9891,7 +10062,7 @@ app4.post("/reply", requireAdminSession, async (c) => {
|
|
|
9891
10062
|
var whatsapp_reader_default = app4;
|
|
9892
10063
|
|
|
9893
10064
|
// server/routes/public-reader.ts
|
|
9894
|
-
import { statSync as statSync6, openSync as openSync2, readSync as readSync2, closeSync as closeSync2, watch as watch2, readFileSync as
|
|
10065
|
+
import { statSync as statSync6, openSync as openSync2, readSync as readSync2, closeSync as closeSync2, watch as watch2, readFileSync as readFileSync17, readdirSync as readdirSync11 } from "fs";
|
|
9895
10066
|
import { basename as basename5, dirname as dirname5, join as join16, resolve as resolve13, sep as sep4 } from "path";
|
|
9896
10067
|
|
|
9897
10068
|
// app/lib/whatsapp-reader/delivered-kinds.ts
|
|
@@ -10125,7 +10296,7 @@ data: ${JSON.stringify(turn)}
|
|
|
10125
10296
|
});
|
|
10126
10297
|
});
|
|
10127
10298
|
var ATT_TAG = "[public-attachment]";
|
|
10128
|
-
var
|
|
10299
|
+
var ATTACHMENT_ID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
10129
10300
|
app5.get("/attachment/:attachmentId", (c) => {
|
|
10130
10301
|
const visitor = resolveVisitor(c);
|
|
10131
10302
|
const attachmentId = c.req.param("attachmentId");
|
|
@@ -10137,7 +10308,7 @@ app5.get("/attachment/:attachmentId", (c) => {
|
|
|
10137
10308
|
return new Response("Unauthorized", { status: 401 });
|
|
10138
10309
|
}
|
|
10139
10310
|
console.log(`${ATT_TAG} op=request session=${ses} att=${at}`);
|
|
10140
|
-
if (!
|
|
10311
|
+
if (!ATTACHMENT_ID_RE2.test(attachmentId) || !SESSION_ID_RE2.test(sessionId)) {
|
|
10141
10312
|
console.error(`${ATT_TAG} op=denied session=${ses} att=${at} reason=bad-id`);
|
|
10142
10313
|
return new Response("Not found", { status: 404 });
|
|
10143
10314
|
}
|
|
@@ -10166,19 +10337,22 @@ app5.get("/attachment/:attachmentId", (c) => {
|
|
|
10166
10337
|
let dataFile;
|
|
10167
10338
|
let buffer;
|
|
10168
10339
|
try {
|
|
10169
|
-
dataFile =
|
|
10340
|
+
dataFile = readdirSync11(dir).find((f) => !f.endsWith(".meta.json") && !f.endsWith(EXTRACTED_TEXT_SUFFIX));
|
|
10170
10341
|
if (!dataFile) throw new Error("no data file");
|
|
10171
|
-
buffer =
|
|
10342
|
+
buffer = readFileSync17(resolve13(dir, dataFile));
|
|
10172
10343
|
} catch {
|
|
10173
10344
|
console.error(`${ATT_TAG} op=denied session=${ses} att=${at} reason=not-found`);
|
|
10174
10345
|
return new Response("Not found", { status: 404 });
|
|
10175
10346
|
}
|
|
10176
|
-
|
|
10347
|
+
const inlineSafe = isInlineSafeMime(meta.mimeType);
|
|
10348
|
+
const disposition = inlineSafe ? "inline" : "attachment";
|
|
10349
|
+
console.log(`${ATT_TAG} op=served session=${ses} att=${at} bytes=${buffer.length} mime=${meta.mimeType} disposition=${disposition}${inlineSafe ? "" : " reason=non-preview-mime"}`);
|
|
10177
10350
|
const safeName = meta.filename.replace(/["\\\r\n]/g, "_");
|
|
10178
10351
|
return new Response(new Uint8Array(buffer), {
|
|
10179
10352
|
headers: {
|
|
10180
10353
|
"Content-Type": meta.mimeType,
|
|
10181
|
-
"Content-Disposition":
|
|
10354
|
+
"Content-Disposition": `${disposition}; filename="${safeName}"`,
|
|
10355
|
+
"X-Content-Type-Options": "nosniff",
|
|
10182
10356
|
"Cache-Control": "private, max-age=3600"
|
|
10183
10357
|
}
|
|
10184
10358
|
});
|
|
@@ -10188,10 +10362,10 @@ var public_reader_default = app5;
|
|
|
10188
10362
|
// server/routes/webchat.ts
|
|
10189
10363
|
import { basename as basename6, dirname as dirname6 } from "path";
|
|
10190
10364
|
import { join as join19 } from "path";
|
|
10191
|
-
import { existsSync as existsSync12, readdirSync as
|
|
10365
|
+
import { existsSync as existsSync12, readdirSync as readdirSync13, readFileSync as readFileSync20, renameSync as renameSync4, statSync as statSync7, writeFileSync as writeFileSync7 } from "fs";
|
|
10192
10366
|
|
|
10193
10367
|
// server/canonical-webchat-override.ts
|
|
10194
|
-
import { readFileSync as
|
|
10368
|
+
import { readFileSync as readFileSync18, writeFileSync as writeFileSync5, renameSync as renameSync2 } from "fs";
|
|
10195
10369
|
import { join as join17 } from "path";
|
|
10196
10370
|
var FILE = "canonical-webchat-session.json";
|
|
10197
10371
|
var UUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
@@ -10200,7 +10374,7 @@ function canonicalOverridePath(accountDir) {
|
|
|
10200
10374
|
}
|
|
10201
10375
|
function readRaw(accountDir) {
|
|
10202
10376
|
try {
|
|
10203
|
-
return JSON.parse(
|
|
10377
|
+
return JSON.parse(readFileSync18(canonicalOverridePath(accountDir), "utf8"));
|
|
10204
10378
|
} catch {
|
|
10205
10379
|
return null;
|
|
10206
10380
|
}
|
|
@@ -10275,7 +10449,7 @@ function isNewSessionEffortLevel(value) {
|
|
|
10275
10449
|
}
|
|
10276
10450
|
|
|
10277
10451
|
// ../services/claude-session-manager/src/sidecar-store.ts
|
|
10278
|
-
import { existsSync as existsSync11, mkdirSync as mkdirSync3, readdirSync as
|
|
10452
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync3, readdirSync as readdirSync12, readFileSync as readFileSync19, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
10279
10453
|
import { join as join18 } from "path";
|
|
10280
10454
|
function escapeRegExp(s) {
|
|
10281
10455
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -10305,7 +10479,7 @@ function createSidecarStore(config) {
|
|
|
10305
10479
|
function readFileAt(path2) {
|
|
10306
10480
|
let raw;
|
|
10307
10481
|
try {
|
|
10308
|
-
raw =
|
|
10482
|
+
raw = readFileSync19(path2, "utf8");
|
|
10309
10483
|
} catch {
|
|
10310
10484
|
return null;
|
|
10311
10485
|
}
|
|
@@ -10321,7 +10495,7 @@ function createSidecarStore(config) {
|
|
|
10321
10495
|
function readAll(sessionsDir, onSkip) {
|
|
10322
10496
|
let names;
|
|
10323
10497
|
try {
|
|
10324
|
-
names =
|
|
10498
|
+
names = readdirSync12(sessionsDir, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name);
|
|
10325
10499
|
} catch {
|
|
10326
10500
|
return [];
|
|
10327
10501
|
}
|
|
@@ -10331,7 +10505,7 @@ function createSidecarStore(config) {
|
|
|
10331
10505
|
const path2 = join18(sessionsDir, name);
|
|
10332
10506
|
let raw;
|
|
10333
10507
|
try {
|
|
10334
|
-
raw =
|
|
10508
|
+
raw = readFileSync19(path2, "utf8");
|
|
10335
10509
|
} catch {
|
|
10336
10510
|
onSkip?.(name, "unreadable");
|
|
10337
10511
|
continue;
|
|
@@ -10414,7 +10588,7 @@ function locateSidecar(sessionId) {
|
|
|
10414
10588
|
const projectsRoot = join19(cfg, "projects");
|
|
10415
10589
|
let slugs;
|
|
10416
10590
|
try {
|
|
10417
|
-
slugs =
|
|
10591
|
+
slugs = readdirSync13(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
10418
10592
|
} catch {
|
|
10419
10593
|
return null;
|
|
10420
10594
|
}
|
|
@@ -10897,7 +11071,7 @@ ${note}` : note;
|
|
|
10897
11071
|
}
|
|
10898
11072
|
const accountJsonPath = join19(account.accountDir, "account.json");
|
|
10899
11073
|
try {
|
|
10900
|
-
const parsed = JSON.parse(
|
|
11074
|
+
const parsed = JSON.parse(readFileSync20(accountJsonPath, "utf8"));
|
|
10901
11075
|
if (op === "model") parsed.adminModel = value;
|
|
10902
11076
|
else if (op === "effort") parsed.effort = value;
|
|
10903
11077
|
else parsed.adminPermissionMode = value;
|
|
@@ -11015,7 +11189,7 @@ ${note}` : note;
|
|
|
11015
11189
|
import { resolve as resolve14 } from "path";
|
|
11016
11190
|
|
|
11017
11191
|
// app/lib/claude-agent/specialist-roster.ts
|
|
11018
|
-
import { existsSync as existsSync13, readFileSync as
|
|
11192
|
+
import { existsSync as existsSync13, readFileSync as readFileSync21, readdirSync as readdirSync14 } from "fs";
|
|
11019
11193
|
import { join as join20 } from "path";
|
|
11020
11194
|
function field(fm, name) {
|
|
11021
11195
|
const m = fm.match(new RegExp(`^${name}:\\s*(.*?)\\r?$`, "m"));
|
|
@@ -11028,14 +11202,14 @@ function field(fm, name) {
|
|
|
11028
11202
|
}
|
|
11029
11203
|
function readSpecialistRoster(specialistsDir) {
|
|
11030
11204
|
if (!existsSync13(specialistsDir)) return { specialists: [], skipped: [] };
|
|
11031
|
-
const entries =
|
|
11205
|
+
const entries = readdirSync14(specialistsDir);
|
|
11032
11206
|
const specialists = [];
|
|
11033
11207
|
const skipped = [];
|
|
11034
11208
|
for (const file of entries.sort()) {
|
|
11035
11209
|
if (!file.endsWith(".md")) continue;
|
|
11036
11210
|
let raw;
|
|
11037
11211
|
try {
|
|
11038
|
-
raw =
|
|
11212
|
+
raw = readFileSync21(join20(specialistsDir, file), "utf-8");
|
|
11039
11213
|
} catch (err) {
|
|
11040
11214
|
skipped.push({ file, reason: err instanceof Error ? err.message : String(err) });
|
|
11041
11215
|
continue;
|
|
@@ -11153,7 +11327,7 @@ var webchat_greeting_default = app6;
|
|
|
11153
11327
|
// server/routes/telegram.ts
|
|
11154
11328
|
import { homedir as homedir2 } from "os";
|
|
11155
11329
|
import { resolve as resolve15, join as join21 } from "path";
|
|
11156
|
-
import { existsSync as existsSync14, readFileSync as
|
|
11330
|
+
import { existsSync as existsSync14, readFileSync as readFileSync22 } from "fs";
|
|
11157
11331
|
|
|
11158
11332
|
// app/lib/telegram/gateway/instance.ts
|
|
11159
11333
|
var instance = null;
|
|
@@ -11215,7 +11389,7 @@ function configDirName() {
|
|
|
11215
11389
|
const brandPath = join21(platformRoot3, "config", "brand.json");
|
|
11216
11390
|
if (existsSync14(brandPath)) {
|
|
11217
11391
|
try {
|
|
11218
|
-
return JSON.parse(
|
|
11392
|
+
return JSON.parse(readFileSync22(brandPath, "utf-8")).configDir ?? ".maxy";
|
|
11219
11393
|
} catch {
|
|
11220
11394
|
}
|
|
11221
11395
|
}
|
|
@@ -11238,7 +11412,7 @@ app7.post("/", async (c) => {
|
|
|
11238
11412
|
console.error(`${TAG23} op=reject reason=no-secret-file botType=${botType}`);
|
|
11239
11413
|
return c.json({ ok: false }, 401);
|
|
11240
11414
|
}
|
|
11241
|
-
const expected =
|
|
11415
|
+
const expected = readFileSync22(sp, "utf-8").trim();
|
|
11242
11416
|
const got = c.req.header("x-telegram-bot-api-secret-token") ?? "";
|
|
11243
11417
|
if (got !== expected) {
|
|
11244
11418
|
console.error(`${TAG23} op=reject reason=bad-secret botType=${botType}`);
|
|
@@ -11302,7 +11476,7 @@ var telegram_default = app7;
|
|
|
11302
11476
|
|
|
11303
11477
|
// server/routes/quickbooks.ts
|
|
11304
11478
|
import { join as join22 } from "path";
|
|
11305
|
-
import { existsSync as existsSync15, readFileSync as
|
|
11479
|
+
import { existsSync as existsSync15, readFileSync as readFileSync23, writeFileSync as writeFileSync8, mkdirSync as mkdirSync4, rmSync, renameSync as renameSync5 } from "fs";
|
|
11306
11480
|
var TAG24 = "[quickbooks]";
|
|
11307
11481
|
var INTUIT_TOKEN_URL = "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer";
|
|
11308
11482
|
var STATE_RE = /^[A-Za-z0-9_-]+$/;
|
|
@@ -11329,7 +11503,7 @@ async function completeConsent(args) {
|
|
|
11329
11503
|
try {
|
|
11330
11504
|
let pending;
|
|
11331
11505
|
try {
|
|
11332
|
-
pending = JSON.parse(
|
|
11506
|
+
pending = JSON.parse(readFileSync23(claimFile, "utf-8"));
|
|
11333
11507
|
} catch {
|
|
11334
11508
|
console.error(`${TAG24} op=callback state=${state} stateValid=false realmId=${realmId ?? ""}`);
|
|
11335
11509
|
return { ok: false, status: 400, message: "Authorization state could not be read.", stateValid: false };
|
|
@@ -11345,7 +11519,7 @@ async function completeConsent(args) {
|
|
|
11345
11519
|
if (!existsSync15(storePath(accountDir))) {
|
|
11346
11520
|
return { ok: false, status: 500, message: "No QuickBooks credentials are stored for this account.", stateValid: true };
|
|
11347
11521
|
}
|
|
11348
|
-
const store2 = JSON.parse(
|
|
11522
|
+
const store2 = JSON.parse(readFileSync23(storePath(accountDir), "utf-8"));
|
|
11349
11523
|
const form = new URLSearchParams({
|
|
11350
11524
|
grant_type: "authorization_code",
|
|
11351
11525
|
code,
|
|
@@ -11379,7 +11553,7 @@ async function completeConsent(args) {
|
|
|
11379
11553
|
};
|
|
11380
11554
|
mkdirSync4(join22(accountDir, "secrets"), { recursive: true });
|
|
11381
11555
|
writeFileSync8(storePath(accountDir), JSON.stringify(store2, null, 2), { mode: 384 });
|
|
11382
|
-
const persisted = JSON.parse(
|
|
11556
|
+
const persisted = JSON.parse(readFileSync23(storePath(accountDir), "utf-8")).connections?.[realmId]?.refreshToken === body.refresh_token;
|
|
11383
11557
|
console.error(`${TAG24} op=token-exchange realmId=${realmId} persisted=${persisted}`);
|
|
11384
11558
|
return { ok: persisted, status: persisted ? 200 : 500, message: persisted ? `Connected company ${realmId}.` : "Failed to persist the connection.", stateValid: true };
|
|
11385
11559
|
} finally {
|
|
@@ -11410,7 +11584,7 @@ var quickbooks_default = app8;
|
|
|
11410
11584
|
|
|
11411
11585
|
// server/routes/onboarding.ts
|
|
11412
11586
|
import { spawn, spawnSync as spawnSync2, execFileSync as execFileSync3 } from "child_process";
|
|
11413
|
-
import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeFileSync10, writeSync, existsSync as existsSync17, readFileSync as
|
|
11587
|
+
import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeFileSync10, writeSync, existsSync as existsSync17, readFileSync as readFileSync25, unlinkSync as unlinkSync3, renameSync as renameSync7 } from "fs";
|
|
11414
11588
|
import { createHash as createHash4, randomUUID as randomUUID7 } from "crypto";
|
|
11415
11589
|
|
|
11416
11590
|
// app/lib/claude-spawn-env.ts
|
|
@@ -11548,7 +11722,7 @@ function readHostCredsBlob(service) {
|
|
|
11548
11722
|
}
|
|
11549
11723
|
|
|
11550
11724
|
// ../lib/admins-write/src/index.ts
|
|
11551
|
-
import { existsSync as existsSync16, readFileSync as
|
|
11725
|
+
import { existsSync as existsSync16, readFileSync as readFileSync24, writeFileSync as writeFileSync9, renameSync as renameSync6, mkdirSync as mkdirSync5, readdirSync as readdirSync15, statSync as statSync8, appendFileSync as appendFileSync2 } from "fs";
|
|
11552
11726
|
import { dirname as dirname7, join as join23 } from "path";
|
|
11553
11727
|
function id8(value) {
|
|
11554
11728
|
return value.slice(0, 8);
|
|
@@ -11591,7 +11765,7 @@ function writeAdminEntry(input) {
|
|
|
11591
11765
|
try {
|
|
11592
11766
|
let users = [];
|
|
11593
11767
|
if (existsSync16(input.usersFile)) {
|
|
11594
|
-
const raw =
|
|
11768
|
+
const raw = readFileSync24(input.usersFile, "utf-8").trim();
|
|
11595
11769
|
if (raw) {
|
|
11596
11770
|
const parsed = JSON.parse(raw);
|
|
11597
11771
|
if (!Array.isArray(parsed)) {
|
|
@@ -11626,7 +11800,7 @@ function writeAdminEntry(input) {
|
|
|
11626
11800
|
if (!existsSync16(accountJsonPath)) {
|
|
11627
11801
|
throw new Error(`account.json not found at ${accountJsonPath}`);
|
|
11628
11802
|
}
|
|
11629
|
-
const config = JSON.parse(
|
|
11803
|
+
const config = JSON.parse(readFileSync24(accountJsonPath, "utf-8"));
|
|
11630
11804
|
const admins = config.admins ?? [];
|
|
11631
11805
|
if (admins.some((a) => a.userId === input.userId)) {
|
|
11632
11806
|
result.accountJsonResult = "noop";
|
|
@@ -11648,7 +11822,7 @@ function computeAdminStoreDivergence(input) {
|
|
|
11648
11822
|
const usersUserIds = /* @__PURE__ */ new Set();
|
|
11649
11823
|
if (existsSync16(input.usersFile)) {
|
|
11650
11824
|
try {
|
|
11651
|
-
const raw =
|
|
11825
|
+
const raw = readFileSync24(input.usersFile, "utf-8").trim();
|
|
11652
11826
|
if (raw) {
|
|
11653
11827
|
const users = JSON.parse(raw);
|
|
11654
11828
|
for (const u of users) {
|
|
@@ -11663,7 +11837,7 @@ function computeAdminStoreDivergence(input) {
|
|
|
11663
11837
|
if (existsSync16(input.accountsDir)) {
|
|
11664
11838
|
let entries;
|
|
11665
11839
|
try {
|
|
11666
|
-
entries =
|
|
11840
|
+
entries = readdirSync15(input.accountsDir);
|
|
11667
11841
|
} catch (err) {
|
|
11668
11842
|
result.errors.push({ source: input.accountsDir, detail: err instanceof Error ? err.message : String(err) });
|
|
11669
11843
|
return result;
|
|
@@ -11680,7 +11854,7 @@ function computeAdminStoreDivergence(input) {
|
|
|
11680
11854
|
if (!existsSync16(accountJsonPath)) continue;
|
|
11681
11855
|
let admins = [];
|
|
11682
11856
|
try {
|
|
11683
|
-
const config = JSON.parse(
|
|
11857
|
+
const config = JSON.parse(readFileSync24(accountJsonPath, "utf-8"));
|
|
11684
11858
|
admins = config.admins ?? [];
|
|
11685
11859
|
} catch (err) {
|
|
11686
11860
|
result.errors.push({ source: accountJsonPath, detail: err instanceof Error ? err.message : String(err) });
|
|
@@ -11729,7 +11903,7 @@ function hashPin2(pin) {
|
|
|
11729
11903
|
}
|
|
11730
11904
|
function readUsersFile2() {
|
|
11731
11905
|
if (!existsSync17(USERS_FILE)) return null;
|
|
11732
|
-
const raw =
|
|
11906
|
+
const raw = readFileSync25(USERS_FILE, "utf-8").trim();
|
|
11733
11907
|
if (!raw) return [];
|
|
11734
11908
|
return JSON.parse(raw);
|
|
11735
11909
|
}
|
|
@@ -11939,7 +12113,7 @@ app9.post("/set-pin", async (c) => {
|
|
|
11939
12113
|
let installOwner = null;
|
|
11940
12114
|
if (existsSync17(INSTALL_OWNER_FILE)) {
|
|
11941
12115
|
try {
|
|
11942
|
-
const raw =
|
|
12116
|
+
const raw = readFileSync25(INSTALL_OWNER_FILE, "utf-8").trim();
|
|
11943
12117
|
if (raw.length > 0) installOwner = raw;
|
|
11944
12118
|
} catch (err) {
|
|
11945
12119
|
console.error(`[set-pin] install-owner-read-failed path=${INSTALL_OWNER_FILE} error=${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -12087,7 +12261,7 @@ app9.put("/set-pin", requireAdminSession, async (c) => {
|
|
|
12087
12261
|
let installOwner = null;
|
|
12088
12262
|
if (existsSync17(INSTALL_OWNER_FILE)) {
|
|
12089
12263
|
try {
|
|
12090
|
-
const raw =
|
|
12264
|
+
const raw = readFileSync25(INSTALL_OWNER_FILE, "utf-8").trim();
|
|
12091
12265
|
if (raw.length > 0) installOwner = raw;
|
|
12092
12266
|
} catch (err) {
|
|
12093
12267
|
console.error(`[set-pin] install-owner-read-failed path=${INSTALL_OWNER_FILE} error=${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -12489,7 +12663,7 @@ app12.get("/", requireAdminSession, async (c) => {
|
|
|
12489
12663
|
var accounts_default = app12;
|
|
12490
12664
|
|
|
12491
12665
|
// server/routes/admin/logs.ts
|
|
12492
|
-
import { existsSync as existsSync20, readdirSync as
|
|
12666
|
+
import { existsSync as existsSync20, readdirSync as readdirSync16, readFileSync as readFileSync26, statSync as statSync10 } from "fs";
|
|
12493
12667
|
import { resolve as resolve16, basename as basename7 } from "path";
|
|
12494
12668
|
|
|
12495
12669
|
// app/lib/logs-read-resolve.ts
|
|
@@ -12528,7 +12702,7 @@ app13.get("/", async (c) => {
|
|
|
12528
12702
|
const filePath = resolve16(dir, safe);
|
|
12529
12703
|
searched.push(filePath);
|
|
12530
12704
|
try {
|
|
12531
|
-
const buffer =
|
|
12705
|
+
const buffer = readFileSync26(filePath);
|
|
12532
12706
|
const onDiskBytes = statSync10(filePath).size;
|
|
12533
12707
|
const headers = {
|
|
12534
12708
|
"Content-Type": "text/plain; charset=utf-8",
|
|
@@ -12593,7 +12767,7 @@ app13.get("/", async (c) => {
|
|
|
12593
12767
|
console.info(`[admin/logs] resolved cacheKey=${cacheKeySlice} sessionId=${sessionIdSlice} via=${primaryId === cacheKey ? "cacheKey" : primaryId === sessionKeyFromConv ? "reverse-lookup" : "sessionId-fallback"}`);
|
|
12594
12768
|
try {
|
|
12595
12769
|
const filename = basename7(hit.path);
|
|
12596
|
-
const buffer =
|
|
12770
|
+
const buffer = readFileSync26(hit.path);
|
|
12597
12771
|
const onDiskBytes = statSync10(hit.path).size;
|
|
12598
12772
|
const headers = {
|
|
12599
12773
|
"Content-Type": "text/plain; charset=utf-8",
|
|
@@ -12631,7 +12805,7 @@ app13.get("/", async (c) => {
|
|
|
12631
12805
|
if (!existsSync20(dir)) continue;
|
|
12632
12806
|
let files;
|
|
12633
12807
|
try {
|
|
12634
|
-
files =
|
|
12808
|
+
files = readdirSync16(dir).filter((f) => f.endsWith(".log"));
|
|
12635
12809
|
} catch (err) {
|
|
12636
12810
|
const reason = err instanceof Error ? err.message : String(err);
|
|
12637
12811
|
console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
|
|
@@ -12640,7 +12814,7 @@ app13.get("/", async (c) => {
|
|
|
12640
12814
|
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync10(resolve16(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
|
|
12641
12815
|
seen.add(name);
|
|
12642
12816
|
try {
|
|
12643
|
-
const content =
|
|
12817
|
+
const content = readFileSync26(resolve16(dir, name));
|
|
12644
12818
|
const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
|
|
12645
12819
|
logs[name] = tail.trim() || "(empty)";
|
|
12646
12820
|
} catch (err) {
|
|
@@ -12683,7 +12857,7 @@ import { readFile as readFile2, readdir } from "fs/promises";
|
|
|
12683
12857
|
import { existsSync as existsSync21 } from "fs";
|
|
12684
12858
|
import { resolve as resolve17 } from "path";
|
|
12685
12859
|
var app15 = new Hono();
|
|
12686
|
-
var
|
|
12860
|
+
var ATTACHMENT_ID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
12687
12861
|
function uploadsDirFor2(accountId, attachmentId) {
|
|
12688
12862
|
return resolve17(DATA_ROOT, "accounts", accountId, "uploads", attachmentId);
|
|
12689
12863
|
}
|
|
@@ -12697,7 +12871,7 @@ app15.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
12697
12871
|
console.log(`[admin-attachment] op=miss attachmentId=${shortId2} session=${shortSession} status=401 reason=no-account`);
|
|
12698
12872
|
return new Response("Unauthorized", { status: 401 });
|
|
12699
12873
|
}
|
|
12700
|
-
if (!
|
|
12874
|
+
if (!ATTACHMENT_ID_RE3.test(attachmentId)) {
|
|
12701
12875
|
console.log(`[admin-attachment] op=miss attachmentId=${shortId2} session=${shortSession} status=404 reason=bad-id`);
|
|
12702
12876
|
return new Response("Not found", { status: 404 });
|
|
12703
12877
|
}
|
|
@@ -12739,10 +12913,16 @@ app15.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
12739
12913
|
}
|
|
12740
12914
|
const filePath = resolve17(dir, dataFile);
|
|
12741
12915
|
const buffer = await readFile2(filePath);
|
|
12916
|
+
const inlineSafe = isInlineSafeMime(meta.mimeType);
|
|
12917
|
+
const safeName = meta.filename.replace(/["\\\r\n]/g, "_");
|
|
12918
|
+
if (!inlineSafe) {
|
|
12919
|
+
console.log(`[admin-attachment] op=served attachmentId=${shortId2} disposition=attachment reason=non-preview-mime mime=${meta.mimeType}`);
|
|
12920
|
+
}
|
|
12742
12921
|
return new Response(new Uint8Array(buffer), {
|
|
12743
12922
|
headers: {
|
|
12744
12923
|
"Content-Type": meta.mimeType,
|
|
12745
|
-
"Content-Disposition":
|
|
12924
|
+
"Content-Disposition": `${inlineSafe ? "inline" : "attachment"}; filename="${safeName}"`,
|
|
12925
|
+
"X-Content-Type-Options": "nosniff",
|
|
12746
12926
|
"Cache-Control": "private, max-age=3600"
|
|
12747
12927
|
}
|
|
12748
12928
|
});
|
|
@@ -12751,7 +12931,7 @@ var attachment_default = app15;
|
|
|
12751
12931
|
|
|
12752
12932
|
// server/routes/admin/agents.ts
|
|
12753
12933
|
import { resolve as resolve18 } from "path";
|
|
12754
|
-
import { readdirSync as
|
|
12934
|
+
import { readdirSync as readdirSync17, readFileSync as readFileSync27, existsSync as existsSync22, rmSync as rmSync2 } from "fs";
|
|
12755
12935
|
var app16 = new Hono();
|
|
12756
12936
|
app16.get("/", (c) => {
|
|
12757
12937
|
const account = resolveAccount();
|
|
@@ -12760,14 +12940,14 @@ app16.get("/", (c) => {
|
|
|
12760
12940
|
if (!existsSync22(agentsDir)) return c.json({ agents: [] });
|
|
12761
12941
|
const agents = [];
|
|
12762
12942
|
try {
|
|
12763
|
-
const entries =
|
|
12943
|
+
const entries = readdirSync17(agentsDir, { withFileTypes: true });
|
|
12764
12944
|
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
12765
12945
|
if (!entry.isDirectory()) continue;
|
|
12766
12946
|
if (entry.name === "admin") continue;
|
|
12767
12947
|
const configPath2 = resolve18(agentsDir, entry.name, "config.json");
|
|
12768
12948
|
if (!existsSync22(configPath2)) continue;
|
|
12769
12949
|
try {
|
|
12770
|
-
const config = JSON.parse(
|
|
12950
|
+
const config = JSON.parse(readFileSync27(configPath2, "utf-8"));
|
|
12771
12951
|
agents.push({
|
|
12772
12952
|
slug: entry.name,
|
|
12773
12953
|
displayName: config.displayName ?? entry.name,
|
|
@@ -13526,7 +13706,7 @@ app17.put("/:id/label", requireAdminSession, async (c) => {
|
|
|
13526
13706
|
var sessions_default = app17;
|
|
13527
13707
|
|
|
13528
13708
|
// app/lib/claude-agent/spawn-context.ts
|
|
13529
|
-
import { existsSync as existsSync24, readFileSync as
|
|
13709
|
+
import { existsSync as existsSync24, readFileSync as readFileSync28, readdirSync as readdirSync18, statSync as statSync11 } from "fs";
|
|
13530
13710
|
import { dirname as dirname9, resolve as resolve19, join as join27 } from "path";
|
|
13531
13711
|
async function resolveOwnerProfileBlock(accountId, userId) {
|
|
13532
13712
|
if (!userId) return { ok: false, reason: "missing-user-id" };
|
|
@@ -13575,7 +13755,7 @@ function extractPluginToolDescriptions(pluginDir) {
|
|
|
13575
13755
|
for (const path2 of candidates) {
|
|
13576
13756
|
if (!existsSync24(path2)) continue;
|
|
13577
13757
|
try {
|
|
13578
|
-
raw =
|
|
13758
|
+
raw = readFileSync28(path2, "utf-8");
|
|
13579
13759
|
break;
|
|
13580
13760
|
} catch {
|
|
13581
13761
|
}
|
|
@@ -13626,7 +13806,7 @@ function listPluginDirs() {
|
|
|
13626
13806
|
const out = /* @__PURE__ */ new Map();
|
|
13627
13807
|
const platformPlugins = resolve19(PLATFORM_ROOT, "plugins");
|
|
13628
13808
|
if (existsSync24(platformPlugins)) {
|
|
13629
|
-
for (const name of
|
|
13809
|
+
for (const name of readdirSync18(platformPlugins)) {
|
|
13630
13810
|
const dir = join27(platformPlugins, name);
|
|
13631
13811
|
try {
|
|
13632
13812
|
if (statSync11(dir).isDirectory()) out.set(name, dir);
|
|
@@ -13636,11 +13816,11 @@ function listPluginDirs() {
|
|
|
13636
13816
|
}
|
|
13637
13817
|
const premiumRoot = resolve19(dirname9(PLATFORM_ROOT), "premium-plugins");
|
|
13638
13818
|
if (existsSync24(premiumRoot)) {
|
|
13639
|
-
for (const bundle of
|
|
13819
|
+
for (const bundle of readdirSync18(premiumRoot)) {
|
|
13640
13820
|
const bundlePlugins = join27(premiumRoot, bundle, "plugins");
|
|
13641
13821
|
if (!existsSync24(bundlePlugins)) continue;
|
|
13642
13822
|
try {
|
|
13643
|
-
for (const name of
|
|
13823
|
+
for (const name of readdirSync18(bundlePlugins)) {
|
|
13644
13824
|
const dir = join27(bundlePlugins, name);
|
|
13645
13825
|
try {
|
|
13646
13826
|
if (statSync11(dir).isDirectory()) out.set(name, dir);
|
|
@@ -13657,7 +13837,7 @@ function readEnabledPlugins(accountId) {
|
|
|
13657
13837
|
const accountFile = resolve19(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
13658
13838
|
if (!existsSync24(accountFile)) return /* @__PURE__ */ new Set();
|
|
13659
13839
|
try {
|
|
13660
|
-
const parsed = JSON.parse(
|
|
13840
|
+
const parsed = JSON.parse(readFileSync28(accountFile, "utf-8"));
|
|
13661
13841
|
return new Set(
|
|
13662
13842
|
Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
|
|
13663
13843
|
);
|
|
@@ -13669,7 +13849,7 @@ function readFrontmatter(path2) {
|
|
|
13669
13849
|
if (!existsSync24(path2)) return null;
|
|
13670
13850
|
let raw;
|
|
13671
13851
|
try {
|
|
13672
|
-
raw =
|
|
13852
|
+
raw = readFileSync28(path2, "utf-8");
|
|
13673
13853
|
} catch {
|
|
13674
13854
|
return null;
|
|
13675
13855
|
}
|
|
@@ -13731,7 +13911,7 @@ function computeSpecialistDomains(accountId) {
|
|
|
13731
13911
|
if (!existsSync24(specialistsDir)) return [];
|
|
13732
13912
|
let entries;
|
|
13733
13913
|
try {
|
|
13734
|
-
entries =
|
|
13914
|
+
entries = readdirSync18(specialistsDir);
|
|
13735
13915
|
} catch {
|
|
13736
13916
|
return [];
|
|
13737
13917
|
}
|
|
@@ -13777,7 +13957,7 @@ function computeDormantPlugins(accountId) {
|
|
|
13777
13957
|
if (!existsSync24(accountFile)) return [];
|
|
13778
13958
|
let enabled;
|
|
13779
13959
|
try {
|
|
13780
|
-
const raw =
|
|
13960
|
+
const raw = readFileSync28(accountFile, "utf-8");
|
|
13781
13961
|
const parsed = JSON.parse(raw);
|
|
13782
13962
|
enabled = new Set(
|
|
13783
13963
|
Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
|
|
@@ -13792,7 +13972,7 @@ function computeDormantPlugins(accountId) {
|
|
|
13792
13972
|
if (!existsSync24(pluginsDir)) return [];
|
|
13793
13973
|
let entries;
|
|
13794
13974
|
try {
|
|
13795
|
-
entries =
|
|
13975
|
+
entries = readdirSync18(pluginsDir);
|
|
13796
13976
|
} catch {
|
|
13797
13977
|
return [];
|
|
13798
13978
|
}
|
|
@@ -13803,7 +13983,7 @@ function computeDormantPlugins(accountId) {
|
|
|
13803
13983
|
if (!existsSync24(manifestPath)) continue;
|
|
13804
13984
|
let manifest;
|
|
13805
13985
|
try {
|
|
13806
|
-
manifest =
|
|
13986
|
+
manifest = readFileSync28(manifestPath, "utf-8");
|
|
13807
13987
|
} catch {
|
|
13808
13988
|
continue;
|
|
13809
13989
|
}
|
|
@@ -13817,13 +13997,13 @@ function computeDormantPlugins(accountId) {
|
|
|
13817
13997
|
}
|
|
13818
13998
|
|
|
13819
13999
|
// server/routes/admin/claude-sessions.ts
|
|
13820
|
-
import { existsSync as existsSync25, readFileSync as
|
|
14000
|
+
import { existsSync as existsSync25, readFileSync as readFileSync29 } from "fs";
|
|
13821
14001
|
import { resolve as resolve20 } from "path";
|
|
13822
14002
|
function readTunnelState(brandConfigDir) {
|
|
13823
14003
|
const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
|
|
13824
14004
|
if (!existsSync25(statePath)) return null;
|
|
13825
14005
|
try {
|
|
13826
|
-
const parsed = JSON.parse(
|
|
14006
|
+
const parsed = JSON.parse(readFileSync29(statePath, "utf-8"));
|
|
13827
14007
|
const tunnelId = typeof parsed.tunnelId === "string" ? parsed.tunnelId : null;
|
|
13828
14008
|
const tunnelName = typeof parsed.tunnelName === "string" ? parsed.tunnelName : null;
|
|
13829
14009
|
const domain = typeof parsed.domain === "string" ? parsed.domain : null;
|
|
@@ -13837,7 +14017,7 @@ function resolveTunnelUrl() {
|
|
|
13837
14017
|
const platformRoot3 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve20(process.cwd(), "..");
|
|
13838
14018
|
let brand;
|
|
13839
14019
|
try {
|
|
13840
|
-
brand = JSON.parse(
|
|
14020
|
+
brand = JSON.parse(readFileSync29(resolve20(platformRoot3, "config", "brand.json"), "utf-8"));
|
|
13841
14021
|
} catch {
|
|
13842
14022
|
return null;
|
|
13843
14023
|
}
|
|
@@ -14080,7 +14260,7 @@ var events_default = app20;
|
|
|
14080
14260
|
|
|
14081
14261
|
// server/routes/admin/files.ts
|
|
14082
14262
|
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as existsSync26 } from "fs";
|
|
14083
|
-
import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, unlink as unlink2, rename } from "fs/promises";
|
|
14263
|
+
import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, unlink as unlink2, rename, rmdir } from "fs/promises";
|
|
14084
14264
|
import { realpathSync as realpathSync5 } from "fs";
|
|
14085
14265
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
14086
14266
|
import { basename as basename9, dirname as dirname10, join as join29, relative as relative4, resolve as resolve22, sep as sep6 } from "path";
|
|
@@ -14958,19 +15138,55 @@ async function readAccountNames() {
|
|
|
14958
15138
|
}
|
|
14959
15139
|
return map;
|
|
14960
15140
|
}
|
|
15141
|
+
async function servableFilesIn(dirAbs, uuid) {
|
|
15142
|
+
const metaName = `${uuid}.meta.json`;
|
|
15143
|
+
let dirents;
|
|
15144
|
+
try {
|
|
15145
|
+
dirents = await readdir3(dirAbs, { withFileTypes: true });
|
|
15146
|
+
} catch {
|
|
15147
|
+
return [];
|
|
15148
|
+
}
|
|
15149
|
+
const out = [];
|
|
15150
|
+
for (const d of dirents) {
|
|
15151
|
+
if (!d.isFile()) continue;
|
|
15152
|
+
if (d.name === metaName) continue;
|
|
15153
|
+
if (d.name.endsWith(EXTRACTED_TEXT_SUFFIX)) continue;
|
|
15154
|
+
out.push(d.name);
|
|
15155
|
+
}
|
|
15156
|
+
return out;
|
|
15157
|
+
}
|
|
14961
15158
|
async function enrich(absolute, entry, accountNames) {
|
|
14962
15159
|
if (entry.kind === "directory" && UUID_RE3.test(entry.name)) {
|
|
14963
|
-
const
|
|
15160
|
+
const dirAbs = join29(absolute, entry.name);
|
|
15161
|
+
const meta = await readMeta(dirAbs, entry.name);
|
|
14964
15162
|
if (meta?.filename) {
|
|
15163
|
+
const servable = await servableFilesIn(dirAbs, entry.name);
|
|
15164
|
+
if (servable.length === 1) {
|
|
15165
|
+
const innerName = servable[0];
|
|
15166
|
+
let size = null;
|
|
15167
|
+
let modifiedAt = entry.modifiedAt;
|
|
15168
|
+
try {
|
|
15169
|
+
const st = await stat4(join29(dirAbs, innerName));
|
|
15170
|
+
size = st.size;
|
|
15171
|
+
modifiedAt = st.mtime.toISOString();
|
|
15172
|
+
} catch {
|
|
15173
|
+
}
|
|
15174
|
+
entry.kind = "file";
|
|
15175
|
+
entry.displayName = meta.filename;
|
|
15176
|
+
entry.mimeType = meta.mimeType;
|
|
15177
|
+
entry.sizeBytes = size;
|
|
15178
|
+
entry.modifiedAt = modifiedAt;
|
|
15179
|
+
entry.entryPath = `${entry.name}/${innerName}`;
|
|
15180
|
+
return "flattened";
|
|
15181
|
+
}
|
|
14965
15182
|
entry.displayName = meta.filename;
|
|
14966
|
-
|
|
14967
|
-
return;
|
|
15183
|
+
return "kept-as-dir";
|
|
14968
15184
|
}
|
|
14969
15185
|
const accountName = accountNames.get(entry.name);
|
|
14970
15186
|
if (accountName) {
|
|
14971
15187
|
entry.displayName = accountName;
|
|
14972
15188
|
}
|
|
14973
|
-
return;
|
|
15189
|
+
return null;
|
|
14974
15190
|
}
|
|
14975
15191
|
if (entry.kind === "file") {
|
|
14976
15192
|
const dot = entry.name.lastIndexOf(".");
|
|
@@ -14983,6 +15199,7 @@ async function enrich(absolute, entry, accountNames) {
|
|
|
14983
15199
|
}
|
|
14984
15200
|
}
|
|
14985
15201
|
}
|
|
15202
|
+
return null;
|
|
14986
15203
|
}
|
|
14987
15204
|
function buildDisplayPath(relPath, accountNames) {
|
|
14988
15205
|
if (relPath === "." || relPath === "") return [];
|
|
@@ -15138,8 +15355,18 @@ app21.get("/", requireAdminSession, async (c) => {
|
|
|
15138
15355
|
}
|
|
15139
15356
|
}
|
|
15140
15357
|
const accountNames = await readAccountNames();
|
|
15141
|
-
await Promise.all(entries.map((e) => enrich(absolute, e, accountNames)));
|
|
15358
|
+
const classes = await Promise.all(entries.map((e) => enrich(absolute, e, accountNames)));
|
|
15142
15359
|
sortDirEntries(entries);
|
|
15360
|
+
let flattened = 0;
|
|
15361
|
+
let keptAsDir = 0;
|
|
15362
|
+
for (const cls of classes) {
|
|
15363
|
+
if (cls === "flattened") flattened++;
|
|
15364
|
+
else if (cls === "kept-as-dir") keptAsDir++;
|
|
15365
|
+
}
|
|
15366
|
+
const containers = flattened + keptAsDir;
|
|
15367
|
+
if (containers > 0) {
|
|
15368
|
+
console.error(`[data] op=uploads-flatten containers=${containers} flattened=${flattened} kept-as-dir=${keptAsDir}`);
|
|
15369
|
+
}
|
|
15143
15370
|
const displayPath = buildDisplayPath(relPath, accountNames);
|
|
15144
15371
|
console.error(`[data] file-list path="${relPath}" entries=${entries.length}`);
|
|
15145
15372
|
return c.json({ path: relPath, displayPath, entries });
|
|
@@ -15228,8 +15455,16 @@ app21.get("/download", requireAdminSession, async (c) => {
|
|
|
15228
15455
|
});
|
|
15229
15456
|
}
|
|
15230
15457
|
console.error(`[data] file-download root="${root}" path="${relPath}" size=${info.size}`);
|
|
15231
|
-
|
|
15232
|
-
|
|
15458
|
+
let downloadName = filename;
|
|
15459
|
+
if (root === "data") {
|
|
15460
|
+
const parsed = parseAttachmentPath(relPath);
|
|
15461
|
+
if (parsed) {
|
|
15462
|
+
const meta = await readMeta(dirname10(absolute), parsed.attachmentId);
|
|
15463
|
+
if (meta?.filename) downloadName = meta.filename;
|
|
15464
|
+
}
|
|
15465
|
+
}
|
|
15466
|
+
const safeQuotedName = downloadName.replace(/[\r\n"\\]/g, "_");
|
|
15467
|
+
const encodedName = encodeURIComponent(downloadName);
|
|
15233
15468
|
return new Response(webStream, {
|
|
15234
15469
|
status: 200,
|
|
15235
15470
|
headers: {
|
|
@@ -15324,7 +15559,13 @@ app21.get("/download-zip", requireAdminSession, async (c) => {
|
|
|
15324
15559
|
if (over) return over;
|
|
15325
15560
|
}
|
|
15326
15561
|
} else if (info.isFile()) {
|
|
15327
|
-
|
|
15562
|
+
let member = basename9(absolute);
|
|
15563
|
+
const parsed = parseAttachmentPath(relPath);
|
|
15564
|
+
if (parsed) {
|
|
15565
|
+
const meta = await readMeta(dirname10(absolute), parsed.attachmentId);
|
|
15566
|
+
if (meta?.filename) member = meta.filename;
|
|
15567
|
+
}
|
|
15568
|
+
const over = await addFile(absolute, info.size, member);
|
|
15328
15569
|
if (over) return over;
|
|
15329
15570
|
} else {
|
|
15330
15571
|
return c.json({ error: "Path is not a file or directory" }, 400);
|
|
@@ -15744,7 +15985,9 @@ app21.delete("/", requireAdminSession, async (c) => {
|
|
|
15744
15985
|
}
|
|
15745
15986
|
const dot = base.lastIndexOf(".");
|
|
15746
15987
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
15747
|
-
const
|
|
15988
|
+
const containerDir = dirname10(absolute);
|
|
15989
|
+
const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join29(containerDir, `${stem}.meta.json`) : null;
|
|
15990
|
+
const isAttachmentContainer = UUID_RE3.test(stem) && basename9(containerDir) === stem;
|
|
15748
15991
|
await unlink2(absolute);
|
|
15749
15992
|
if (sidecarPath) {
|
|
15750
15993
|
try {
|
|
@@ -15752,6 +15995,12 @@ app21.delete("/", requireAdminSession, async (c) => {
|
|
|
15752
15995
|
} catch {
|
|
15753
15996
|
}
|
|
15754
15997
|
}
|
|
15998
|
+
if (isAttachmentContainer) {
|
|
15999
|
+
await unlink2(join29(containerDir, `${stem}${EXTRACTED_TEXT_SUFFIX}`)).catch(() => {
|
|
16000
|
+
});
|
|
16001
|
+
await rmdir(containerDir).catch(() => {
|
|
16002
|
+
});
|
|
16003
|
+
}
|
|
15755
16004
|
console.error(`[data] file-delete path="${relPath}" bytes=${info.size}`);
|
|
15756
16005
|
try {
|
|
15757
16006
|
await dropFileIndex(accountId, relPath);
|
|
@@ -18708,14 +18957,14 @@ app36.get("/", async (c) => {
|
|
|
18708
18957
|
var system_stats_default = app36;
|
|
18709
18958
|
|
|
18710
18959
|
// server/routes/admin/health.ts
|
|
18711
|
-
import { existsSync as existsSync28, readFileSync as
|
|
18960
|
+
import { existsSync as existsSync28, readFileSync as readFileSync30 } from "fs";
|
|
18712
18961
|
import { resolve as resolve24, join as join30 } from "path";
|
|
18713
18962
|
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve24(process.cwd(), "..");
|
|
18714
18963
|
var brandHostname = "maxy";
|
|
18715
18964
|
var brandJsonPath = join30(PLATFORM_ROOT6, "config", "brand.json");
|
|
18716
18965
|
if (existsSync28(brandJsonPath)) {
|
|
18717
18966
|
try {
|
|
18718
|
-
const brand = JSON.parse(
|
|
18967
|
+
const brand = JSON.parse(readFileSync30(brandJsonPath, "utf-8"));
|
|
18719
18968
|
if (brand.hostname) brandHostname = brand.hostname;
|
|
18720
18969
|
} catch {
|
|
18721
18970
|
}
|
|
@@ -18725,7 +18974,7 @@ var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
|
18725
18974
|
var PROBE_TIMEOUT_MS = 1e3;
|
|
18726
18975
|
function readVersion() {
|
|
18727
18976
|
if (!existsSync28(VERSION_FILE)) return "unknown";
|
|
18728
|
-
return
|
|
18977
|
+
return readFileSync30(VERSION_FILE, "utf-8").trim() || "unknown";
|
|
18729
18978
|
}
|
|
18730
18979
|
async function probeConversationDb() {
|
|
18731
18980
|
let session;
|
|
@@ -19601,7 +19850,7 @@ function countVEvents(ics) {
|
|
|
19601
19850
|
}
|
|
19602
19851
|
|
|
19603
19852
|
// server/lib/calendar-availability.ts
|
|
19604
|
-
import { readFileSync as
|
|
19853
|
+
import { readFileSync as readFileSync31 } from "fs";
|
|
19605
19854
|
import { join as join31 } from "path";
|
|
19606
19855
|
var AVAILABILITY_FILENAME = "calendar-availability.json";
|
|
19607
19856
|
var REQUIRED_KEYS = [
|
|
@@ -19614,7 +19863,7 @@ function readAvailabilityConfig(accountDir) {
|
|
|
19614
19863
|
const path2 = join31(accountDir, AVAILABILITY_FILENAME);
|
|
19615
19864
|
let raw;
|
|
19616
19865
|
try {
|
|
19617
|
-
raw =
|
|
19866
|
+
raw = readFileSync31(path2, "utf-8");
|
|
19618
19867
|
} catch {
|
|
19619
19868
|
throw new Error(`availability not configured: ${path2} not found`);
|
|
19620
19869
|
}
|
|
@@ -20591,7 +20840,7 @@ app54.route("/request-magic-link", request_magic_link_default);
|
|
|
20591
20840
|
var access_default = app54;
|
|
20592
20841
|
|
|
20593
20842
|
// server/routes/sites.ts
|
|
20594
|
-
import { existsSync as existsSync30, readFileSync as
|
|
20843
|
+
import { existsSync as existsSync30, readFileSync as readFileSync32, realpathSync as realpathSync6, statSync as statSync12 } from "fs";
|
|
20595
20844
|
import { resolve as resolve26 } from "path";
|
|
20596
20845
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
20597
20846
|
var MIME = {
|
|
@@ -20695,7 +20944,7 @@ app55.get("/:rel{.*}", (c) => {
|
|
|
20695
20944
|
}
|
|
20696
20945
|
let body;
|
|
20697
20946
|
try {
|
|
20698
|
-
body =
|
|
20947
|
+
body = readFileSync32(realPath);
|
|
20699
20948
|
} catch (err) {
|
|
20700
20949
|
const code = err?.code;
|
|
20701
20950
|
if (code === "EISDIR") {
|
|
@@ -20731,7 +20980,7 @@ var sites_default = app55;
|
|
|
20731
20980
|
|
|
20732
20981
|
// app/lib/visitor-token.ts
|
|
20733
20982
|
import { createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
20734
|
-
import { mkdirSync as mkdirSync7, readFileSync as
|
|
20983
|
+
import { mkdirSync as mkdirSync7, readFileSync as readFileSync33, writeFileSync as writeFileSync11 } from "fs";
|
|
20735
20984
|
import { dirname as dirname11 } from "path";
|
|
20736
20985
|
var TOKEN_PREFIX = "v1.";
|
|
20737
20986
|
var SECRET_BYTES = 32;
|
|
@@ -20740,7 +20989,7 @@ var cachedSecret = null;
|
|
|
20740
20989
|
function getSecret() {
|
|
20741
20990
|
if (cachedSecret) return cachedSecret;
|
|
20742
20991
|
try {
|
|
20743
|
-
const hex2 =
|
|
20992
|
+
const hex2 = readFileSync33(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
20744
20993
|
if (hex2.length === SECRET_BYTES * 2) {
|
|
20745
20994
|
cachedSecret = Buffer.from(hex2, "hex");
|
|
20746
20995
|
return cachedSecret;
|
|
@@ -20754,7 +21003,7 @@ function getSecret() {
|
|
|
20754
21003
|
console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
|
|
20755
21004
|
} catch {
|
|
20756
21005
|
}
|
|
20757
|
-
const hex =
|
|
21006
|
+
const hex = readFileSync33(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
20758
21007
|
cachedSecret = Buffer.from(hex, "hex");
|
|
20759
21008
|
return cachedSecret;
|
|
20760
21009
|
}
|
|
@@ -20807,7 +21056,7 @@ var VISITOR_COOKIE_NAME = "mxy_v";
|
|
|
20807
21056
|
var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
|
|
20808
21057
|
|
|
20809
21058
|
// app/lib/brand-config.ts
|
|
20810
|
-
import { existsSync as existsSync31, readFileSync as
|
|
21059
|
+
import { existsSync as existsSync31, readFileSync as readFileSync34 } from "fs";
|
|
20811
21060
|
import { join as join33 } from "path";
|
|
20812
21061
|
var cached = null;
|
|
20813
21062
|
var cachedAttempted = false;
|
|
@@ -20819,7 +21068,7 @@ function readBrandConfig() {
|
|
|
20819
21068
|
const brandPath = join33(platformRoot3, "config", "brand.json");
|
|
20820
21069
|
if (!existsSync31(brandPath)) return null;
|
|
20821
21070
|
try {
|
|
20822
|
-
cached = JSON.parse(
|
|
21071
|
+
cached = JSON.parse(readFileSync34(brandPath, "utf-8"));
|
|
20823
21072
|
return cached;
|
|
20824
21073
|
} catch {
|
|
20825
21074
|
return null;
|
|
@@ -24554,7 +24803,7 @@ function broadcastAdminShutdown(reason) {
|
|
|
24554
24803
|
|
|
24555
24804
|
// ../lib/entitlement/src/index.ts
|
|
24556
24805
|
import { createPublicKey, createHash as createHash6, verify as cryptoVerify } from "crypto";
|
|
24557
|
-
import { existsSync as existsSync34, readFileSync as
|
|
24806
|
+
import { existsSync as existsSync34, readFileSync as readFileSync35, statSync as statSync13 } from "fs";
|
|
24558
24807
|
import { resolve as resolve32 } from "path";
|
|
24559
24808
|
|
|
24560
24809
|
// ../lib/entitlement/src/canonicalize.ts
|
|
@@ -24618,7 +24867,7 @@ function resolveEntitlement(brand, account) {
|
|
|
24618
24867
|
function verifyAndResolve(brand, entitlementPath, account) {
|
|
24619
24868
|
let pubkeyPem;
|
|
24620
24869
|
try {
|
|
24621
|
-
pubkeyPem =
|
|
24870
|
+
pubkeyPem = readFileSync35(pubkeyPath(brand), "utf-8");
|
|
24622
24871
|
} catch (err) {
|
|
24623
24872
|
return logResolved(anonymousFallback("pubkey-missing"), {
|
|
24624
24873
|
reason: "pubkey-missing"
|
|
@@ -24632,7 +24881,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
|
|
|
24632
24881
|
}
|
|
24633
24882
|
let envelope;
|
|
24634
24883
|
try {
|
|
24635
|
-
envelope = JSON.parse(
|
|
24884
|
+
envelope = JSON.parse(readFileSync35(entitlementPath, "utf-8"));
|
|
24636
24885
|
} catch {
|
|
24637
24886
|
return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
|
|
24638
24887
|
}
|
|
@@ -24800,7 +25049,7 @@ if (BRAND_JSON_PATH && !existsSync35(BRAND_JSON_PATH)) {
|
|
|
24800
25049
|
}
|
|
24801
25050
|
if (BRAND_JSON_PATH && existsSync35(BRAND_JSON_PATH)) {
|
|
24802
25051
|
try {
|
|
24803
|
-
const parsed = JSON.parse(
|
|
25052
|
+
const parsed = JSON.parse(readFileSync36(BRAND_JSON_PATH, "utf-8"));
|
|
24804
25053
|
BRAND = { ...BRAND, ...parsed };
|
|
24805
25054
|
} catch (err) {
|
|
24806
25055
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -24836,7 +25085,7 @@ var ALIAS_DOMAINS_PATH = join36(homedir4(), BRAND.configDir, "alias-domains.json
|
|
|
24836
25085
|
function loadAliasDomains() {
|
|
24837
25086
|
try {
|
|
24838
25087
|
if (!existsSync35(ALIAS_DOMAINS_PATH)) return null;
|
|
24839
|
-
const parsed = JSON.parse(
|
|
25088
|
+
const parsed = JSON.parse(readFileSync36(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
24840
25089
|
if (!Array.isArray(parsed)) {
|
|
24841
25090
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
24842
25091
|
return null;
|
|
@@ -25525,7 +25774,7 @@ app61.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
25525
25774
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
25526
25775
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
25527
25776
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
25528
|
-
const body =
|
|
25777
|
+
const body = readFileSync36(filePath);
|
|
25529
25778
|
return c.body(body, 200, {
|
|
25530
25779
|
"Content-Type": contentType,
|
|
25531
25780
|
"Cache-Control": "public, max-age=3600"
|
|
@@ -25555,7 +25804,7 @@ app61.get("/generated/:filename", (c) => {
|
|
|
25555
25804
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
25556
25805
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
25557
25806
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
25558
|
-
const body =
|
|
25807
|
+
const body = readFileSync36(filePath);
|
|
25559
25808
|
return c.body(body, 200, {
|
|
25560
25809
|
"Content-Type": contentType,
|
|
25561
25810
|
"Cache-Control": "public, max-age=86400"
|
|
@@ -25570,7 +25819,7 @@ var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
|
25570
25819
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
25571
25820
|
if (BRAND_JSON_PATH && existsSync35(BRAND_JSON_PATH)) {
|
|
25572
25821
|
try {
|
|
25573
|
-
const fullBrand = JSON.parse(
|
|
25822
|
+
const fullBrand = JSON.parse(readFileSync36(BRAND_JSON_PATH, "utf-8"));
|
|
25574
25823
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
25575
25824
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
25576
25825
|
} catch {
|
|
@@ -25601,7 +25850,7 @@ var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskabl
|
|
|
25601
25850
|
);
|
|
25602
25851
|
var SW_SOURCE = (() => {
|
|
25603
25852
|
try {
|
|
25604
|
-
return
|
|
25853
|
+
return readFileSync36(resolve33(process.cwd(), "public", "sw.js"), "utf-8");
|
|
25605
25854
|
} catch {
|
|
25606
25855
|
return null;
|
|
25607
25856
|
}
|
|
@@ -25611,7 +25860,7 @@ function readInstalledVersion() {
|
|
|
25611
25860
|
if (!PLATFORM_ROOT8) return "unknown";
|
|
25612
25861
|
const versionFile = join36(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
|
|
25613
25862
|
if (!existsSync35(versionFile)) return "unknown";
|
|
25614
|
-
const content =
|
|
25863
|
+
const content = readFileSync36(versionFile, "utf-8").trim();
|
|
25615
25864
|
return content || "unknown";
|
|
25616
25865
|
} catch {
|
|
25617
25866
|
return "unknown";
|
|
@@ -25652,7 +25901,7 @@ var clientErrorReporterScript = `<script>
|
|
|
25652
25901
|
function cachedHtml(file) {
|
|
25653
25902
|
let html = htmlCache.get(file);
|
|
25654
25903
|
if (!html) {
|
|
25655
|
-
html =
|
|
25904
|
+
html = readFileSync36(resolve33(process.cwd(), "public", file), "utf-8");
|
|
25656
25905
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
25657
25906
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
25658
25907
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -25675,7 +25924,7 @@ function loadBrandingCache(agentSlug) {
|
|
|
25675
25924
|
if (!accountId) return null;
|
|
25676
25925
|
const cachePath = join36(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
25677
25926
|
if (!existsSync35(cachePath)) return null;
|
|
25678
|
-
return JSON.parse(
|
|
25927
|
+
return JSON.parse(readFileSync36(cachePath, "utf-8"));
|
|
25679
25928
|
} catch {
|
|
25680
25929
|
return null;
|
|
25681
25930
|
}
|
|
@@ -25770,7 +26019,7 @@ app61.use("/vnc-popout.html", logViewerFetch);
|
|
|
25770
26019
|
app61.get("/vnc-popout.html", (c) => {
|
|
25771
26020
|
let html = htmlCache.get("vnc-popout.html");
|
|
25772
26021
|
if (!html) {
|
|
25773
|
-
html =
|
|
26022
|
+
html = readFileSync36(resolve33(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
25774
26023
|
const name = escapeHtml(BRAND.productName);
|
|
25775
26024
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
25776
26025
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -25958,7 +26207,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
25958
26207
|
let hasBookingSite = false;
|
|
25959
26208
|
try {
|
|
25960
26209
|
if (existsSync35(availPath)) {
|
|
25961
|
-
const cfg = JSON.parse(
|
|
26210
|
+
const cfg = JSON.parse(readFileSync36(availPath, "utf-8"));
|
|
25962
26211
|
hasBookingSite = typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
25963
26212
|
}
|
|
25964
26213
|
} catch {
|
|
@@ -25968,7 +26217,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
25968
26217
|
let lastSuccessAt = null;
|
|
25969
26218
|
if (existsSync35(statePath)) {
|
|
25970
26219
|
try {
|
|
25971
|
-
const rec = JSON.parse(
|
|
26220
|
+
const rec = JSON.parse(readFileSync36(statePath, "utf-8"));
|
|
25972
26221
|
lastSuccessAt = rec.lastSuccessAt ?? null;
|
|
25973
26222
|
} catch {
|
|
25974
26223
|
console.error(`[calendar-availability] op=audit accountId=${account.accountId} snapshotAgeMs=na reason=bad-state-file`);
|
|
@@ -26111,7 +26360,7 @@ async function runAdminUserReconcileTick() {
|
|
|
26111
26360
|
console.error("[adminuser-self-heal] skip reason=no-users-file");
|
|
26112
26361
|
return;
|
|
26113
26362
|
}
|
|
26114
|
-
const usersRaw =
|
|
26363
|
+
const usersRaw = readFileSync36(USERS_FILE, "utf-8").trim();
|
|
26115
26364
|
if (!usersRaw) {
|
|
26116
26365
|
console.error("[adminuser-self-heal] skip reason=empty-users-file");
|
|
26117
26366
|
return;
|
|
@@ -26141,7 +26390,7 @@ if (typeof adminUserReconcileTimer.unref === "function") adminUserReconcileTimer
|
|
|
26141
26390
|
var USERS_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
26142
26391
|
function countUsersRows() {
|
|
26143
26392
|
if (!existsSync35(USERS_FILE)) return 0;
|
|
26144
|
-
const raw =
|
|
26393
|
+
const raw = readFileSync36(USERS_FILE, "utf-8").trim();
|
|
26145
26394
|
if (!raw) return 0;
|
|
26146
26395
|
const users = JSON.parse(raw);
|
|
26147
26396
|
return users.filter((u) => typeof u.userId === "string").length;
|