@rubytech/create-maxy 1.0.477 → 1.0.478
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/payload/platform/neo4j/schema.cypher +23 -0
- package/payload/platform/plugins/anthropic/PLUGIN.md +3 -2
- package/payload/platform/plugins/anthropic/references/console-api.md +186 -0
- package/payload/platform/plugins/anthropic/references/setup-guide.md +3 -3
- package/payload/platform/plugins/anthropic/skills/get-api-key/SKILL.md +89 -20
- package/payload/platform/scripts/seed-neo4j.sh +92 -0
- package/payload/platform/templates/account.json +2 -1
- package/payload/server/public/assets/ChatInput-DNdZ2WD7.css +1 -0
- package/payload/server/public/assets/{admin-DpmnCxNk.js → admin-DLtY5oYr.js} +6 -6
- package/payload/server/public/assets/{public-BBxDqQvQ.js → public-B27jukY6.js} +1 -1
- package/payload/server/public/index.html +3 -3
- package/payload/server/public/public.html +3 -3
- package/payload/server/server.js +162 -73
- package/payload/server/public/assets/ChatInput-sDYraTun.css +0 -1
- /package/payload/server/public/assets/{ChatInput-DZ0j0Gdp.js → ChatInput-BWyEqP0k.js} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -2877,6 +2877,8 @@ if (platformRoot) {
|
|
|
2877
2877
|
}
|
|
2878
2878
|
var MAXY_DIR = resolve(homedir(), configDirName);
|
|
2879
2879
|
var PIN_FILE = resolve(MAXY_DIR, ".admin-pin");
|
|
2880
|
+
var PLATFORM_ROOT = process.env.MAXY_PLATFORM_ROOT ?? resolve(process.cwd(), "..");
|
|
2881
|
+
var USERS_FILE = resolve(PLATFORM_ROOT, "config", "users.json");
|
|
2880
2882
|
var LOG_DIR = resolve(MAXY_DIR, "logs");
|
|
2881
2883
|
var BIN_DIR = resolve(MAXY_DIR, "bin");
|
|
2882
2884
|
var API_KEY_FILE = resolve(MAXY_DIR, ".anthropic-api-key");
|
|
@@ -3144,8 +3146,8 @@ import { spawnSync, execFileSync } from "child_process";
|
|
|
3144
3146
|
import { createConnection as createConnection2 } from "net";
|
|
3145
3147
|
import { mkdirSync, writeFileSync as writeFileSync2 } from "fs";
|
|
3146
3148
|
import { resolve as resolve2 } from "path";
|
|
3147
|
-
var
|
|
3148
|
-
var VNC_SCRIPT = resolve2(
|
|
3149
|
+
var PLATFORM_ROOT2 = process.env.MAXY_PLATFORM_ROOT ?? resolve2(process.cwd(), "..");
|
|
3150
|
+
var VNC_SCRIPT = resolve2(PLATFORM_ROOT2, "scripts/vnc.sh");
|
|
3149
3151
|
function sleep(ms) {
|
|
3150
3152
|
return new Promise((r) => setTimeout(r, ms));
|
|
3151
3153
|
}
|
|
@@ -3277,11 +3279,11 @@ import { randomUUID } from "crypto";
|
|
|
3277
3279
|
import { spawn } from "child_process";
|
|
3278
3280
|
import { readFileSync as readFileSync4 } from "fs";
|
|
3279
3281
|
import { resolve as resolve3 } from "path";
|
|
3280
|
-
var
|
|
3282
|
+
var PLATFORM_ROOT3 = process.env.MAXY_PLATFORM_ROOT ?? resolve3(process.cwd(), "..");
|
|
3281
3283
|
var driver = null;
|
|
3282
3284
|
function readPassword() {
|
|
3283
3285
|
if (process.env.NEO4J_PASSWORD) return process.env.NEO4J_PASSWORD;
|
|
3284
|
-
const passwordFile = resolve3(
|
|
3286
|
+
const passwordFile = resolve3(PLATFORM_ROOT3, "config/.neo4j-password");
|
|
3285
3287
|
try {
|
|
3286
3288
|
return readFileSync4(passwordFile, "utf-8").trim();
|
|
3287
3289
|
} catch {
|
|
@@ -4270,11 +4272,11 @@ function agentLogStream(name, accountDir) {
|
|
|
4270
4272
|
}
|
|
4271
4273
|
return createWriteStream(resolve4(logDir, `${name}-${date5}.log`), { flags: "a" });
|
|
4272
4274
|
}
|
|
4273
|
-
var
|
|
4274
|
-
var ACCOUNTS_DIR = resolve4(
|
|
4275
|
-
if (!existsSync5(
|
|
4275
|
+
var PLATFORM_ROOT4 = process.env.MAXY_PLATFORM_ROOT ?? resolve4(process.cwd(), "..");
|
|
4276
|
+
var ACCOUNTS_DIR = resolve4(PLATFORM_ROOT4, "..", "data/accounts");
|
|
4277
|
+
if (!existsSync5(PLATFORM_ROOT4)) {
|
|
4276
4278
|
throw new Error(
|
|
4277
|
-
`PLATFORM_ROOT does not exist: ${
|
|
4279
|
+
`PLATFORM_ROOT does not exist: ${PLATFORM_ROOT4}
|
|
4278
4280
|
Set the MAXY_PLATFORM_ROOT environment variable to the absolute path of the platform directory.`
|
|
4279
4281
|
);
|
|
4280
4282
|
}
|
|
@@ -4452,7 +4454,7 @@ function resolveAgentConfig(accountDir, agentName) {
|
|
|
4452
4454
|
return { model, plugins, status, displayName, image, imageShape, showAgentName, knowledge, knowledgeBaked, liveMemory, knowledgeKeywords, budget, accessMode };
|
|
4453
4455
|
}
|
|
4454
4456
|
function parsePluginFrontmatter(pluginDir) {
|
|
4455
|
-
const pluginPath = resolve4(
|
|
4457
|
+
const pluginPath = resolve4(PLATFORM_ROOT4, "plugins", pluginDir, "PLUGIN.md");
|
|
4456
4458
|
if (!existsSync5(pluginPath)) return null;
|
|
4457
4459
|
let raw2;
|
|
4458
4460
|
try {
|
|
@@ -4513,7 +4515,7 @@ function parsePluginFrontmatter(pluginDir) {
|
|
|
4513
4515
|
};
|
|
4514
4516
|
}
|
|
4515
4517
|
function assemblePublicPluginContent(pluginDir) {
|
|
4516
|
-
const pluginRoot = resolve4(
|
|
4518
|
+
const pluginRoot = resolve4(PLATFORM_ROOT4, "plugins", pluginDir);
|
|
4517
4519
|
const pluginPath = resolve4(pluginRoot, "PLUGIN.md");
|
|
4518
4520
|
let raw2;
|
|
4519
4521
|
try {
|
|
@@ -4607,7 +4609,7 @@ function assemblePublicPluginContent(pluginDir) {
|
|
|
4607
4609
|
return { body: parts.join("\n"), skillCount, refCount };
|
|
4608
4610
|
}
|
|
4609
4611
|
function loadEmbeddedPlugins(agentType, selectedPlugins, enabledPlugins) {
|
|
4610
|
-
const pluginsDir = resolve4(
|
|
4612
|
+
const pluginsDir = resolve4(PLATFORM_ROOT4, "plugins");
|
|
4611
4613
|
let dirs;
|
|
4612
4614
|
try {
|
|
4613
4615
|
dirs = readdirSync(pluginsDir);
|
|
@@ -4687,14 +4689,14 @@ var mcpToolsCache = /* @__PURE__ */ new Map();
|
|
|
4687
4689
|
function fetchMcpToolsList(pluginDir) {
|
|
4688
4690
|
const cached2 = mcpToolsCache.get(pluginDir);
|
|
4689
4691
|
if (cached2) return Promise.resolve(cached2);
|
|
4690
|
-
const serverPath = resolve4(
|
|
4692
|
+
const serverPath = resolve4(PLATFORM_ROOT4, "plugins", pluginDir, "mcp/dist/index.js");
|
|
4691
4693
|
if (!existsSync5(serverPath)) return Promise.resolve([]);
|
|
4692
4694
|
const startMs = Date.now();
|
|
4693
4695
|
return new Promise((resolvePromise) => {
|
|
4694
4696
|
const proc = spawn2(process.execPath, [serverPath], {
|
|
4695
4697
|
env: {
|
|
4696
4698
|
...process.env,
|
|
4697
|
-
PLATFORM_ROOT:
|
|
4699
|
+
PLATFORM_ROOT: PLATFORM_ROOT4,
|
|
4698
4700
|
ACCOUNT_ID: "__toolslist__",
|
|
4699
4701
|
PLATFORM_PORT: process.env.PORT ?? "19200"
|
|
4700
4702
|
}
|
|
@@ -4778,7 +4780,7 @@ function fetchMcpToolsList(pluginDir) {
|
|
|
4778
4780
|
});
|
|
4779
4781
|
}
|
|
4780
4782
|
async function buildPluginManifest(enabledPlugins) {
|
|
4781
|
-
const pluginsDir = resolve4(
|
|
4783
|
+
const pluginsDir = resolve4(PLATFORM_ROOT4, "plugins");
|
|
4782
4784
|
let dirs;
|
|
4783
4785
|
try {
|
|
4784
4786
|
dirs = readdirSync(pluginsDir);
|
|
@@ -4849,7 +4851,7 @@ async function buildPluginManifest(enabledPlugins) {
|
|
|
4849
4851
|
toolLines.push(desc ? ` ${tool.name} \u2014 ${desc}` : ` ${tool.name}`);
|
|
4850
4852
|
}
|
|
4851
4853
|
} else if (parsed.tools.length > 0) {
|
|
4852
|
-
const serverPath = resolve4(
|
|
4854
|
+
const serverPath = resolve4(PLATFORM_ROOT4, "plugins", dir, "mcp/dist/index.js");
|
|
4853
4855
|
if (existsSync5(serverPath)) {
|
|
4854
4856
|
fallbackSourced++;
|
|
4855
4857
|
console.error(`[plugin-manifest] ${dir}: tools/list empty \u2014 fallback to frontmatter (${parsed.tools.length} tools)`);
|
|
@@ -4924,10 +4926,37 @@ function validateComponentData(componentName, data) {
|
|
|
4924
4926
|
function getDefaultAccountId() {
|
|
4925
4927
|
return resolveAccount()?.accountId ?? null;
|
|
4926
4928
|
}
|
|
4929
|
+
function resolveUserAccounts(userId) {
|
|
4930
|
+
if (!existsSync5(ACCOUNTS_DIR)) return [];
|
|
4931
|
+
const results = [];
|
|
4932
|
+
const entries = readdirSync(ACCOUNTS_DIR, { withFileTypes: true });
|
|
4933
|
+
for (const entry of entries) {
|
|
4934
|
+
if (!entry.isDirectory()) continue;
|
|
4935
|
+
const configPath2 = resolve4(ACCOUNTS_DIR, entry.name, "account.json");
|
|
4936
|
+
if (!existsSync5(configPath2)) continue;
|
|
4937
|
+
let config2;
|
|
4938
|
+
try {
|
|
4939
|
+
config2 = JSON.parse(readFileSync5(configPath2, "utf-8"));
|
|
4940
|
+
} catch {
|
|
4941
|
+
console.error(`[session] account.json corrupt at ${configPath2} \u2014 skipping`);
|
|
4942
|
+
continue;
|
|
4943
|
+
}
|
|
4944
|
+
const adminEntry = config2.admins?.find((a) => a.userId === userId);
|
|
4945
|
+
if (adminEntry) {
|
|
4946
|
+
results.push({
|
|
4947
|
+
accountId: config2.accountId,
|
|
4948
|
+
accountDir: resolve4(ACCOUNTS_DIR, entry.name),
|
|
4949
|
+
config: config2,
|
|
4950
|
+
role: adminEntry.role
|
|
4951
|
+
});
|
|
4952
|
+
}
|
|
4953
|
+
}
|
|
4954
|
+
return results;
|
|
4955
|
+
}
|
|
4927
4956
|
var sessionStore = /* @__PURE__ */ new Map();
|
|
4928
4957
|
setSessionStoreRef(sessionStore);
|
|
4929
|
-
function registerSession(sessionKey, agentType, accountId, agentName) {
|
|
4930
|
-
sessionStore.set(sessionKey, { createdAt: Date.now(), agentType, accountId, agentName });
|
|
4958
|
+
function registerSession(sessionKey, agentType, accountId, agentName, userId, userName) {
|
|
4959
|
+
sessionStore.set(sessionKey, { createdAt: Date.now(), agentType, accountId, agentName, userId, userName });
|
|
4931
4960
|
}
|
|
4932
4961
|
function registerResumedSession(sessionKey, accountId, agentName, conversationId, messages) {
|
|
4933
4962
|
const messageHistory = messages.map((m) => ({
|
|
@@ -5076,38 +5105,38 @@ function getMcpServers(accountId, enabledPlugins) {
|
|
|
5076
5105
|
const servers = {
|
|
5077
5106
|
"memory": {
|
|
5078
5107
|
command: "node",
|
|
5079
|
-
args: [resolve4(
|
|
5080
|
-
env: { ACCOUNT_ID: accountId, PLATFORM_ROOT:
|
|
5108
|
+
args: [resolve4(PLATFORM_ROOT4, "plugins/memory/mcp/dist/index.js")],
|
|
5109
|
+
env: { ACCOUNT_ID: accountId, PLATFORM_ROOT: PLATFORM_ROOT4 }
|
|
5081
5110
|
},
|
|
5082
5111
|
"contacts": {
|
|
5083
5112
|
command: "node",
|
|
5084
|
-
args: [resolve4(
|
|
5085
|
-
env: { ACCOUNT_ID: accountId, PLATFORM_ROOT:
|
|
5113
|
+
args: [resolve4(PLATFORM_ROOT4, "plugins/contacts/mcp/dist/index.js")],
|
|
5114
|
+
env: { ACCOUNT_ID: accountId, PLATFORM_ROOT: PLATFORM_ROOT4 }
|
|
5086
5115
|
},
|
|
5087
5116
|
"whatsapp": {
|
|
5088
5117
|
command: "node",
|
|
5089
|
-
args: [resolve4(
|
|
5090
|
-
env: { ACCOUNT_ID: accountId, PLATFORM_ROOT:
|
|
5118
|
+
args: [resolve4(PLATFORM_ROOT4, "plugins/whatsapp/mcp/dist/index.js")],
|
|
5119
|
+
env: { ACCOUNT_ID: accountId, PLATFORM_ROOT: PLATFORM_ROOT4, PLATFORM_PORT: process.env.PORT ?? "19200" }
|
|
5091
5120
|
},
|
|
5092
5121
|
"admin": {
|
|
5093
5122
|
command: "node",
|
|
5094
|
-
args: [resolve4(
|
|
5095
|
-
env: { ACCOUNT_ID: accountId, PLATFORM_ROOT:
|
|
5123
|
+
args: [resolve4(PLATFORM_ROOT4, "plugins/admin/mcp/dist/index.js")],
|
|
5124
|
+
env: { ACCOUNT_ID: accountId, PLATFORM_ROOT: PLATFORM_ROOT4, PLATFORM_PORT: process.env.PORT ?? "19200" }
|
|
5096
5125
|
},
|
|
5097
5126
|
"scheduling": {
|
|
5098
5127
|
command: "node",
|
|
5099
|
-
args: [resolve4(
|
|
5100
|
-
env: { ACCOUNT_ID: accountId, PLATFORM_ROOT:
|
|
5128
|
+
args: [resolve4(PLATFORM_ROOT4, "plugins/scheduling/mcp/dist/index.js")],
|
|
5129
|
+
env: { ACCOUNT_ID: accountId, PLATFORM_ROOT: PLATFORM_ROOT4 }
|
|
5101
5130
|
},
|
|
5102
5131
|
"tasks": {
|
|
5103
5132
|
command: "node",
|
|
5104
|
-
args: [resolve4(
|
|
5105
|
-
env: { ACCOUNT_ID: accountId, PLATFORM_ROOT:
|
|
5133
|
+
args: [resolve4(PLATFORM_ROOT4, "plugins/tasks/mcp/dist/index.js")],
|
|
5134
|
+
env: { ACCOUNT_ID: accountId, PLATFORM_ROOT: PLATFORM_ROOT4 }
|
|
5106
5135
|
},
|
|
5107
5136
|
"email": {
|
|
5108
5137
|
command: "node",
|
|
5109
|
-
args: [resolve4(
|
|
5110
|
-
env: { ACCOUNT_ID: accountId, PLATFORM_ROOT:
|
|
5138
|
+
args: [resolve4(PLATFORM_ROOT4, "plugins/email/mcp/dist/index.js")],
|
|
5139
|
+
env: { ACCOUNT_ID: accountId, PLATFORM_ROOT: PLATFORM_ROOT4 }
|
|
5111
5140
|
},
|
|
5112
5141
|
// Playwright MCP server — browser automation for browser-specialist.
|
|
5113
5142
|
// Key matches Claude Code's plugin naming: plugin_{plugin}_{server} so tools
|
|
@@ -5123,8 +5152,8 @@ function getMcpServers(accountId, enabledPlugins) {
|
|
|
5123
5152
|
if (process.env.TELEGRAM_PUBLIC_BOT_TOKEN) {
|
|
5124
5153
|
servers["telegram"] = {
|
|
5125
5154
|
command: "node",
|
|
5126
|
-
args: [resolve4(
|
|
5127
|
-
env: { ACCOUNT_ID: accountId, PLATFORM_ROOT:
|
|
5155
|
+
args: [resolve4(PLATFORM_ROOT4, "plugins/telegram/mcp/dist/index.js")],
|
|
5156
|
+
env: { ACCOUNT_ID: accountId, PLATFORM_ROOT: PLATFORM_ROOT4 }
|
|
5128
5157
|
};
|
|
5129
5158
|
} else {
|
|
5130
5159
|
console.error("[plugins] telegram MCP: skipped (no TELEGRAM_PUBLIC_BOT_TOKEN)");
|
|
@@ -5141,14 +5170,14 @@ function getMcpServers(accountId, enabledPlugins) {
|
|
|
5141
5170
|
if (!tunnelConfigured) {
|
|
5142
5171
|
servers["cloudflare"] = {
|
|
5143
5172
|
command: "node",
|
|
5144
|
-
args: [resolve4(
|
|
5145
|
-
env: { PLATFORM_ROOT:
|
|
5173
|
+
args: [resolve4(PLATFORM_ROOT4, "plugins/cloudflare/mcp/dist/index.js")],
|
|
5174
|
+
env: { PLATFORM_ROOT: PLATFORM_ROOT4 }
|
|
5146
5175
|
};
|
|
5147
5176
|
} else {
|
|
5148
5177
|
console.error("[plugins] cloudflare MCP: skipped (tunnel already configured)");
|
|
5149
5178
|
}
|
|
5150
5179
|
if (Array.isArray(enabledPlugins) && enabledPlugins.length > 0) {
|
|
5151
|
-
const pluginsDir = resolve4(
|
|
5180
|
+
const pluginsDir = resolve4(PLATFORM_ROOT4, "plugins");
|
|
5152
5181
|
let dirs;
|
|
5153
5182
|
try {
|
|
5154
5183
|
dirs = readdirSync(pluginsDir);
|
|
@@ -5171,12 +5200,12 @@ function getMcpServers(accountId, enabledPlugins) {
|
|
|
5171
5200
|
continue;
|
|
5172
5201
|
}
|
|
5173
5202
|
}
|
|
5174
|
-
const mcpEntry = resolve4(
|
|
5203
|
+
const mcpEntry = resolve4(PLATFORM_ROOT4, "plugins", dir, "mcp/dist/index.js");
|
|
5175
5204
|
if (!existsSync5(mcpEntry)) continue;
|
|
5176
5205
|
servers[dir] = {
|
|
5177
5206
|
command: "node",
|
|
5178
5207
|
args: [mcpEntry],
|
|
5179
|
-
env: { ACCOUNT_ID: accountId, PLATFORM_ROOT:
|
|
5208
|
+
env: { ACCOUNT_ID: accountId, PLATFORM_ROOT: PLATFORM_ROOT4 }
|
|
5180
5209
|
};
|
|
5181
5210
|
console.log(`[plugins] optional MCP server started: ${dir}`);
|
|
5182
5211
|
}
|
|
@@ -5265,7 +5294,7 @@ var ADMIN_CORE_TOOLS = [
|
|
|
5265
5294
|
function getAdminAllowedTools(enabledPlugins) {
|
|
5266
5295
|
const tools = [...ADMIN_CORE_TOOLS];
|
|
5267
5296
|
if (Array.isArray(enabledPlugins) && enabledPlugins.length > 0) {
|
|
5268
|
-
const pluginsDir = resolve4(
|
|
5297
|
+
const pluginsDir = resolve4(PLATFORM_ROOT4, "plugins");
|
|
5269
5298
|
let dirs;
|
|
5270
5299
|
try {
|
|
5271
5300
|
dirs = readdirSync(pluginsDir);
|
|
@@ -5358,7 +5387,7 @@ ${message.slice(0, QUERY_CLASSIFIER_MSG_CAP)}`
|
|
|
5358
5387
|
}
|
|
5359
5388
|
}
|
|
5360
5389
|
async function fetchMemoryContext(accountId, query, sessionKey, options) {
|
|
5361
|
-
const serverPath = resolve4(
|
|
5390
|
+
const serverPath = resolve4(PLATFORM_ROOT4, "plugins/memory/mcp/dist/index.js");
|
|
5362
5391
|
if (!existsSync5(serverPath)) {
|
|
5363
5392
|
console.error(`[fetchMemoryContext] MCP server not found: ${serverPath}`);
|
|
5364
5393
|
return null;
|
|
@@ -5369,7 +5398,7 @@ async function fetchMemoryContext(accountId, query, sessionKey, options) {
|
|
|
5369
5398
|
env: {
|
|
5370
5399
|
...process.env,
|
|
5371
5400
|
ACCOUNT_ID: accountId,
|
|
5372
|
-
PLATFORM_ROOT:
|
|
5401
|
+
PLATFORM_ROOT: PLATFORM_ROOT4,
|
|
5373
5402
|
READ_ONLY: "true",
|
|
5374
5403
|
ALLOWED_SCOPES: "public,shared",
|
|
5375
5404
|
...sessionKey ? { SESSION_ID: sessionKey } : {},
|
|
@@ -5456,7 +5485,7 @@ async function fetchMemoryContext(accountId, query, sessionKey, options) {
|
|
|
5456
5485
|
}
|
|
5457
5486
|
async function compactTrimmedMessages(accountId, trimmedMessages) {
|
|
5458
5487
|
if (trimmedMessages.length === 0) return true;
|
|
5459
|
-
const serverPath = resolve4(
|
|
5488
|
+
const serverPath = resolve4(PLATFORM_ROOT4, "plugins/memory/mcp/dist/index.js");
|
|
5460
5489
|
if (!existsSync5(serverPath)) return false;
|
|
5461
5490
|
const briefing = trimmedMessages.map((m) => `[${m.role.toUpperCase()}] ${m.content}`).join("\n\n");
|
|
5462
5491
|
return new Promise((resolvePromise) => {
|
|
@@ -5888,7 +5917,7 @@ async function* runCompactionTurn(accountDir, accountId, systemPrompt, resumeSes
|
|
|
5888
5917
|
const proc = spawn2("claude", args, {
|
|
5889
5918
|
cwd: accountDir,
|
|
5890
5919
|
stdio: ["ignore", "pipe", "pipe"],
|
|
5891
|
-
env: { ...process.env, PLATFORM_ROOT:
|
|
5920
|
+
env: { ...process.env, PLATFORM_ROOT: PLATFORM_ROOT4, ACCOUNT_DIR: accountDir }
|
|
5892
5921
|
});
|
|
5893
5922
|
const stderrLog = agentLogStream("claude-agent-compaction-stderr", accountDir);
|
|
5894
5923
|
proc.stderr?.pipe(stderrLog);
|
|
@@ -6529,7 +6558,7 @@ async function* invokeAdminAgent(message, systemPrompt, accountDir, accountId, a
|
|
|
6529
6558
|
const proc = spawn2("claude", args, {
|
|
6530
6559
|
cwd: accountDir,
|
|
6531
6560
|
stdio: ["ignore", "pipe", "pipe"],
|
|
6532
|
-
env: { ...process.env, PLATFORM_ROOT:
|
|
6561
|
+
env: { ...process.env, PLATFORM_ROOT: PLATFORM_ROOT4, ACCOUNT_DIR: accountDir }
|
|
6533
6562
|
});
|
|
6534
6563
|
const stderrLog = agentLogStream("claude-agent-stderr", accountDir);
|
|
6535
6564
|
proc.stderr?.pipe(stderrLog);
|
|
@@ -6778,7 +6807,7 @@ async function* invokeManagedAdminAgent(message, systemPrompt, accountDir, accou
|
|
|
6778
6807
|
const proc = spawn2("claude", args, {
|
|
6779
6808
|
cwd: accountDir,
|
|
6780
6809
|
stdio: ["ignore", "pipe", "pipe"],
|
|
6781
|
-
env: { ...process.env, PLATFORM_ROOT:
|
|
6810
|
+
env: { ...process.env, PLATFORM_ROOT: PLATFORM_ROOT4, ACCOUNT_DIR: accountDir }
|
|
6782
6811
|
});
|
|
6783
6812
|
const stderrLog = agentLogStream("claude-agent-stderr", accountDir);
|
|
6784
6813
|
proc.stderr?.pipe(stderrLog);
|
|
@@ -7606,8 +7635,8 @@ import { randomUUID as randomUUID2 } from "crypto";
|
|
|
7606
7635
|
import { mkdir, readFile, stat, writeFile } from "fs/promises";
|
|
7607
7636
|
import { realpathSync } from "fs";
|
|
7608
7637
|
import { resolve as resolve6, extname, basename } from "path";
|
|
7609
|
-
var
|
|
7610
|
-
var ATTACHMENTS_ROOT = resolve6(
|
|
7638
|
+
var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve6(process.cwd(), "../platform");
|
|
7639
|
+
var ATTACHMENTS_ROOT = resolve6(PLATFORM_ROOT5, "..", "data/uploads");
|
|
7611
7640
|
var SUPPORTED_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
7612
7641
|
"image/jpeg",
|
|
7613
7642
|
"image/png",
|
|
@@ -8463,11 +8492,11 @@ import neo4j2 from "neo4j-driver";
|
|
|
8463
8492
|
import { readFileSync as readFileSync7 } from "fs";
|
|
8464
8493
|
import { resolve as resolve7 } from "path";
|
|
8465
8494
|
import { randomUUID as randomUUID3, randomInt } from "crypto";
|
|
8466
|
-
var
|
|
8495
|
+
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve7(process.cwd(), "..");
|
|
8467
8496
|
var driver2 = null;
|
|
8468
8497
|
function readPassword2() {
|
|
8469
8498
|
if (process.env.NEO4J_PASSWORD) return process.env.NEO4J_PASSWORD;
|
|
8470
|
-
const passwordFile = resolve7(
|
|
8499
|
+
const passwordFile = resolve7(PLATFORM_ROOT6, "config/.neo4j-password");
|
|
8471
8500
|
try {
|
|
8472
8501
|
return readFileSync7(passwordFile, "utf-8").trim();
|
|
8473
8502
|
} catch {
|
|
@@ -25619,7 +25648,7 @@ import { readFile as readFile2, stat as stat2 } from "fs/promises";
|
|
|
25619
25648
|
import { realpathSync as realpathSync2 } from "fs";
|
|
25620
25649
|
import { resolve as resolve11, basename as basename2 } from "path";
|
|
25621
25650
|
var TAG11 = "[whatsapp:api]";
|
|
25622
|
-
var
|
|
25651
|
+
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
25623
25652
|
async function POST15(req) {
|
|
25624
25653
|
try {
|
|
25625
25654
|
const body = await req.json();
|
|
@@ -25628,13 +25657,13 @@ async function POST15(req) {
|
|
|
25628
25657
|
if (!to || !filePath) {
|
|
25629
25658
|
return Response.json({ error: "Missing required fields: to, filePath" }, { status: 400 });
|
|
25630
25659
|
}
|
|
25631
|
-
if (!maxyAccountId || !
|
|
25660
|
+
if (!maxyAccountId || !PLATFORM_ROOT7) {
|
|
25632
25661
|
return Response.json(
|
|
25633
25662
|
{ error: "Cannot validate file path: missing account or platform context" },
|
|
25634
25663
|
{ status: 400 }
|
|
25635
25664
|
);
|
|
25636
25665
|
}
|
|
25637
|
-
const accountDir = resolve11(
|
|
25666
|
+
const accountDir = resolve11(PLATFORM_ROOT7, "..", "data/accounts", maxyAccountId);
|
|
25638
25667
|
let resolvedPath;
|
|
25639
25668
|
try {
|
|
25640
25669
|
resolvedPath = realpathSync2(filePath);
|
|
@@ -25877,35 +25906,93 @@ function getStoredPinHash() {
|
|
|
25877
25906
|
}
|
|
25878
25907
|
return null;
|
|
25879
25908
|
}
|
|
25909
|
+
function readUsersFile() {
|
|
25910
|
+
if (!existsSync13(USERS_FILE)) return null;
|
|
25911
|
+
const raw2 = readFileSync13(USERS_FILE, "utf-8").trim();
|
|
25912
|
+
if (!raw2) return [];
|
|
25913
|
+
return JSON.parse(raw2);
|
|
25914
|
+
}
|
|
25880
25915
|
async function POST19(req) {
|
|
25881
|
-
const storedHash = getStoredPinHash();
|
|
25882
|
-
if (!storedHash) {
|
|
25883
|
-
return Response.json(
|
|
25884
|
-
{ error: "PIN not configured. Complete onboarding first." },
|
|
25885
|
-
{ status: 503 }
|
|
25886
|
-
);
|
|
25887
|
-
}
|
|
25888
25916
|
let body;
|
|
25889
25917
|
try {
|
|
25890
25918
|
body = await req.json();
|
|
25891
25919
|
} catch {
|
|
25892
25920
|
return Response.json({ error: "Invalid request" }, { status: 400 });
|
|
25893
25921
|
}
|
|
25922
|
+
if (!body.pin) {
|
|
25923
|
+
return Response.json({ error: "Invalid request" }, { status: 400 });
|
|
25924
|
+
}
|
|
25894
25925
|
const inputHash = hashPin2(body.pin);
|
|
25895
|
-
|
|
25926
|
+
let users = null;
|
|
25927
|
+
try {
|
|
25928
|
+
users = readUsersFile();
|
|
25929
|
+
} catch (err) {
|
|
25930
|
+
console.error(`[session] users.json corrupt: ${err instanceof Error ? err.message : String(err)}`);
|
|
25931
|
+
return Response.json(
|
|
25932
|
+
{ error: "User configuration is corrupt. Re-run the seed script." },
|
|
25933
|
+
{ status: 503 }
|
|
25934
|
+
);
|
|
25935
|
+
}
|
|
25936
|
+
if (users !== null) {
|
|
25937
|
+
const matchedUser = users.find((u) => u.pin === inputHash);
|
|
25938
|
+
if (!matchedUser) {
|
|
25939
|
+
console.log(`[session] PIN auth failed: no matching user`);
|
|
25940
|
+
return Response.json({ error: "Invalid PIN" }, { status: 401 });
|
|
25941
|
+
}
|
|
25942
|
+
const { userId, name: userName } = matchedUser;
|
|
25943
|
+
const accounts = resolveUserAccounts(userId);
|
|
25944
|
+
if (accounts.length === 0) {
|
|
25945
|
+
console.log(`[session] user has no accounts: userId=${userId}`);
|
|
25946
|
+
return Response.json(
|
|
25947
|
+
{ error: "No account access for this user." },
|
|
25948
|
+
{ status: 403 }
|
|
25949
|
+
);
|
|
25950
|
+
}
|
|
25951
|
+
if (accounts.length > 1 && !body.accountId) {
|
|
25952
|
+
console.log(`[session] multi-account user: userId=${userId} accounts=${accounts.length}`);
|
|
25953
|
+
const accountList = await Promise.all(
|
|
25954
|
+
accounts.map(async (a) => {
|
|
25955
|
+
let businessName;
|
|
25956
|
+
try {
|
|
25957
|
+
const branding = await fetchBranding(a.accountId);
|
|
25958
|
+
businessName = branding?.name || void 0;
|
|
25959
|
+
} catch {
|
|
25960
|
+
}
|
|
25961
|
+
return { accountId: a.accountId, businessName, role: a.role };
|
|
25962
|
+
})
|
|
25963
|
+
);
|
|
25964
|
+
return Response.json({ accounts: accountList, userId, userName });
|
|
25965
|
+
}
|
|
25966
|
+
const selected = body.accountId ? accounts.find((a) => a.accountId === body.accountId) : accounts[0];
|
|
25967
|
+
if (!selected) {
|
|
25968
|
+
console.log(`[session] account selection invalid: userId=${userId} requested=${body.accountId}`);
|
|
25969
|
+
return Response.json({ error: "Invalid account selection." }, { status: 403 });
|
|
25970
|
+
}
|
|
25971
|
+
return createAdminSession(selected.accountId, selected.config.thinkingView, userId, userName);
|
|
25972
|
+
}
|
|
25973
|
+
const storedHash = getStoredPinHash();
|
|
25974
|
+
if (!storedHash) {
|
|
25975
|
+
return Response.json(
|
|
25976
|
+
{ error: "PIN not configured. Complete onboarding first." },
|
|
25977
|
+
{ status: 503 }
|
|
25978
|
+
);
|
|
25979
|
+
}
|
|
25980
|
+
if (inputHash !== storedHash) {
|
|
25896
25981
|
console.log(`[session] PIN mismatch \u2014 stored=${storedHash.slice(0, 8)}\u2026 input=${inputHash.slice(0, 8)}\u2026 file=${PIN_FILE}`);
|
|
25897
25982
|
return Response.json({ error: "Invalid PIN" }, { status: 401 });
|
|
25898
25983
|
}
|
|
25899
25984
|
const accountId = getDefaultAccountId() ?? "default";
|
|
25900
|
-
|
|
25901
|
-
|
|
25985
|
+
return createAdminSession(accountId);
|
|
25986
|
+
}
|
|
25987
|
+
async function createAdminSession(accountId, thinkingView, userId, userName) {
|
|
25902
25988
|
const account = resolveAccount();
|
|
25903
|
-
const
|
|
25989
|
+
const effectiveThinkingView = thinkingView ?? account?.config.thinkingView ?? "default";
|
|
25990
|
+
const sessionKey = crypto.randomUUID();
|
|
25991
|
+
registerSession(sessionKey, "admin", accountId, void 0, userId, userName);
|
|
25904
25992
|
let onboardingComplete = true;
|
|
25905
25993
|
try {
|
|
25906
25994
|
const step = await loadOnboardingStep(accountId);
|
|
25907
25995
|
onboardingComplete = step === null || step >= 7;
|
|
25908
|
-
console.log(`[session] accountId=${accountId} onboardingComplete=${onboardingComplete}`);
|
|
25909
25996
|
} catch (err) {
|
|
25910
25997
|
console.error(`[session] onboarding query failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
25911
25998
|
}
|
|
@@ -25915,11 +26002,13 @@ async function POST19(req) {
|
|
|
25915
26002
|
businessName = branding?.name || void 0;
|
|
25916
26003
|
} catch {
|
|
25917
26004
|
}
|
|
25918
|
-
console.log(`[session]
|
|
26005
|
+
console.log(`[session] admin session created: userId=${userId ?? "\u2013"} userName=${userName ?? "\u2013"} accountId=${accountId}`);
|
|
25919
26006
|
return Response.json({
|
|
25920
26007
|
session_key: sessionKey,
|
|
25921
26008
|
agent_id: "admin",
|
|
25922
|
-
|
|
26009
|
+
userId,
|
|
26010
|
+
userName,
|
|
26011
|
+
thinkingView: effectiveThinkingView,
|
|
25923
26012
|
onboardingComplete,
|
|
25924
26013
|
businessName
|
|
25925
26014
|
});
|
|
@@ -26433,10 +26522,10 @@ async function GET8() {
|
|
|
26433
26522
|
// app/api/admin/version/route.ts
|
|
26434
26523
|
import { readFileSync as readFileSync17, existsSync as existsSync17 } from "fs";
|
|
26435
26524
|
import { resolve as resolve16, join as join7 } from "path";
|
|
26436
|
-
var
|
|
26525
|
+
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve16(process.cwd(), "..");
|
|
26437
26526
|
var brandHostname = "maxy";
|
|
26438
26527
|
var brandNpmPackage = "@rubytech/create-maxy";
|
|
26439
|
-
var brandJsonPath = join7(
|
|
26528
|
+
var brandJsonPath = join7(PLATFORM_ROOT8, "config", "brand.json");
|
|
26440
26529
|
if (existsSync17(brandJsonPath)) {
|
|
26441
26530
|
try {
|
|
26442
26531
|
const brand = JSON.parse(readFileSync17(brandJsonPath, "utf-8"));
|
|
@@ -26445,7 +26534,7 @@ if (existsSync17(brandJsonPath)) {
|
|
|
26445
26534
|
} catch {
|
|
26446
26535
|
}
|
|
26447
26536
|
}
|
|
26448
|
-
var VERSION_FILE = resolve16(
|
|
26537
|
+
var VERSION_FILE = resolve16(PLATFORM_ROOT8, `config/.${brandHostname}-version`);
|
|
26449
26538
|
var NPM_PACKAGE = brandNpmPackage;
|
|
26450
26539
|
var REGISTRY_URL = `https://registry.npmjs.org/${NPM_PACKAGE}/latest`;
|
|
26451
26540
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
@@ -26509,10 +26598,10 @@ async function GET9() {
|
|
|
26509
26598
|
import { spawn as spawn4 } from "child_process";
|
|
26510
26599
|
import { existsSync as existsSync18, statSync as statSync4, writeFileSync as writeFileSync10, readFileSync as readFileSync18, openSync as openSync2, closeSync as closeSync2 } from "fs";
|
|
26511
26600
|
import { resolve as resolve17, join as join8 } from "path";
|
|
26512
|
-
var
|
|
26601
|
+
var PLATFORM_ROOT9 = process.env.MAXY_PLATFORM_ROOT ?? resolve17(process.cwd(), "..");
|
|
26513
26602
|
var upgradePkg = "@rubytech/create-maxy";
|
|
26514
26603
|
var upgradeHostname = "maxy";
|
|
26515
|
-
var brandPath = join8(
|
|
26604
|
+
var brandPath = join8(PLATFORM_ROOT9, "config", "brand.json");
|
|
26516
26605
|
if (existsSync18(brandPath)) {
|
|
26517
26606
|
try {
|
|
26518
26607
|
const brand = JSON.parse(readFileSync18(brandPath, "utf-8"));
|
|
@@ -26678,8 +26767,8 @@ async function POST23() {
|
|
|
26678
26767
|
}
|
|
26679
26768
|
|
|
26680
26769
|
// server/index.ts
|
|
26681
|
-
var
|
|
26682
|
-
var BRAND_JSON_PATH =
|
|
26770
|
+
var PLATFORM_ROOT10 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
26771
|
+
var BRAND_JSON_PATH = PLATFORM_ROOT10 ? join9(PLATFORM_ROOT10, "config", "brand.json") : "";
|
|
26683
26772
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", domain: "getmaxy.com" };
|
|
26684
26773
|
if (BRAND_JSON_PATH && !existsSync19(BRAND_JSON_PATH)) {
|
|
26685
26774
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|