@rubytech/create-maxy 1.0.678 → 1.0.679
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 +23 -0
- package/package.json +1 -1
- package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate.test.d.ts +2 -0
- package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate.test.d.ts.map +1 -0
- package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate.test.js +112 -0
- package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate.test.js.map +1 -0
- package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cache.test.d.ts +2 -0
- package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cache.test.d.ts.map +1 -0
- package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cache.test.js +163 -0
- package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cache.test.js.map +1 -0
- package/payload/platform/lib/graph-mcp/dist/cypher-validate.d.ts +38 -0
- package/payload/platform/lib/graph-mcp/dist/cypher-validate.d.ts.map +1 -0
- package/payload/platform/lib/graph-mcp/dist/cypher-validate.js +130 -0
- package/payload/platform/lib/graph-mcp/dist/cypher-validate.js.map +1 -0
- package/payload/platform/lib/graph-mcp/dist/index.js +201 -45
- package/payload/platform/lib/graph-mcp/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-mcp/dist/schema-cache.d.ts +78 -0
- package/payload/platform/lib/graph-mcp/dist/schema-cache.d.ts.map +1 -0
- package/payload/platform/lib/graph-mcp/dist/schema-cache.js +194 -0
- package/payload/platform/lib/graph-mcp/dist/schema-cache.js.map +1 -0
- package/payload/platform/lib/graph-mcp/src/__tests__/cypher-validate.test.ts +141 -0
- package/payload/platform/lib/graph-mcp/src/__tests__/schema-cache.test.ts +169 -0
- package/payload/platform/lib/graph-mcp/src/cypher-validate.ts +157 -0
- package/payload/platform/lib/graph-mcp/src/index.ts +247 -47
- package/payload/platform/lib/graph-mcp/src/schema-cache.ts +212 -0
- package/payload/platform/lib/graph-trash/dist/index.d.ts +8 -0
- package/payload/platform/lib/graph-trash/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-trash/dist/index.js +109 -14
- package/payload/platform/lib/graph-trash/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-trash/src/index.ts +136 -21
- package/payload/platform/plugins/docs/references/memory-guide.md +5 -1
- package/payload/platform/plugins/docs/references/platform.md +1 -1
- package/payload/platform/plugins/docs/references/troubleshooting.md +18 -0
- package/payload/platform/plugins/memory/PLUGIN.md +1 -0
- package/payload/platform/plugins/memory/mcp/dist/index.js +54 -6
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/filter-token.d.ts +36 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/filter-token.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/filter-token.js +86 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/filter-token.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.d.ts +23 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js +47 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.d.ts +58 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.js +125 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.js.map +1 -0
- package/payload/platform/templates/agents/admin/IDENTITY.md +16 -0
- package/payload/server/chunk-3RBKKDHC.js +783 -0
- package/payload/server/maxy-edge.js +11 -3
- package/payload/server/server.js +284 -112
package/payload/server/server.js
CHANGED
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
clearRateLimit,
|
|
14
14
|
createRemoteSession,
|
|
15
15
|
hashPassword,
|
|
16
|
-
invalidateRemoteSession,
|
|
17
16
|
isPasswordValid,
|
|
18
17
|
isRemoteAuthConfigured,
|
|
19
18
|
recordFailedAttempt,
|
|
@@ -25,7 +24,7 @@ import {
|
|
|
25
24
|
verifyPassword,
|
|
26
25
|
verifyRemotePassword,
|
|
27
26
|
vncLog
|
|
28
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-3RBKKDHC.js";
|
|
29
28
|
|
|
30
29
|
// ../lib/models/dist/index.js
|
|
31
30
|
var require_dist = __commonJS({
|
|
@@ -2895,7 +2894,7 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
2895
2894
|
};
|
|
2896
2895
|
|
|
2897
2896
|
// server/index.ts
|
|
2898
|
-
import { readFileSync as
|
|
2897
|
+
import { readFileSync as readFileSync25, existsSync as existsSync23, watchFile } from "fs";
|
|
2899
2898
|
import { resolve as resolve27, join as join12, basename as basename7 } from "path";
|
|
2900
2899
|
import { homedir as homedir4 } from "os";
|
|
2901
2900
|
|
|
@@ -2908,7 +2907,7 @@ import { spawn as spawn2, spawnSync as spawnSync2 } from "child_process";
|
|
|
2908
2907
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
2909
2908
|
import { resolve as resolve5, join as join3 } from "path";
|
|
2910
2909
|
import { platform as osPlatform } from "os";
|
|
2911
|
-
import { readFileSync as
|
|
2910
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, readdirSync as readdirSync2, existsSync as existsSync5, mkdirSync as mkdirSync4, createWriteStream, statSync as statSync3, unlinkSync as unlinkSync3, cpSync, rmSync as rmSync2, appendFileSync, openSync as openSync2, readSync as readSync2, closeSync as closeSync2 } from "fs";
|
|
2912
2911
|
import { lookup as dnsLookup } from "dns/promises";
|
|
2913
2912
|
import { createConnection as netConnect } from "net";
|
|
2914
2913
|
import { StringDecoder } from "string_decoder";
|
|
@@ -5803,6 +5802,101 @@ async function criticAndRecord(opts) {
|
|
|
5803
5802
|
}
|
|
5804
5803
|
}
|
|
5805
5804
|
|
|
5805
|
+
// app/lib/admin-schema-block.ts
|
|
5806
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
5807
|
+
var EDGE_TAXONOMY = [
|
|
5808
|
+
{ type: "PART_OF", direction: "(Message)-[:PART_OF]->(Conversation)", note: "Messages belong to exactly one Conversation. Do NOT use :HAS_MESSAGE \u2014 that edge does not exist." },
|
|
5809
|
+
{ type: "NEXT", direction: "(Message)-[:NEXT]->(Message)", note: "Chain order within a Conversation. Each Message has at most one NEXT successor." },
|
|
5810
|
+
{ type: "BELONGS_TO", direction: "(Conversation|Task|...)-[:BELONGS_TO]->(LocalBusiness)", note: "Account scope. Universal \u2014 almost every tenant-owned node has one." },
|
|
5811
|
+
{ type: "ADMIN_OF", direction: "(AdminUser)-[:ADMIN_OF]->(LocalBusiness)", note: "Device-level admin membership (see admin-add / admin-remove)." },
|
|
5812
|
+
{ type: "AUTHORED_BY", direction: "(Message)-[:AUTHORED_BY]->(Person)", note: "Message authorship (when the author is an identified Person)." },
|
|
5813
|
+
{ type: "HAS_TOOL_CALL", direction: "(Message)-[:HAS_TOOL_CALL]->(ToolCall)", note: "Tool calls attached to an assistant message." },
|
|
5814
|
+
{ type: "HAS_RESULT", direction: "(WorkflowStep|ToolCall)-[:HAS_RESULT]->(StepResult)", note: "Workflow step / tool-call outputs." },
|
|
5815
|
+
{ type: "HAS_STEP", direction: "(Workflow)-[:HAS_STEP]->(WorkflowStep)", note: "Workflow composition." },
|
|
5816
|
+
{ type: "RUN_OF", direction: "(WorkflowRun)-[:RUN_OF]->(Workflow)", note: "Workflow execution instance." },
|
|
5817
|
+
{ type: "HAS_SECTION", direction: "(KnowledgeDocument)-[:HAS_SECTION]->(Section)", note: "Document hierarchy." },
|
|
5818
|
+
{ type: "HAS_CHUNK", direction: "(Section)-[:HAS_CHUNK]->(Chunk)", note: "Section-to-embeddable-chunk." },
|
|
5819
|
+
{ type: "HAS_PREFERENCE", direction: "(Person)-[:HAS_PREFERENCE]->(Preference)", note: "Person-scoped preferences (profile memory)." },
|
|
5820
|
+
{ type: "HAS_ACCESS", direction: "(Person)-[:HAS_ACCESS]->(AccessGrant)", note: "Public agent access grants." },
|
|
5821
|
+
{ type: "HAS_TASK", direction: "(Person|LocalBusiness)-[:HAS_TASK]->(Task)", note: "Task ownership / assignment." },
|
|
5822
|
+
{ type: "HAS_PRICING", direction: "(Service)-[:HAS_PRICING]->(PriceSpecification)", note: "Service pricing." },
|
|
5823
|
+
{ type: "HAS_HOURS", direction: "(LocalBusiness)-[:HAS_HOURS]->(OpeningHoursSpecification)", note: "Opening hours." },
|
|
5824
|
+
{ type: "HAS_FAQ", direction: "(LocalBusiness)-[:HAS_FAQ]->(Question)", note: "FAQ attached to business." },
|
|
5825
|
+
{ type: "HAS_BRAND_ASSET", direction: "(LocalBusiness)-[:HAS_BRAND_ASSET]->(DigitalDocument|ImageObject)", note: "Branding assets." },
|
|
5826
|
+
{ type: "OFFERS", direction: "(LocalBusiness)-[:OFFERS]->(Service)", note: "Service catalogue." },
|
|
5827
|
+
{ type: "CONTAINS", direction: "(KnowledgeDocument)-[:CONTAINS]->(Chunk)", note: "Flat document-to-chunk (alternative to HAS_SECTION then HAS_CHUNK)." },
|
|
5828
|
+
{ type: "REFERENCES", direction: "(Message|KnowledgeDocument)-[:REFERENCES]->(*)", note: "Soft reference link." },
|
|
5829
|
+
{ type: "ABOUT", direction: "(Review|Message)-[:ABOUT]->(*)", note: "Subject pointer." },
|
|
5830
|
+
{ type: "REPLY_TO", direction: "(Email)-[:REPLY_TO]->(Email)", note: "Email threading." },
|
|
5831
|
+
{ type: "RECEIVED_BY", direction: "(Email)-[:RECEIVED_BY]->(Person)", note: "Email recipient." },
|
|
5832
|
+
{ type: "RAISED_BY", direction: "(ReviewAlert)-[:RAISED_BY]->(*)", note: "Alert provenance." },
|
|
5833
|
+
{ type: "AFFECTS", direction: "(ReviewAlert)-[:AFFECTS]->(*)", note: "Alert impact surface." },
|
|
5834
|
+
{ type: "BLOCKS", direction: "(Task)-[:BLOCKS]->(Task)", note: "Task dependency." },
|
|
5835
|
+
{ type: "OBSERVED_IN", direction: "(*)-[:OBSERVED_IN]->(Conversation)", note: "Observation provenance." }
|
|
5836
|
+
];
|
|
5837
|
+
var SUBLABELS = [
|
|
5838
|
+
{ base: "Conversation", sub: "AdminConversation", note: "Admin-only conversation (admin chat, not public)." },
|
|
5839
|
+
{ base: "Conversation", sub: "PublicConversation", note: "Public agent conversation (visitor-facing)." },
|
|
5840
|
+
{ base: "Message", sub: "UserMessage", note: "Message authored by the human user." },
|
|
5841
|
+
{ base: "Message", sub: "AssistantMessage", note: "Message authored by the assistant." }
|
|
5842
|
+
];
|
|
5843
|
+
var LABEL_PATTERN = /FOR\s*\(\s*\w+\s*:\s*(\w+)\s*\)/g;
|
|
5844
|
+
function parseLabelsFromSchemaCypher(schemaCypher) {
|
|
5845
|
+
const found = /* @__PURE__ */ new Set();
|
|
5846
|
+
for (const match2 of schemaCypher.matchAll(LABEL_PATTERN)) {
|
|
5847
|
+
found.add(match2[1]);
|
|
5848
|
+
}
|
|
5849
|
+
return [...found].sort();
|
|
5850
|
+
}
|
|
5851
|
+
function buildSchemaBlock(schemaCypherText) {
|
|
5852
|
+
const baseLabels = parseLabelsFromSchemaCypher(schemaCypherText);
|
|
5853
|
+
const sublabels = SUBLABELS.map((s) => s.sub);
|
|
5854
|
+
const lines = [];
|
|
5855
|
+
lines.push("# SCHEMA (Neo4j graph, canonical reference)");
|
|
5856
|
+
lines.push("");
|
|
5857
|
+
lines.push("The Neo4j instance backing this admin session contains exactly the labels and relationship types below. Never invent names outside this list. If you need cypher against a token not listed here, first invoke `maxy-graph-get_neo4j_schema` to confirm it exists \u2014 do not guess.");
|
|
5858
|
+
lines.push("");
|
|
5859
|
+
lines.push("## Labels (from platform/neo4j/schema.cypher)");
|
|
5860
|
+
lines.push("");
|
|
5861
|
+
for (const label of baseLabels) {
|
|
5862
|
+
lines.push(`- :${label}`);
|
|
5863
|
+
}
|
|
5864
|
+
lines.push("");
|
|
5865
|
+
lines.push("### Sublabels (Task 633 role-cue variants)");
|
|
5866
|
+
lines.push("");
|
|
5867
|
+
for (const s of SUBLABELS) {
|
|
5868
|
+
lines.push(`- :${s.sub} (on :${s.base}) \u2014 ${s.note}`);
|
|
5869
|
+
}
|
|
5870
|
+
lines.push("");
|
|
5871
|
+
lines.push("## Relationship types (from .docs/neo4j.md)");
|
|
5872
|
+
lines.push("");
|
|
5873
|
+
for (const e of EDGE_TAXONOMY) {
|
|
5874
|
+
lines.push(`- :${e.type} \u2014 ${e.direction} \u2014 ${e.note}`);
|
|
5875
|
+
}
|
|
5876
|
+
lines.push("");
|
|
5877
|
+
lines.push("The cypher MCP validator (graph-mcp proxy, Task 654) rejects write cypher that references unknown labels or edges and warns on read cypher. Stick to the taxonomy above; if you believe a token is missing, invoke `maxy-graph-get_neo4j_schema` for the live snapshot.");
|
|
5878
|
+
const text = lines.join("\n");
|
|
5879
|
+
return {
|
|
5880
|
+
text,
|
|
5881
|
+
labelCount: baseLabels.length + sublabels.length,
|
|
5882
|
+
relationshipTypeCount: EDGE_TAXONOMY.length,
|
|
5883
|
+
bytes: Buffer.byteLength(text, "utf-8")
|
|
5884
|
+
};
|
|
5885
|
+
}
|
|
5886
|
+
function loadAdminSchemaBlock(schemaCypherPath) {
|
|
5887
|
+
let text;
|
|
5888
|
+
try {
|
|
5889
|
+
text = readFileSync6(schemaCypherPath, "utf-8");
|
|
5890
|
+
} catch (err) {
|
|
5891
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
5892
|
+
console.error(
|
|
5893
|
+
`[admin-identity] schema.cypher unreadable path=${schemaCypherPath} error="${msg.replace(/"/g, "'")}" block=omitted`
|
|
5894
|
+
);
|
|
5895
|
+
return null;
|
|
5896
|
+
}
|
|
5897
|
+
return buildSchemaBlock(text);
|
|
5898
|
+
}
|
|
5899
|
+
|
|
5806
5900
|
// app/lib/claude-agent.ts
|
|
5807
5901
|
var LOG_RETENTION_DAYS = 7;
|
|
5808
5902
|
var BROWSER_TOOL_PREFIXES = [
|
|
@@ -6063,7 +6157,7 @@ function sampleProcState(pid) {
|
|
|
6063
6157
|
let sockets2 = 0;
|
|
6064
6158
|
for (const tcpFile of ["/proc/" + pid + "/net/tcp", "/proc/" + pid + "/net/tcp6"]) {
|
|
6065
6159
|
try {
|
|
6066
|
-
const raw2 =
|
|
6160
|
+
const raw2 = readFileSync7(tcpFile, "utf-8");
|
|
6067
6161
|
const lines2 = raw2.split("\n");
|
|
6068
6162
|
for (let i = 1; i < lines2.length; i++) {
|
|
6069
6163
|
const line = lines2[i].trim();
|
|
@@ -6079,7 +6173,7 @@ function sampleProcState(pid) {
|
|
|
6079
6173
|
}
|
|
6080
6174
|
let rssMb = 0;
|
|
6081
6175
|
try {
|
|
6082
|
-
const statm =
|
|
6176
|
+
const statm = readFileSync7(`/proc/${pid}/statm`, "utf-8").trim().split(/\s+/);
|
|
6083
6177
|
const rssPages = parseInt(statm[1] ?? "0", 10);
|
|
6084
6178
|
if (Number.isFinite(rssPages)) rssMb = Math.round(rssPages * 4096 / (1024 * 1024));
|
|
6085
6179
|
} catch {
|
|
@@ -6126,7 +6220,7 @@ function resolveAccount() {
|
|
|
6126
6220
|
let usersJsonUserId = null;
|
|
6127
6221
|
if (existsSync5(usersFilePath)) {
|
|
6128
6222
|
try {
|
|
6129
|
-
const raw2 =
|
|
6223
|
+
const raw2 = readFileSync7(usersFilePath, "utf-8").trim();
|
|
6130
6224
|
if (raw2) {
|
|
6131
6225
|
const users = JSON.parse(raw2);
|
|
6132
6226
|
if (users.length > 0) {
|
|
@@ -6142,7 +6236,7 @@ function resolveAccount() {
|
|
|
6142
6236
|
if (!entry.isDirectory()) continue;
|
|
6143
6237
|
const configPath2 = resolve5(ACCOUNTS_DIR, entry.name, "account.json");
|
|
6144
6238
|
if (!existsSync5(configPath2)) continue;
|
|
6145
|
-
const raw2 =
|
|
6239
|
+
const raw2 = readFileSync7(configPath2, "utf-8");
|
|
6146
6240
|
let config;
|
|
6147
6241
|
try {
|
|
6148
6242
|
config = JSON.parse(raw2);
|
|
@@ -6177,7 +6271,7 @@ function resolveAccount() {
|
|
|
6177
6271
|
function readAgentFile(accountDir, agentName, filename) {
|
|
6178
6272
|
const filePath = resolve5(accountDir, "agents", agentName, filename);
|
|
6179
6273
|
if (!existsSync5(filePath)) return null;
|
|
6180
|
-
return
|
|
6274
|
+
return readFileSync7(filePath, "utf-8");
|
|
6181
6275
|
}
|
|
6182
6276
|
function readIdentity(accountDir, agentName) {
|
|
6183
6277
|
return readAgentFile(accountDir, agentName, "IDENTITY.md");
|
|
@@ -6219,7 +6313,7 @@ function resolveDefaultAgentSlug(accountDir) {
|
|
|
6219
6313
|
}
|
|
6220
6314
|
let config;
|
|
6221
6315
|
try {
|
|
6222
|
-
config = JSON.parse(
|
|
6316
|
+
config = JSON.parse(readFileSync7(configPath2, "utf-8"));
|
|
6223
6317
|
} catch (err) {
|
|
6224
6318
|
console.error("[agent-resolve] failed to read account.json:", err);
|
|
6225
6319
|
return null;
|
|
@@ -6310,14 +6404,14 @@ function resolveAgentConfig(accountDir, agentName) {
|
|
|
6310
6404
|
const knowledgeMtime = statSync3(knowledgePath).mtimeMs;
|
|
6311
6405
|
const summaryMtime = statSync3(summaryPath).mtimeMs;
|
|
6312
6406
|
if (summaryMtime >= knowledgeMtime) {
|
|
6313
|
-
knowledge =
|
|
6407
|
+
knowledge = readFileSync7(summaryPath, "utf-8");
|
|
6314
6408
|
} else {
|
|
6315
6409
|
console.warn(`[agent-config] ${agentName}: KNOWLEDGE-SUMMARY.md is stale (KNOWLEDGE.md is newer) \u2014 using full knowledge`);
|
|
6316
|
-
knowledge =
|
|
6410
|
+
knowledge = readFileSync7(knowledgePath, "utf-8");
|
|
6317
6411
|
}
|
|
6318
6412
|
knowledgeBaked = true;
|
|
6319
6413
|
} else if (hasKnowledge) {
|
|
6320
|
-
knowledge =
|
|
6414
|
+
knowledge = readFileSync7(knowledgePath, "utf-8");
|
|
6321
6415
|
knowledgeBaked = true;
|
|
6322
6416
|
}
|
|
6323
6417
|
let budget = null;
|
|
@@ -6343,7 +6437,7 @@ function parsePluginFrontmatter(pluginDir) {
|
|
|
6343
6437
|
if (!existsSync5(pluginPath)) return null;
|
|
6344
6438
|
let raw2;
|
|
6345
6439
|
try {
|
|
6346
|
-
raw2 =
|
|
6440
|
+
raw2 = readFileSync7(pluginPath, "utf-8");
|
|
6347
6441
|
} catch {
|
|
6348
6442
|
console.warn(`[plugins] cannot read ${pluginPath}`);
|
|
6349
6443
|
return null;
|
|
@@ -6419,7 +6513,7 @@ function autoDeliverPremiumPlugins(purchasedPlugins) {
|
|
|
6419
6513
|
if (isBundle) {
|
|
6420
6514
|
let bundleRaw;
|
|
6421
6515
|
try {
|
|
6422
|
-
bundleRaw =
|
|
6516
|
+
bundleRaw = readFileSync7(bundlePath, "utf-8");
|
|
6423
6517
|
} catch (err) {
|
|
6424
6518
|
console.log(`${TAG19} ${pluginName}: cannot read BUNDLE.md \u2014 ${err instanceof Error ? err.message : String(err)}`);
|
|
6425
6519
|
continue;
|
|
@@ -6512,7 +6606,7 @@ function migratePluginRenames(accountDir, config) {
|
|
|
6512
6606
|
if (!changed) return;
|
|
6513
6607
|
const configPath2 = resolve5(accountDir, "account.json");
|
|
6514
6608
|
try {
|
|
6515
|
-
const raw2 =
|
|
6609
|
+
const raw2 = readFileSync7(configPath2, "utf-8");
|
|
6516
6610
|
const parsed = JSON.parse(raw2);
|
|
6517
6611
|
parsed.enabledPlugins = migrated;
|
|
6518
6612
|
writeFileSync5(configPath2, JSON.stringify(parsed, null, 2) + "\n");
|
|
@@ -6546,7 +6640,7 @@ function autoDeliverBundleAgents(accountDir, purchasedPlugins) {
|
|
|
6546
6640
|
const agentsmdPath = resolve5(accountDir, "agents", "admin", "AGENTS.md");
|
|
6547
6641
|
let agentsmd = "";
|
|
6548
6642
|
try {
|
|
6549
|
-
agentsmd = existsSync5(agentsmdPath) ?
|
|
6643
|
+
agentsmd = existsSync5(agentsmdPath) ? readFileSync7(agentsmdPath, "utf-8") : "";
|
|
6550
6644
|
} catch {
|
|
6551
6645
|
}
|
|
6552
6646
|
let delivered = 0;
|
|
@@ -6570,7 +6664,7 @@ function autoDeliverBundleAgents(accountDir, purchasedPlugins) {
|
|
|
6570
6664
|
continue;
|
|
6571
6665
|
}
|
|
6572
6666
|
try {
|
|
6573
|
-
const content =
|
|
6667
|
+
const content = readFileSync7(target, "utf-8");
|
|
6574
6668
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
6575
6669
|
if (fmMatch) {
|
|
6576
6670
|
const nameMatch = fmMatch[1].match(/^name:\s*(.+)/m);
|
|
@@ -6606,7 +6700,7 @@ function assemblePublicPluginContent(pluginDir) {
|
|
|
6606
6700
|
const pluginPath = resolve5(pluginRoot, "PLUGIN.md");
|
|
6607
6701
|
let raw2;
|
|
6608
6702
|
try {
|
|
6609
|
-
raw2 =
|
|
6703
|
+
raw2 = readFileSync7(pluginPath, "utf-8");
|
|
6610
6704
|
} catch {
|
|
6611
6705
|
return null;
|
|
6612
6706
|
}
|
|
@@ -6627,7 +6721,7 @@ function assemblePublicPluginContent(pluginDir) {
|
|
|
6627
6721
|
const skillMdPath = resolve5(skillDir, "SKILL.md");
|
|
6628
6722
|
let skillRaw;
|
|
6629
6723
|
try {
|
|
6630
|
-
skillRaw =
|
|
6724
|
+
skillRaw = readFileSync7(skillMdPath, "utf-8");
|
|
6631
6725
|
} catch {
|
|
6632
6726
|
continue;
|
|
6633
6727
|
}
|
|
@@ -6678,7 +6772,7 @@ function assemblePublicPluginContent(pluginDir) {
|
|
|
6678
6772
|
}
|
|
6679
6773
|
for (const refFile of refFiles) {
|
|
6680
6774
|
try {
|
|
6681
|
-
const refContent =
|
|
6775
|
+
const refContent = readFileSync7(resolve5(refsDir, refFile), "utf-8").trim();
|
|
6682
6776
|
if (refContent) {
|
|
6683
6777
|
parts.push(`
|
|
6684
6778
|
<!-- reference: ${refFile} -->`);
|
|
@@ -6752,7 +6846,7 @@ function loadEmbeddedPlugins(agentType, selectedPlugins, enabledPlugins) {
|
|
|
6752
6846
|
const pluginPath = resolve5(pluginsDir, dir, "PLUGIN.md");
|
|
6753
6847
|
let raw2;
|
|
6754
6848
|
try {
|
|
6755
|
-
raw2 =
|
|
6849
|
+
raw2 = readFileSync7(pluginPath, "utf-8");
|
|
6756
6850
|
} catch (err) {
|
|
6757
6851
|
console.warn(`[plugins] ${dir}: failed to read PLUGIN.md for ${agentType} embed: ${String(err)}`);
|
|
6758
6852
|
continue;
|
|
@@ -7098,7 +7192,7 @@ function resolveUserAccounts(userId) {
|
|
|
7098
7192
|
if (!existsSync5(configPath2)) continue;
|
|
7099
7193
|
let config;
|
|
7100
7194
|
try {
|
|
7101
|
-
config = JSON.parse(
|
|
7195
|
+
config = JSON.parse(readFileSync7(configPath2, "utf-8"));
|
|
7102
7196
|
} catch {
|
|
7103
7197
|
console.error(`[session] account.json corrupt at ${configPath2} \u2014 skipping`);
|
|
7104
7198
|
continue;
|
|
@@ -7414,7 +7508,7 @@ function readBrandHostname() {
|
|
|
7414
7508
|
if (cachedBrandHostname !== null) return cachedBrandHostname;
|
|
7415
7509
|
try {
|
|
7416
7510
|
const brandPath = resolve5(PLATFORM_ROOT3, "config", "brand.json");
|
|
7417
|
-
const parsed = JSON.parse(
|
|
7511
|
+
const parsed = JSON.parse(readFileSync7(brandPath, "utf-8"));
|
|
7418
7512
|
cachedBrandHostname = typeof parsed.hostname === "string" && parsed.hostname.length > 0 ? parsed.hostname : "maxy";
|
|
7419
7513
|
} catch {
|
|
7420
7514
|
cachedBrandHostname = "maxy";
|
|
@@ -10219,7 +10313,7 @@ ${sessionContext}`;
|
|
|
10219
10313
|
const skillPath = resolve5(PLATFORM_ROOT3, "plugins/admin/skills/onboarding/SKILL.md");
|
|
10220
10314
|
let skillContent = "";
|
|
10221
10315
|
try {
|
|
10222
|
-
skillContent =
|
|
10316
|
+
skillContent = readFileSync7(skillPath, "utf-8");
|
|
10223
10317
|
} catch (err) {
|
|
10224
10318
|
console.error(`[onboarding-inject] accountId=${accountId.slice(0, 8)}\u2026 error=skill-read-failed path=${skillPath} reason=${err instanceof Error ? err.message : String(err)}`);
|
|
10225
10319
|
}
|
|
@@ -10271,13 +10365,23 @@ ${manifest}`;
|
|
|
10271
10365
|
}
|
|
10272
10366
|
const graphRefPath = resolve5(PLATFORM_ROOT3, "plugins/memory/references/graph-primitives.md");
|
|
10273
10367
|
try {
|
|
10274
|
-
const graphRef =
|
|
10368
|
+
const graphRef = readFileSync7(graphRefPath, "utf-8");
|
|
10275
10369
|
baseSystemPrompt += `
|
|
10276
10370
|
|
|
10277
10371
|
${graphRef}`;
|
|
10278
10372
|
} catch (err) {
|
|
10279
10373
|
console.error(`[graph-primitives] reference missing at ${graphRefPath} \u2014 admin session will have no Cypher cookbook: ${err instanceof Error ? err.message : String(err)}`);
|
|
10280
10374
|
}
|
|
10375
|
+
const schemaCypherPath = resolve5(PLATFORM_ROOT3, "neo4j/schema.cypher");
|
|
10376
|
+
const schemaBlock = loadAdminSchemaBlock(schemaCypherPath);
|
|
10377
|
+
if (schemaBlock) {
|
|
10378
|
+
baseSystemPrompt += `
|
|
10379
|
+
|
|
10380
|
+
${schemaBlock.text}`;
|
|
10381
|
+
console.log(
|
|
10382
|
+
`[admin-identity] schemaBlockBytes=${schemaBlock.bytes} labels=${schemaBlock.labelCount} relationshipTypes=${schemaBlock.relationshipTypeCount}`
|
|
10383
|
+
);
|
|
10384
|
+
}
|
|
10281
10385
|
}
|
|
10282
10386
|
if (agentConfig?.budget) {
|
|
10283
10387
|
const pluginTokens = embeddedPlugins.reduce((sum, p) => sum + estimateTokens(p.body), 0);
|
|
@@ -10486,7 +10590,7 @@ var clientIpMiddleware = async (c, next) => {
|
|
|
10486
10590
|
};
|
|
10487
10591
|
|
|
10488
10592
|
// server/routes/health.ts
|
|
10489
|
-
import { existsSync as existsSync10, readFileSync as
|
|
10593
|
+
import { existsSync as existsSync10, readFileSync as readFileSync12 } from "fs";
|
|
10490
10594
|
import { createConnection as createConnection2 } from "net";
|
|
10491
10595
|
|
|
10492
10596
|
// app/lib/network.ts
|
|
@@ -10511,7 +10615,7 @@ function getLanIp() {
|
|
|
10511
10615
|
import { basename as basename2 } from "path";
|
|
10512
10616
|
|
|
10513
10617
|
// app/lib/review-detector/rules.ts
|
|
10514
|
-
import { readFileSync as
|
|
10618
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, existsSync as existsSync6, statSync as statSync4, mkdirSync as mkdirSync5, renameSync as renameSync2 } from "fs";
|
|
10515
10619
|
import { resolve as resolve6, dirname as dirname3 } from "path";
|
|
10516
10620
|
var DEFAULT_SCAN_INTERVAL_MS = 5e3;
|
|
10517
10621
|
var RATE_LIMIT_PATTERN = "rate[- ]?limit(?:ed| reached| hit)|(?:HTTP|status)[^a-z]{0,3}429|too many requests";
|
|
@@ -10959,7 +11063,7 @@ function loadRules(configDir2) {
|
|
|
10959
11063
|
if (!existsSync6(path2)) {
|
|
10960
11064
|
throw new Error(`rules file missing at ${path2}`);
|
|
10961
11065
|
}
|
|
10962
|
-
const raw2 =
|
|
11066
|
+
const raw2 = readFileSync8(path2, "utf-8");
|
|
10963
11067
|
let parsed;
|
|
10964
11068
|
try {
|
|
10965
11069
|
parsed = JSON.parse(raw2);
|
|
@@ -11124,7 +11228,7 @@ function validateRule(input, label, seenIds) {
|
|
|
11124
11228
|
}
|
|
11125
11229
|
|
|
11126
11230
|
// app/lib/review-detector/sources.ts
|
|
11127
|
-
import { existsSync as existsSync7, readdirSync as readdirSync3, statSync as statSync5, writeFileSync as writeFileSync7, renameSync as renameSync3, mkdirSync as mkdirSync6, openSync as openSync3, readSync as readSync3, closeSync as closeSync3, readFileSync as
|
|
11231
|
+
import { existsSync as existsSync7, readdirSync as readdirSync3, statSync as statSync5, writeFileSync as writeFileSync7, renameSync as renameSync3, mkdirSync as mkdirSync6, openSync as openSync3, readSync as readSync3, closeSync as closeSync3, readFileSync as readFileSync9 } from "fs";
|
|
11128
11232
|
import { resolve as resolve7, join as join4, basename, dirname as dirname4 } from "path";
|
|
11129
11233
|
function tailStatePath(configDir2) {
|
|
11130
11234
|
return resolve7(configDir2, "review-state.json");
|
|
@@ -11133,7 +11237,7 @@ function loadTailState(configDir2) {
|
|
|
11133
11237
|
const path2 = tailStatePath(configDir2);
|
|
11134
11238
|
if (!existsSync7(path2)) return {};
|
|
11135
11239
|
try {
|
|
11136
|
-
const raw2 =
|
|
11240
|
+
const raw2 = readFileSync9(path2, "utf-8");
|
|
11137
11241
|
const parsed = JSON.parse(raw2);
|
|
11138
11242
|
if (!parsed || typeof parsed !== "object") return {};
|
|
11139
11243
|
const clean = {};
|
|
@@ -11303,7 +11407,7 @@ function sourceKey(file) {
|
|
|
11303
11407
|
}
|
|
11304
11408
|
|
|
11305
11409
|
// app/lib/review-detector/writer.ts
|
|
11306
|
-
import { appendFileSync as appendFileSync2, existsSync as existsSync8, mkdirSync as mkdirSync7, readFileSync as
|
|
11410
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync8, mkdirSync as mkdirSync7, readFileSync as readFileSync10, writeFileSync as writeFileSync8, renameSync as renameSync4, statSync as statSync6 } from "fs";
|
|
11307
11411
|
import { resolve as resolve8, dirname as dirname5 } from "path";
|
|
11308
11412
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
11309
11413
|
function reviewLogPath(configDir2) {
|
|
@@ -11442,7 +11546,7 @@ function queueAlert(configDir2, accountId, match2) {
|
|
|
11442
11546
|
async function drainPendingAlerts(configDir2) {
|
|
11443
11547
|
const path2 = pendingAlertsPath(configDir2);
|
|
11444
11548
|
if (!existsSync8(path2)) return { drained: 0, remaining: 0 };
|
|
11445
|
-
const raw2 =
|
|
11549
|
+
const raw2 = readFileSync10(path2, "utf-8");
|
|
11446
11550
|
const lines = raw2.split("\n").filter((l) => l.trim().length > 0);
|
|
11447
11551
|
if (lines.length === 0) return { drained: 0, remaining: 0 };
|
|
11448
11552
|
const remaining = [];
|
|
@@ -12105,7 +12209,7 @@ var WhatsAppConfigSchema = z.object({
|
|
|
12105
12209
|
});
|
|
12106
12210
|
|
|
12107
12211
|
// app/lib/whatsapp/config-persist.ts
|
|
12108
|
-
import { readFileSync as
|
|
12212
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync9, existsSync as existsSync9 } from "fs";
|
|
12109
12213
|
import { resolve as resolve10, join as join5 } from "path";
|
|
12110
12214
|
var TAG3 = "[whatsapp:config]";
|
|
12111
12215
|
function configPath(accountDir) {
|
|
@@ -12114,7 +12218,7 @@ function configPath(accountDir) {
|
|
|
12114
12218
|
function readConfig(accountDir) {
|
|
12115
12219
|
const path2 = configPath(accountDir);
|
|
12116
12220
|
if (!existsSync9(path2)) throw new Error(`account.json not found at ${path2}`);
|
|
12117
|
-
return JSON.parse(
|
|
12221
|
+
return JSON.parse(readFileSync11(path2, "utf-8"));
|
|
12118
12222
|
}
|
|
12119
12223
|
function writeConfig(accountDir, config) {
|
|
12120
12224
|
const path2 = configPath(accountDir);
|
|
@@ -14406,7 +14510,7 @@ app.get("/", async (c) => {
|
|
|
14406
14510
|
let pinConfigured = false;
|
|
14407
14511
|
try {
|
|
14408
14512
|
if (existsSync10(USERS_FILE)) {
|
|
14409
|
-
const raw2 =
|
|
14513
|
+
const raw2 = readFileSync12(USERS_FILE, "utf-8").trim();
|
|
14410
14514
|
if (raw2) {
|
|
14411
14515
|
const users = JSON.parse(raw2);
|
|
14412
14516
|
pinConfigured = Array.isArray(users) && users.length > 0;
|
|
@@ -15523,7 +15627,7 @@ var group_default = app4;
|
|
|
15523
15627
|
|
|
15524
15628
|
// app/lib/access-gate.ts
|
|
15525
15629
|
import neo4j2 from "neo4j-driver";
|
|
15526
|
-
import { readFileSync as
|
|
15630
|
+
import { readFileSync as readFileSync13 } from "fs";
|
|
15527
15631
|
import { resolve as resolve13 } from "path";
|
|
15528
15632
|
import { randomUUID as randomUUID7, randomInt } from "crypto";
|
|
15529
15633
|
var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve13(process.cwd(), "..");
|
|
@@ -15532,7 +15636,7 @@ function readPassword2() {
|
|
|
15532
15636
|
if (process.env.NEO4J_PASSWORD) return process.env.NEO4J_PASSWORD;
|
|
15533
15637
|
const passwordFile = resolve13(PLATFORM_ROOT5, "config/.neo4j-password");
|
|
15534
15638
|
try {
|
|
15535
|
-
return
|
|
15639
|
+
return readFileSync13(passwordFile, "utf-8").trim();
|
|
15536
15640
|
} catch {
|
|
15537
15641
|
throw new Error(
|
|
15538
15642
|
`Neo4j password not found. Expected at ${passwordFile} or in NEO4J_PASSWORD env var.`
|
|
@@ -15843,7 +15947,7 @@ async function findActiveGrantByContact(contactValue, agentSlug, accountId) {
|
|
|
15843
15947
|
}
|
|
15844
15948
|
|
|
15845
15949
|
// app/lib/brevo-sms.ts
|
|
15846
|
-
import { readFileSync as
|
|
15950
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync11, mkdirSync as mkdirSync9, existsSync as existsSync12, chmodSync } from "fs";
|
|
15847
15951
|
import { dirname as dirname6 } from "path";
|
|
15848
15952
|
import { resolve as resolve14 } from "path";
|
|
15849
15953
|
var BREVO_API_KEY_FILE = resolve14(MAXY_DIR, ".brevo-api-key");
|
|
@@ -15855,7 +15959,7 @@ if (platformRoot) {
|
|
|
15855
15959
|
try {
|
|
15856
15960
|
const brandPath = resolve14(platformRoot, "config", "brand.json");
|
|
15857
15961
|
if (existsSync12(brandPath)) {
|
|
15858
|
-
const brand = JSON.parse(
|
|
15962
|
+
const brand = JSON.parse(readFileSync14(brandPath, "utf-8"));
|
|
15859
15963
|
if (brand.productName) BREVO_SENDER = brand.productName;
|
|
15860
15964
|
}
|
|
15861
15965
|
} catch {
|
|
@@ -15863,7 +15967,7 @@ if (platformRoot) {
|
|
|
15863
15967
|
}
|
|
15864
15968
|
function readBrevoApiKey() {
|
|
15865
15969
|
try {
|
|
15866
|
-
const key =
|
|
15970
|
+
const key = readFileSync14(BREVO_API_KEY_FILE, "utf-8").trim();
|
|
15867
15971
|
if (!key) {
|
|
15868
15972
|
throw new Error(`Brevo API key file is empty: ${BREVO_API_KEY_FILE}`);
|
|
15869
15973
|
}
|
|
@@ -16294,7 +16398,7 @@ app5.post("/send-otp", async (c) => {
|
|
|
16294
16398
|
var access_default = app5;
|
|
16295
16399
|
|
|
16296
16400
|
// server/routes/telegram.ts
|
|
16297
|
-
import { existsSync as existsSync13, readFileSync as
|
|
16401
|
+
import { existsSync as existsSync13, readFileSync as readFileSync15 } from "fs";
|
|
16298
16402
|
import { timingSafeEqual } from "crypto";
|
|
16299
16403
|
|
|
16300
16404
|
// app/lib/telegram/access-control.ts
|
|
@@ -16332,7 +16436,7 @@ function getWebhookSecret(botType) {
|
|
|
16332
16436
|
const filePath = botType === "admin" ? TELEGRAM_ADMIN_WEBHOOK_SECRET_FILE : TELEGRAM_WEBHOOK_SECRET_FILE;
|
|
16333
16437
|
try {
|
|
16334
16438
|
if (!existsSync13(filePath)) return null;
|
|
16335
|
-
const secret =
|
|
16439
|
+
const secret = readFileSync15(filePath, "utf-8").trim();
|
|
16336
16440
|
return secret || null;
|
|
16337
16441
|
} catch {
|
|
16338
16442
|
return null;
|
|
@@ -16492,7 +16596,7 @@ var telegram_default = app6;
|
|
|
16492
16596
|
// server/routes/whatsapp.ts
|
|
16493
16597
|
import { join as join8, resolve as resolve15, basename as basename4 } from "path";
|
|
16494
16598
|
import { readFile as readFile2, stat as stat3 } from "fs/promises";
|
|
16495
|
-
import { realpathSync as realpathSync2, readdirSync as readdirSync4, readFileSync as
|
|
16599
|
+
import { realpathSync as realpathSync2, readdirSync as readdirSync4, readFileSync as readFileSync16, existsSync as existsSync14 } from "fs";
|
|
16496
16600
|
|
|
16497
16601
|
// app/lib/whatsapp/login.ts
|
|
16498
16602
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
@@ -16980,7 +17084,7 @@ app7.post("/config", async (c) => {
|
|
|
16980
17084
|
const configPath2 = resolve15(agentsDir, entry.name, "config.json");
|
|
16981
17085
|
if (!existsSync14(configPath2)) continue;
|
|
16982
17086
|
try {
|
|
16983
|
-
const config = JSON.parse(
|
|
17087
|
+
const config = JSON.parse(readFileSync16(configPath2, "utf-8"));
|
|
16984
17088
|
agents.push({ slug: entry.name, displayName: config.displayName ?? entry.name });
|
|
16985
17089
|
} catch {
|
|
16986
17090
|
console.error(`${TAG18} config action=list-public-agents error="failed to parse config.json for agent ${entry.name}" \u2014 skipping`);
|
|
@@ -17192,7 +17296,7 @@ var whatsapp_default = app7;
|
|
|
17192
17296
|
|
|
17193
17297
|
// server/routes/onboarding.ts
|
|
17194
17298
|
import { spawn as spawn3, execFileSync as execFileSync2 } from "child_process";
|
|
17195
|
-
import { openSync as openSync4, closeSync as closeSync4, writeFileSync as writeFileSync12, writeSync, existsSync as existsSync15, mkdirSync as mkdirSync10, readFileSync as
|
|
17299
|
+
import { openSync as openSync4, closeSync as closeSync4, writeFileSync as writeFileSync12, writeSync, existsSync as existsSync15, mkdirSync as mkdirSync10, readFileSync as readFileSync17, unlinkSync as unlinkSync4 } from "fs";
|
|
17196
17300
|
import { resolve as resolve16, dirname as dirname7 } from "path";
|
|
17197
17301
|
import { createHash, randomUUID as randomUUID9 } from "crypto";
|
|
17198
17302
|
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
@@ -17201,7 +17305,7 @@ function hashPin(pin) {
|
|
|
17201
17305
|
}
|
|
17202
17306
|
function readUsersFile() {
|
|
17203
17307
|
if (!existsSync15(USERS_FILE)) return null;
|
|
17204
|
-
const raw2 =
|
|
17308
|
+
const raw2 = readFileSync17(USERS_FILE, "utf-8").trim();
|
|
17205
17309
|
if (!raw2) return [];
|
|
17206
17310
|
return JSON.parse(raw2);
|
|
17207
17311
|
}
|
|
@@ -17312,7 +17416,7 @@ app8.post("/set-pin", async (c) => {
|
|
|
17312
17416
|
const account = resolveAccount();
|
|
17313
17417
|
if (account) {
|
|
17314
17418
|
try {
|
|
17315
|
-
const config = JSON.parse(
|
|
17419
|
+
const config = JSON.parse(readFileSync17(`${account.accountDir}/account.json`, "utf-8"));
|
|
17316
17420
|
if (!config.admins) config.admins = [];
|
|
17317
17421
|
if (!config.admins.some((a) => a.userId === userId)) {
|
|
17318
17422
|
config.admins.push({ userId, role: "owner" });
|
|
@@ -17370,7 +17474,7 @@ app8.post("/skip", async (c) => {
|
|
|
17370
17474
|
const brandPath = PLATFORM_ROOT7 ? resolve16(PLATFORM_ROOT7, "config", "brand.json") : "";
|
|
17371
17475
|
if (brandPath && existsSync15(brandPath)) {
|
|
17372
17476
|
try {
|
|
17373
|
-
const brand = JSON.parse(
|
|
17477
|
+
const brand = JSON.parse(readFileSync17(brandPath, "utf-8"));
|
|
17374
17478
|
if (brand.productName) agentName = brand.productName;
|
|
17375
17479
|
} catch (err) {
|
|
17376
17480
|
console.error(`[onboarding-skip] brand.json read failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -17564,14 +17668,14 @@ app9.post("/", async (c) => {
|
|
|
17564
17668
|
var client_error_default = app9;
|
|
17565
17669
|
|
|
17566
17670
|
// server/routes/admin/session.ts
|
|
17567
|
-
import { readFileSync as
|
|
17671
|
+
import { readFileSync as readFileSync18, existsSync as existsSync17 } from "fs";
|
|
17568
17672
|
import { createHash as createHash2 } from "crypto";
|
|
17569
17673
|
function hashPin2(pin) {
|
|
17570
17674
|
return createHash2("sha256").update(pin).digest("hex");
|
|
17571
17675
|
}
|
|
17572
17676
|
function readUsersFile2() {
|
|
17573
17677
|
if (!existsSync17(USERS_FILE)) return null;
|
|
17574
|
-
const raw2 =
|
|
17678
|
+
const raw2 = readFileSync18(USERS_FILE, "utf-8").trim();
|
|
17575
17679
|
if (!raw2) return [];
|
|
17576
17680
|
return JSON.parse(raw2);
|
|
17577
17681
|
}
|
|
@@ -18267,7 +18371,7 @@ app12.post("/", requireAdminSession, async (c) => {
|
|
|
18267
18371
|
var compact_default = app12;
|
|
18268
18372
|
|
|
18269
18373
|
// server/routes/admin/logs.ts
|
|
18270
|
-
import { existsSync as existsSync18, readdirSync as readdirSync5, readFileSync as
|
|
18374
|
+
import { existsSync as existsSync18, readdirSync as readdirSync5, readFileSync as readFileSync19, statSync as statSync9 } from "fs";
|
|
18271
18375
|
import { resolve as resolve18, basename as basename5 } from "path";
|
|
18272
18376
|
var TAIL_BYTES = 8192;
|
|
18273
18377
|
var app13 = new Hono2();
|
|
@@ -18286,7 +18390,7 @@ app13.get("/", async (c) => {
|
|
|
18286
18390
|
const filePath = resolve18(dir, safe);
|
|
18287
18391
|
searched.push(filePath);
|
|
18288
18392
|
try {
|
|
18289
|
-
const content =
|
|
18393
|
+
const content = readFileSync19(filePath, "utf-8");
|
|
18290
18394
|
const headers = { "Content-Type": "text/plain; charset=utf-8" };
|
|
18291
18395
|
if (download) headers["Content-Disposition"] = `attachment; filename="${safe}"`;
|
|
18292
18396
|
return new Response(content, { headers });
|
|
@@ -18328,7 +18432,7 @@ app13.get("/", async (c) => {
|
|
|
18328
18432
|
const filePath = resolve18(dir, fileName);
|
|
18329
18433
|
searched.push(filePath);
|
|
18330
18434
|
try {
|
|
18331
|
-
const content =
|
|
18435
|
+
const content = readFileSync19(filePath, "utf-8");
|
|
18332
18436
|
const headers = { "Content-Type": "text/plain; charset=utf-8" };
|
|
18333
18437
|
if (download) headers["Content-Disposition"] = `attachment; filename="${fileName}"`;
|
|
18334
18438
|
return new Response(content, { headers });
|
|
@@ -18355,7 +18459,7 @@ app13.get("/", async (c) => {
|
|
|
18355
18459
|
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync9(resolve18(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
|
|
18356
18460
|
seen.add(name);
|
|
18357
18461
|
try {
|
|
18358
|
-
const content =
|
|
18462
|
+
const content = readFileSync19(resolve18(dir, name));
|
|
18359
18463
|
const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
|
|
18360
18464
|
logs[name] = tail.trim() || "(empty)";
|
|
18361
18465
|
} catch (err) {
|
|
@@ -18440,7 +18544,7 @@ app15.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
18440
18544
|
var attachment_default = app15;
|
|
18441
18545
|
|
|
18442
18546
|
// server/routes/admin/account.ts
|
|
18443
|
-
import { readFileSync as
|
|
18547
|
+
import { readFileSync as readFileSync20, writeFileSync as writeFileSync13 } from "fs";
|
|
18444
18548
|
import { resolve as resolve20 } from "path";
|
|
18445
18549
|
var VALID_CONTEXT_MODES = ["managed", "claude-code"];
|
|
18446
18550
|
var app16 = new Hono2();
|
|
@@ -18459,7 +18563,7 @@ app16.patch("/", requireAdminSession, async (c) => {
|
|
|
18459
18563
|
if (!account) return c.json({ error: "No account configured" }, 500);
|
|
18460
18564
|
const configPath2 = resolve20(account.accountDir, "account.json");
|
|
18461
18565
|
try {
|
|
18462
|
-
const raw2 =
|
|
18566
|
+
const raw2 = readFileSync20(configPath2, "utf-8");
|
|
18463
18567
|
const config = JSON.parse(raw2);
|
|
18464
18568
|
config.contextMode = contextMode;
|
|
18465
18569
|
writeFileSync13(configPath2, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
@@ -18474,7 +18578,7 @@ var account_default = app16;
|
|
|
18474
18578
|
|
|
18475
18579
|
// server/routes/admin/agents.ts
|
|
18476
18580
|
import { resolve as resolve21 } from "path";
|
|
18477
|
-
import { readdirSync as readdirSync6, readFileSync as
|
|
18581
|
+
import { readdirSync as readdirSync6, readFileSync as readFileSync21, existsSync as existsSync20, rmSync as rmSync3 } from "fs";
|
|
18478
18582
|
var app17 = new Hono2();
|
|
18479
18583
|
app17.get("/", (c) => {
|
|
18480
18584
|
const account = resolveAccount();
|
|
@@ -18490,7 +18594,7 @@ app17.get("/", (c) => {
|
|
|
18490
18594
|
const configPath2 = resolve21(agentsDir, entry.name, "config.json");
|
|
18491
18595
|
if (!existsSync20(configPath2)) continue;
|
|
18492
18596
|
try {
|
|
18493
|
-
const config = JSON.parse(
|
|
18597
|
+
const config = JSON.parse(readFileSync21(configPath2, "utf-8"));
|
|
18494
18598
|
agents.push({
|
|
18495
18599
|
slug: entry.name,
|
|
18496
18600
|
displayName: config.displayName ?? entry.name,
|
|
@@ -18532,7 +18636,7 @@ app17.delete("/:slug", (c) => {
|
|
|
18532
18636
|
var agents_default = app17;
|
|
18533
18637
|
|
|
18534
18638
|
// server/routes/admin/version.ts
|
|
18535
|
-
import { existsSync as existsSync21, readFileSync as
|
|
18639
|
+
import { existsSync as existsSync21, readFileSync as readFileSync22 } from "fs";
|
|
18536
18640
|
import { resolve as resolve22, join as join10 } from "path";
|
|
18537
18641
|
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve22(process.cwd(), "..");
|
|
18538
18642
|
var brandHostname = "maxy";
|
|
@@ -18540,7 +18644,7 @@ var brandNpmPackage = "@rubytech/create-maxy";
|
|
|
18540
18644
|
var brandJsonPath = join10(PLATFORM_ROOT8, "config", "brand.json");
|
|
18541
18645
|
if (existsSync21(brandJsonPath)) {
|
|
18542
18646
|
try {
|
|
18543
|
-
const brand = JSON.parse(
|
|
18647
|
+
const brand = JSON.parse(readFileSync22(brandJsonPath, "utf-8"));
|
|
18544
18648
|
if (brand.hostname) brandHostname = brand.hostname;
|
|
18545
18649
|
if (brand.npm?.packageName) brandNpmPackage = brand.npm.packageName;
|
|
18546
18650
|
} catch {
|
|
@@ -18552,7 +18656,7 @@ var REGISTRY_URL = `https://registry.npmjs.org/${NPM_PACKAGE}/latest`;
|
|
|
18552
18656
|
var FETCH_TIMEOUT_MS = 5e3;
|
|
18553
18657
|
function readInstalled() {
|
|
18554
18658
|
if (!existsSync21(VERSION_FILE)) return "unknown";
|
|
18555
|
-
const content =
|
|
18659
|
+
const content = readFileSync22(VERSION_FILE, "utf-8").trim();
|
|
18556
18660
|
return content || "unknown";
|
|
18557
18661
|
}
|
|
18558
18662
|
async function fetchLatest() {
|
|
@@ -19041,7 +19145,7 @@ var events_default = app23;
|
|
|
19041
19145
|
// server/routes/admin/cloudflare.ts
|
|
19042
19146
|
import { homedir as homedir3 } from "os";
|
|
19043
19147
|
import { resolve as resolve24 } from "path";
|
|
19044
|
-
import { readFileSync as
|
|
19148
|
+
import { readFileSync as readFileSync24 } from "fs";
|
|
19045
19149
|
|
|
19046
19150
|
// app/lib/dns-label.ts
|
|
19047
19151
|
var VALID_LABEL = /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
@@ -19057,14 +19161,14 @@ function isValidDomain(value) {
|
|
|
19057
19161
|
}
|
|
19058
19162
|
|
|
19059
19163
|
// app/lib/alias-domains.ts
|
|
19060
|
-
import { existsSync as existsSync22, mkdirSync as mkdirSync12, readFileSync as
|
|
19164
|
+
import { existsSync as existsSync22, mkdirSync as mkdirSync12, readFileSync as readFileSync23, writeFileSync as writeFileSync14 } from "fs";
|
|
19061
19165
|
import { dirname as dirname9 } from "path";
|
|
19062
19166
|
import { resolve as resolve23 } from "path";
|
|
19063
19167
|
var ALIAS_DOMAINS_PATH = resolve23(MAXY_DIR, "alias-domains.json");
|
|
19064
19168
|
function readExisting() {
|
|
19065
19169
|
if (!existsSync22(ALIAS_DOMAINS_PATH)) return /* @__PURE__ */ new Set();
|
|
19066
19170
|
try {
|
|
19067
|
-
const parsed = JSON.parse(
|
|
19171
|
+
const parsed = JSON.parse(readFileSync23(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
19068
19172
|
if (!Array.isArray(parsed)) return /* @__PURE__ */ new Set();
|
|
19069
19173
|
return new Set(parsed.filter((h) => typeof h === "string"));
|
|
19070
19174
|
} catch {
|
|
@@ -19086,7 +19190,7 @@ function loadBrandInfo() {
|
|
|
19086
19190
|
const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? resolve24(process.cwd(), "..");
|
|
19087
19191
|
const brandPath = resolve24(platformRoot2, "config", "brand.json");
|
|
19088
19192
|
try {
|
|
19089
|
-
const parsed = JSON.parse(
|
|
19193
|
+
const parsed = JSON.parse(readFileSync24(brandPath, "utf-8"));
|
|
19090
19194
|
const hostname2 = typeof parsed.hostname === "string" && parsed.hostname ? parsed.hostname : "maxy";
|
|
19091
19195
|
const configDir2 = typeof parsed.configDir === "string" && parsed.configDir ? parsed.configDir : ".maxy";
|
|
19092
19196
|
return { hostname: hostname2, configDir: configDir2 };
|
|
@@ -19489,25 +19593,72 @@ async function trashNode(params) {
|
|
|
19489
19593
|
const setNullClauses = Object.keys(originalKeys).map((k) => `n.\`${k}\` = null`).join(", ");
|
|
19490
19594
|
const setNullSuffix = setNullClauses ? `, ${setNullClauses}` : "";
|
|
19491
19595
|
const trashedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
19492
|
-
|
|
19493
|
-
|
|
19494
|
-
|
|
19495
|
-
|
|
19496
|
-
|
|
19497
|
-
|
|
19498
|
-
|
|
19499
|
-
|
|
19500
|
-
|
|
19501
|
-
|
|
19502
|
-
|
|
19503
|
-
|
|
19504
|
-
|
|
19596
|
+
const isConversation = baseLabels.includes("Conversation");
|
|
19597
|
+
const messageUniqueKeys = UNIQUE_KEYS_BY_LABEL["Message"] ?? [];
|
|
19598
|
+
let cascadedMessageCount = 0;
|
|
19599
|
+
await session.executeWrite(async (tx) => {
|
|
19600
|
+
await tx.run(
|
|
19601
|
+
`MATCH (n) WHERE elementId(n) = $eid
|
|
19602
|
+
SET n:Trashed,
|
|
19603
|
+
n.trashedAt = datetime($trashedAt),
|
|
19604
|
+
n.trashedBy = $by,
|
|
19605
|
+
n.trashReason = $reason,
|
|
19606
|
+
n._trashedKeys = $trashedKeysJson${setNullSuffix}`,
|
|
19607
|
+
{
|
|
19608
|
+
eid: elementId,
|
|
19609
|
+
trashedAt,
|
|
19610
|
+
by,
|
|
19611
|
+
reason: reason ?? null,
|
|
19612
|
+
trashedKeysJson: JSON.stringify(originalKeys)
|
|
19613
|
+
}
|
|
19614
|
+
);
|
|
19615
|
+
if (isConversation) {
|
|
19616
|
+
const collectKeys = messageUniqueKeys.length > 0 ? messageUniqueKeys.map((k) => `\`${k}\`: m.\`${k}\``).join(", ") : "";
|
|
19617
|
+
const collectMsgProps = collectKeys ? `, {${collectKeys}}` : ", {}";
|
|
19618
|
+
const collected = await tx.run(
|
|
19619
|
+
`MATCH (c) WHERE elementId(c) = $eid
|
|
19620
|
+
MATCH (m:Message)-[:PART_OF]->(c)
|
|
19621
|
+
WHERE NOT m:Trashed
|
|
19622
|
+
RETURN elementId(m) AS meid${collectMsgProps} AS keys`,
|
|
19623
|
+
{ eid: elementId }
|
|
19624
|
+
);
|
|
19625
|
+
for (const rec of collected.records) {
|
|
19626
|
+
const meid = rec.get("meid");
|
|
19627
|
+
const keys = rec.get("keys");
|
|
19628
|
+
const liveKeys = {};
|
|
19629
|
+
for (const k of messageUniqueKeys) {
|
|
19630
|
+
if (keys[k] !== void 0 && keys[k] !== null) liveKeys[k] = keys[k];
|
|
19631
|
+
}
|
|
19632
|
+
const msgSetNulls = Object.keys(liveKeys).length > 0 ? ", " + Object.keys(liveKeys).map((k) => `m.\`${k}\` = null`).join(", ") : "";
|
|
19633
|
+
await tx.run(
|
|
19634
|
+
`MATCH (m) WHERE elementId(m) = $meid
|
|
19635
|
+
SET m:Trashed,
|
|
19636
|
+
m.trashedAt = datetime($trashedAt),
|
|
19637
|
+
m.trashedBy = $by,
|
|
19638
|
+
m.trashReason = $reason,
|
|
19639
|
+
m._trashedKeys = $trashedKeysJson${msgSetNulls}`,
|
|
19640
|
+
{
|
|
19641
|
+
meid,
|
|
19642
|
+
trashedAt,
|
|
19643
|
+
by: `${by}:cascade-from-conversation`,
|
|
19644
|
+
reason: reason ?? `cascade from Conversation ${elementId}`,
|
|
19645
|
+
trashedKeysJson: JSON.stringify(liveKeys)
|
|
19646
|
+
}
|
|
19647
|
+
);
|
|
19648
|
+
}
|
|
19649
|
+
cascadedMessageCount = collected.records.length;
|
|
19505
19650
|
}
|
|
19506
|
-
);
|
|
19651
|
+
});
|
|
19507
19652
|
process.stderr.write(
|
|
19508
19653
|
`[trash:marked] accountId=${accountId} elementId=${elementId} labels=${baseLabels.join(",")} by=${by} reason=${reason ?? "null"}
|
|
19509
19654
|
`
|
|
19510
19655
|
);
|
|
19656
|
+
if (isConversation) {
|
|
19657
|
+
process.stderr.write(
|
|
19658
|
+
`[trash:cascaded] accountId=${accountId} conversationElementId=${elementId} messageCount=${cascadedMessageCount} by=${by}
|
|
19659
|
+
`
|
|
19660
|
+
);
|
|
19661
|
+
}
|
|
19511
19662
|
return {
|
|
19512
19663
|
trashed: true,
|
|
19513
19664
|
alreadyTrashed: false,
|
|
@@ -19558,16 +19709,50 @@ async function restoreNode(params) {
|
|
|
19558
19709
|
const setSuffix = setClauses ? `, ${setClauses}` : "";
|
|
19559
19710
|
const setParams = { eid: elementId };
|
|
19560
19711
|
for (const [k, v] of Object.entries(originalKeys)) setParams[`val_${k}`] = v;
|
|
19561
|
-
|
|
19562
|
-
|
|
19563
|
-
|
|
19564
|
-
|
|
19565
|
-
|
|
19566
|
-
|
|
19712
|
+
const isConversation = baseLabels.includes("Conversation");
|
|
19713
|
+
let cascadedMessageCount = 0;
|
|
19714
|
+
await session.executeWrite(async (tx) => {
|
|
19715
|
+
await tx.run(
|
|
19716
|
+
`MATCH (n:Trashed) WHERE elementId(n) = $eid
|
|
19717
|
+
REMOVE n:Trashed, n.trashedAt, n.trashedBy, n.trashReason, n._trashedKeys
|
|
19718
|
+
SET n.restoredAt = datetime()${setSuffix}`,
|
|
19719
|
+
setParams
|
|
19720
|
+
);
|
|
19721
|
+
if (isConversation) {
|
|
19722
|
+
const collected = await tx.run(
|
|
19723
|
+
`MATCH (c) WHERE elementId(c) = $eid
|
|
19724
|
+
MATCH (m:Trashed:Message)-[:PART_OF]->(c)
|
|
19725
|
+
WHERE m.trashedBy ENDS WITH ':cascade-from-conversation'
|
|
19726
|
+
RETURN elementId(m) AS meid, m._trashedKeys AS keysJson`,
|
|
19727
|
+
{ eid: elementId }
|
|
19728
|
+
);
|
|
19729
|
+
for (const rec of collected.records) {
|
|
19730
|
+
const meid = rec.get("meid");
|
|
19731
|
+
const keysJson2 = rec.get("keysJson");
|
|
19732
|
+
const keys = keysJson2 ? JSON.parse(keysJson2) : {};
|
|
19733
|
+
const setClause = Object.keys(keys).length > 0 ? ", " + Object.keys(keys).map((k) => `m.\`${k}\` = $val_${k}`).join(", ") : "";
|
|
19734
|
+
const msgParams = { meid };
|
|
19735
|
+
for (const [k, v] of Object.entries(keys)) msgParams[`val_${k}`] = v;
|
|
19736
|
+
await tx.run(
|
|
19737
|
+
`MATCH (m) WHERE elementId(m) = $meid
|
|
19738
|
+
REMOVE m:Trashed, m.trashedAt, m.trashedBy, m.trashReason, m._trashedKeys
|
|
19739
|
+
SET m.restoredAt = datetime()${setClause}`,
|
|
19740
|
+
msgParams
|
|
19741
|
+
);
|
|
19742
|
+
}
|
|
19743
|
+
cascadedMessageCount = collected.records.length;
|
|
19744
|
+
}
|
|
19745
|
+
});
|
|
19567
19746
|
process.stderr.write(
|
|
19568
19747
|
`[trash:restored] accountId=${accountId} elementId=${elementId} labels=${baseLabels.join(",")}
|
|
19569
19748
|
`
|
|
19570
19749
|
);
|
|
19750
|
+
if (isConversation) {
|
|
19751
|
+
process.stderr.write(
|
|
19752
|
+
`[trash:cascade-restored] accountId=${accountId} conversationElementId=${elementId} messageCount=${cascadedMessageCount}
|
|
19753
|
+
`
|
|
19754
|
+
);
|
|
19755
|
+
}
|
|
19571
19756
|
return {
|
|
19572
19757
|
restored: true,
|
|
19573
19758
|
nodeId: elementId,
|
|
@@ -20825,7 +21010,7 @@ if (BRAND_JSON_PATH && !existsSync23(BRAND_JSON_PATH)) {
|
|
|
20825
21010
|
}
|
|
20826
21011
|
if (BRAND_JSON_PATH && existsSync23(BRAND_JSON_PATH)) {
|
|
20827
21012
|
try {
|
|
20828
|
-
const parsed = JSON.parse(
|
|
21013
|
+
const parsed = JSON.parse(readFileSync25(BRAND_JSON_PATH, "utf-8"));
|
|
20829
21014
|
BRAND = { ...BRAND, ...parsed };
|
|
20830
21015
|
} catch (err) {
|
|
20831
21016
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -20848,7 +21033,7 @@ var ALIAS_DOMAINS_PATH2 = join12(homedir4(), BRAND.configDir, "alias-domains.jso
|
|
|
20848
21033
|
function loadAliasDomains() {
|
|
20849
21034
|
try {
|
|
20850
21035
|
if (!existsSync23(ALIAS_DOMAINS_PATH2)) return null;
|
|
20851
|
-
const parsed = JSON.parse(
|
|
21036
|
+
const parsed = JSON.parse(readFileSync25(ALIAS_DOMAINS_PATH2, "utf-8"));
|
|
20852
21037
|
if (!Array.isArray(parsed)) {
|
|
20853
21038
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
20854
21039
|
return null;
|
|
@@ -20973,10 +21158,7 @@ app35.post("/__remote-auth/login", async (c) => {
|
|
|
20973
21158
|
}
|
|
20974
21159
|
});
|
|
20975
21160
|
});
|
|
20976
|
-
app35.get("/__remote-auth/logout", (
|
|
20977
|
-
const cookieHeader = c.req.header("cookie");
|
|
20978
|
-
const token = parseCookie(cookieHeader, "__remote_session");
|
|
20979
|
-
if (token) invalidateRemoteSession(token);
|
|
21161
|
+
app35.get("/__remote-auth/logout", () => {
|
|
20980
21162
|
return new Response(null, {
|
|
20981
21163
|
status: 302,
|
|
20982
21164
|
headers: {
|
|
@@ -21142,16 +21324,6 @@ app35.use("*", async (c, next) => {
|
|
|
21142
21324
|
console.error(`[remote-auth] login required ip=${clientIp} path=${path2}`);
|
|
21143
21325
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), redirect: path2 }), 200);
|
|
21144
21326
|
});
|
|
21145
|
-
function parseCookie(cookieHeader, name) {
|
|
21146
|
-
if (!cookieHeader) return null;
|
|
21147
|
-
const match2 = cookieHeader.match(new RegExp(`(?:^|;\\s*)${name}=([^;]*)`));
|
|
21148
|
-
if (!match2) return null;
|
|
21149
|
-
try {
|
|
21150
|
-
return decodeURIComponent(match2[1]);
|
|
21151
|
-
} catch {
|
|
21152
|
-
return null;
|
|
21153
|
-
}
|
|
21154
|
-
}
|
|
21155
21327
|
app35.route("/api/health", health_default);
|
|
21156
21328
|
app35.route("/api/session", session_default);
|
|
21157
21329
|
app35.route("/api/chat", chat_default);
|
|
@@ -21201,7 +21373,7 @@ app35.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
21201
21373
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
21202
21374
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
21203
21375
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
21204
|
-
const body =
|
|
21376
|
+
const body = readFileSync25(filePath);
|
|
21205
21377
|
return c.body(body, 200, {
|
|
21206
21378
|
"Content-Type": contentType,
|
|
21207
21379
|
"Cache-Control": "public, max-age=3600"
|
|
@@ -21231,7 +21403,7 @@ app35.get("/generated/:filename", (c) => {
|
|
|
21231
21403
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
21232
21404
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
21233
21405
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
21234
|
-
const body =
|
|
21406
|
+
const body = readFileSync25(filePath);
|
|
21235
21407
|
return c.body(body, 200, {
|
|
21236
21408
|
"Content-Type": contentType,
|
|
21237
21409
|
"Cache-Control": "public, max-age=86400"
|
|
@@ -21242,7 +21414,7 @@ var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
|
21242
21414
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
21243
21415
|
if (BRAND_JSON_PATH && existsSync23(BRAND_JSON_PATH)) {
|
|
21244
21416
|
try {
|
|
21245
|
-
const fullBrand = JSON.parse(
|
|
21417
|
+
const fullBrand = JSON.parse(readFileSync25(BRAND_JSON_PATH, "utf-8"));
|
|
21246
21418
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
21247
21419
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
21248
21420
|
} catch {
|
|
@@ -21261,7 +21433,7 @@ function readInstalledVersion() {
|
|
|
21261
21433
|
if (!PLATFORM_ROOT10) return "unknown";
|
|
21262
21434
|
const versionFile = join12(PLATFORM_ROOT10, "config", `.${BRAND.hostname}-version`);
|
|
21263
21435
|
if (!existsSync23(versionFile)) return "unknown";
|
|
21264
|
-
const content =
|
|
21436
|
+
const content = readFileSync25(versionFile, "utf-8").trim();
|
|
21265
21437
|
return content || "unknown";
|
|
21266
21438
|
} catch {
|
|
21267
21439
|
return "unknown";
|
|
@@ -21302,7 +21474,7 @@ var clientErrorReporterScript = `<script>
|
|
|
21302
21474
|
function cachedHtml(file) {
|
|
21303
21475
|
let html = htmlCache.get(file);
|
|
21304
21476
|
if (!html) {
|
|
21305
|
-
html =
|
|
21477
|
+
html = readFileSync25(resolve27(process.cwd(), "public", file), "utf-8");
|
|
21306
21478
|
html = html.replace("<title>Maxy</title>", `<title>${escapeHtml(BRAND.productName)}</title>`);
|
|
21307
21479
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
21308
21480
|
const headInjection = file === "index.html" ? `${brandScript}
|
|
@@ -21321,12 +21493,12 @@ function loadBrandingCache(agentSlug) {
|
|
|
21321
21493
|
try {
|
|
21322
21494
|
const accountJsonPath = join12(configDir2, "account.json");
|
|
21323
21495
|
if (!existsSync23(accountJsonPath)) return null;
|
|
21324
|
-
const account = JSON.parse(
|
|
21496
|
+
const account = JSON.parse(readFileSync25(accountJsonPath, "utf-8"));
|
|
21325
21497
|
const accountId = account.accountId;
|
|
21326
21498
|
if (!accountId) return null;
|
|
21327
21499
|
const cachePath = join12(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
21328
21500
|
if (!existsSync23(cachePath)) return null;
|
|
21329
|
-
return JSON.parse(
|
|
21501
|
+
return JSON.parse(readFileSync25(cachePath, "utf-8"));
|
|
21330
21502
|
} catch {
|
|
21331
21503
|
return null;
|
|
21332
21504
|
}
|
|
@@ -21336,7 +21508,7 @@ function resolveDefaultSlug() {
|
|
|
21336
21508
|
const configDir2 = join12(homedir4(), BRAND.configDir);
|
|
21337
21509
|
const accountJsonPath = join12(configDir2, "account.json");
|
|
21338
21510
|
if (!existsSync23(accountJsonPath)) return null;
|
|
21339
|
-
const account = JSON.parse(
|
|
21511
|
+
const account = JSON.parse(readFileSync25(accountJsonPath, "utf-8"));
|
|
21340
21512
|
return account.defaultAgent || null;
|
|
21341
21513
|
} catch {
|
|
21342
21514
|
return null;
|
|
@@ -21409,7 +21581,7 @@ app35.use("/vnc-popout.html", logViewerFetch);
|
|
|
21409
21581
|
app35.get("/vnc-popout.html", (c) => {
|
|
21410
21582
|
let html = htmlCache.get("vnc-popout.html");
|
|
21411
21583
|
if (!html) {
|
|
21412
|
-
html =
|
|
21584
|
+
html = readFileSync25(resolve27(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
21413
21585
|
const name = escapeHtml(BRAND.productName);
|
|
21414
21586
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
21415
21587
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -21500,7 +21672,7 @@ try {
|
|
|
21500
21672
|
try {
|
|
21501
21673
|
let userId = "";
|
|
21502
21674
|
if (existsSync23(USERS_FILE)) {
|
|
21503
|
-
const users = JSON.parse(
|
|
21675
|
+
const users = JSON.parse(readFileSync25(USERS_FILE, "utf-8").trim() || "[]");
|
|
21504
21676
|
userId = users[0]?.userId ?? "";
|
|
21505
21677
|
}
|
|
21506
21678
|
await backfillNullUserIdConversations(userId);
|