@rubytech/create-realagent 1.0.807 → 1.0.808
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/payload/platform/plugins/admin/skills/onboarding/SKILL.md +2 -0
- package/payload/platform/plugins/docs/references/cloudflare.md +1 -0
- package/payload/platform/plugins/docs/references/memory-guide.md +4 -0
- package/payload/platform/plugins/docs/references/troubleshooting.md +19 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js +19 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js.map +1 -1
- package/payload/platform/templates/agents/admin/IDENTITY.md +1 -0
- package/payload/platform/templates/agents/admin/SOUL.md +2 -0
- package/payload/server/chunk-CRWLE6BZ.js +3511 -0
- package/payload/server/chunk-V3VLAL7N.js +10009 -0
- package/payload/server/client-pool-N2Y57223.js +31 -0
- package/payload/server/maxy-edge.js +5 -4
- package/payload/server/public/assets/{admin-CTM9Vb-j.js → admin-MxaCgGHZ.js} +6 -6
- package/payload/server/public/index.html +1 -1
- package/payload/server/server.js +353 -90
package/payload/server/server.js
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
TELEGRAM_ADMIN_WEBHOOK_SECRET_FILE,
|
|
7
7
|
TELEGRAM_WEBHOOK_SECRET_FILE,
|
|
8
8
|
USERS_FILE,
|
|
9
|
+
actionLogPath,
|
|
9
10
|
autoDeliverPremiumPlugins,
|
|
10
11
|
buildX11Env,
|
|
11
12
|
callOauthLlm,
|
|
@@ -29,6 +30,7 @@ import {
|
|
|
29
30
|
launchAction,
|
|
30
31
|
load,
|
|
31
32
|
logPath,
|
|
33
|
+
reconcileCloudflareSetupFromLog,
|
|
32
34
|
recordFailedAttempt,
|
|
33
35
|
render,
|
|
34
36
|
renderLoginPage,
|
|
@@ -50,7 +52,7 @@ import {
|
|
|
50
52
|
vncLog,
|
|
51
53
|
waitForExit,
|
|
52
54
|
writeChromiumWrapper
|
|
53
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-V3VLAL7N.js";
|
|
54
56
|
import {
|
|
55
57
|
ACCOUNTS_DIR,
|
|
56
58
|
GREETING_DIRECTIVE,
|
|
@@ -114,7 +116,7 @@ import {
|
|
|
114
116
|
verifyAndGetConversationUpdatedAt,
|
|
115
117
|
verifyConversationOwnership,
|
|
116
118
|
writeAdminUserAndPerson
|
|
117
|
-
} from "./chunk-
|
|
119
|
+
} from "./chunk-CRWLE6BZ.js";
|
|
118
120
|
import {
|
|
119
121
|
__commonJS,
|
|
120
122
|
__toESM
|
|
@@ -617,8 +619,8 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
617
619
|
};
|
|
618
620
|
|
|
619
621
|
// server/index.ts
|
|
620
|
-
import { readFileSync as
|
|
621
|
-
import { resolve as resolve24, join as
|
|
622
|
+
import { readFileSync as readFileSync18, existsSync as existsSync25, watchFile } from "fs";
|
|
623
|
+
import { resolve as resolve24, join as join11, basename as basename7 } from "path";
|
|
622
624
|
import { homedir as homedir2 } from "os";
|
|
623
625
|
|
|
624
626
|
// app/lib/agent-slug-pattern.ts
|
|
@@ -804,6 +806,28 @@ function defaultRules() {
|
|
|
804
806
|
scope: "session",
|
|
805
807
|
suggestedAction: "The WebFetch SPA preflight has fired more than once in this conversation. Either the agent is ignoring the loud-failure directive (retrying WebFetch after seeing WEBFETCH_CANNOT_READ_JS_SPA), or multiple SPA URLs are being asked about. Read the conversation's stream log for the [tool-use] / [tool-result] sequence around each occurrence \u2014 if the agent dispatched WebFetch on the same URL or substituted Playwright silently, revisit the IDENTITY.md `Tool Failure Discipline` paragraph that names structured-error handling."
|
|
806
808
|
},
|
|
809
|
+
{
|
|
810
|
+
// Task 867 — fires when setup-tunnel.sh emits step=done but no
|
|
811
|
+
// `[persist] role=user … Cloudflare setup completed (actionId: <id>)`
|
|
812
|
+
// line appears within 60s. Covers the three failure modes of the
|
|
813
|
+
// action-relay-queue plumbing: queue-write failed, boot-drain consumer
|
|
814
|
+
// skipped the record, or the agent's hoisted persist threw. The
|
|
815
|
+
// followup pattern is intentionally narrow to the cloudflare-setup
|
|
816
|
+
// relay shape (not a general "any user persist") so a benign user
|
|
817
|
+
// typing in chat does not satisfy the followup. logSource=any so
|
|
818
|
+
// the rule sees both the script tee (in stream logs / server.log)
|
|
819
|
+
// and the [persist] line (server.log).
|
|
820
|
+
id: "cloudflare-setup-relay-not-acknowledged",
|
|
821
|
+
name: "Cloudflare-setup completed but the chat relay never acknowledged",
|
|
822
|
+
type: "absent-followup",
|
|
823
|
+
logSource: "any",
|
|
824
|
+
pattern: "\\[script:setup-tunnel\\] step=done",
|
|
825
|
+
followupPattern: "\\[persist\\] .*role=user.* Cloudflare setup completed \\(actionId:",
|
|
826
|
+
followupWindowMs: 6e4,
|
|
827
|
+
thresholdCount: 0,
|
|
828
|
+
thresholdWindowMinutes: 0,
|
|
829
|
+
suggestedAction: "[Task 867] cloudflare-setup completed but the post-action relay never reached the chat history. Check `[action-relay-queue] phase=enqueued` (queue write), `[action-completion-relay] phase=consumed` (boot-drain ran), and `[persist] role=user \u2026 Cloudflare setup completed` (graph write). One of those is missing; the matching grep recipe is in the Task 867 brief Observability section."
|
|
830
|
+
},
|
|
807
831
|
{
|
|
808
832
|
// Task 538: fires when a [spawn] line appears in a conversation's stream
|
|
809
833
|
// log but no subprocess-lifecycle marker follows within 10s. The three
|
|
@@ -8070,7 +8094,8 @@ app9.post("/", async (c) => {
|
|
|
8070
8094
|
"unknown",
|
|
8071
8095
|
"graph-labels-in-graph",
|
|
8072
8096
|
"graph-default-view",
|
|
8073
|
-
"graph-nav"
|
|
8097
|
+
"graph-nav",
|
|
8098
|
+
"event"
|
|
8074
8099
|
]);
|
|
8075
8100
|
const kind = allowedKinds.has(kindRaw) ? kindRaw : "unknown";
|
|
8076
8101
|
const msg = truncate(body.msg, MAX_MSG_LEN);
|
|
@@ -8084,29 +8109,42 @@ app9.post("/", async (c) => {
|
|
|
8084
8109
|
const stackTrunc = truncate(body.stack, MAX_STACK_LEN);
|
|
8085
8110
|
const head = stackHead(body.stack);
|
|
8086
8111
|
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
8087
|
-
|
|
8088
|
-
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
|
|
8092
|
-
|
|
8093
|
-
|
|
8094
|
-
ip
|
|
8095
|
-
|
|
8096
|
-
|
|
8097
|
-
|
|
8098
|
-
ua
|
|
8099
|
-
|
|
8100
|
-
|
|
8101
|
-
|
|
8102
|
-
|
|
8103
|
-
|
|
8104
|
-
|
|
8105
|
-
|
|
8106
|
-
|
|
8107
|
-
|
|
8108
|
-
|
|
8109
|
-
|
|
8112
|
+
if (kind === "event") {
|
|
8113
|
+
const source = typeof body.source === "string" ? truncate(body.source, 64) : "unknown";
|
|
8114
|
+
const extra = Object.entries(body).filter(([k]) => !["kind", "source", "msg", "url", "ua", "version", "stack", "filename", "lineno", "colno", "tag", "status"].includes(k)).map(([k, v]) => {
|
|
8115
|
+
const safe = typeof v === "string" ? truncate(v, 200) : typeof v === "number" || typeof v === "boolean" ? String(v) : JSON.stringify(v).slice(0, 200);
|
|
8116
|
+
return `${k}=${safe}`;
|
|
8117
|
+
}).join(" ");
|
|
8118
|
+
console.log(
|
|
8119
|
+
`[client-event] ts=${ts} ip=${ip} source=${source} version=${version || "unknown"}${extra ? " " + extra : ""}`
|
|
8120
|
+
);
|
|
8121
|
+
} else {
|
|
8122
|
+
console.error(
|
|
8123
|
+
`[client-error] ts=${ts} ip=${ip} kind=${kind} url=${JSON.stringify(url)} version=${version || "unknown"} ua=${JSON.stringify(ua)} msg=${JSON.stringify(msg)} stack-head=${JSON.stringify(head)} file-line-col=${JSON.stringify(fileLineCol)}`
|
|
8124
|
+
);
|
|
8125
|
+
}
|
|
8126
|
+
if (kind !== "event") {
|
|
8127
|
+
rotateIfNeeded();
|
|
8128
|
+
try {
|
|
8129
|
+
const payload = {
|
|
8130
|
+
ts,
|
|
8131
|
+
ip,
|
|
8132
|
+
kind,
|
|
8133
|
+
url,
|
|
8134
|
+
version,
|
|
8135
|
+
ua,
|
|
8136
|
+
msg,
|
|
8137
|
+
stack: stackTrunc,
|
|
8138
|
+
filename: file,
|
|
8139
|
+
lineno: line,
|
|
8140
|
+
colno: col,
|
|
8141
|
+
tag: typeof body.tag === "string" ? truncate(body.tag, 32) : void 0,
|
|
8142
|
+
status: typeof body.status === "number" ? body.status : void 0
|
|
8143
|
+
};
|
|
8144
|
+
appendFileSync2(CLIENT_ERRORS_LOG, JSON.stringify(payload) + "\n", "utf-8");
|
|
8145
|
+
} catch (err) {
|
|
8146
|
+
console.error(`[client-error] append failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
8147
|
+
}
|
|
8110
8148
|
}
|
|
8111
8149
|
return c.json({ ok: true });
|
|
8112
8150
|
});
|
|
@@ -8586,7 +8624,7 @@ var app11 = new Hono();
|
|
|
8586
8624
|
app11.post("/cancel", requireAdminSession, async (c) => {
|
|
8587
8625
|
const session_key = c.var.sessionKey;
|
|
8588
8626
|
try {
|
|
8589
|
-
const { interruptClient: interruptClient2 } = await import("./client-pool-
|
|
8627
|
+
const { interruptClient: interruptClient2 } = await import("./client-pool-N2Y57223.js");
|
|
8590
8628
|
await interruptClient2(session_key);
|
|
8591
8629
|
return c.json({ ok: true });
|
|
8592
8630
|
} catch (err) {
|
|
@@ -9749,13 +9787,13 @@ async function cdpNavigateNewTab(url, opts = {}) {
|
|
|
9749
9787
|
// server/routes/admin/device-browser.ts
|
|
9750
9788
|
var app19 = new Hono();
|
|
9751
9789
|
app19.post("/navigate", async (c) => {
|
|
9752
|
-
const
|
|
9790
|
+
const TAG20 = "[device-url:click]";
|
|
9753
9791
|
let body;
|
|
9754
9792
|
try {
|
|
9755
9793
|
body = await c.req.json();
|
|
9756
9794
|
} catch (err) {
|
|
9757
9795
|
const detail = err instanceof Error ? err.message : String(err);
|
|
9758
|
-
console.error(`${
|
|
9796
|
+
console.error(`${TAG20} reject reason=body-not-json detail=${detail} browser=fallback navigateResult=error`);
|
|
9759
9797
|
return c.json(
|
|
9760
9798
|
{ ok: false, navigateResult: "error", browser: "fallback", detail: "Request body was not valid JSON" },
|
|
9761
9799
|
400
|
|
@@ -9765,7 +9803,7 @@ app19.post("/navigate", async (c) => {
|
|
|
9765
9803
|
const intent = typeof body.intent === "string" ? body.intent : "";
|
|
9766
9804
|
const hostname2 = typeof body.hostname === "string" ? body.hostname : "";
|
|
9767
9805
|
if (!url) {
|
|
9768
|
-
console.error(`${
|
|
9806
|
+
console.error(`${TAG20} reject reason=missing-url intent=${JSON.stringify(intent)} browser=fallback navigateResult=error`);
|
|
9769
9807
|
return c.json(
|
|
9770
9808
|
{ ok: false, navigateResult: "error", browser: "fallback", detail: "url field is required" },
|
|
9771
9809
|
400
|
|
@@ -9775,7 +9813,7 @@ app19.post("/navigate", async (c) => {
|
|
|
9775
9813
|
try {
|
|
9776
9814
|
parsed = new URL(url);
|
|
9777
9815
|
} catch {
|
|
9778
|
-
console.error(`${
|
|
9816
|
+
console.error(`${TAG20} reject reason=url-malformed intent=${JSON.stringify(intent)} url=${url} browser=fallback navigateResult=error`);
|
|
9779
9817
|
return c.json(
|
|
9780
9818
|
{ ok: false, navigateResult: "error", browser: "fallback", detail: "url is not a valid URL" },
|
|
9781
9819
|
400
|
|
@@ -9783,7 +9821,7 @@ app19.post("/navigate", async (c) => {
|
|
|
9783
9821
|
}
|
|
9784
9822
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
9785
9823
|
console.error(
|
|
9786
|
-
`${
|
|
9824
|
+
`${TAG20} reject reason=scheme-not-allowed scheme=${parsed.protocol} intent=${JSON.stringify(intent)} browser=fallback navigateResult=error`
|
|
9787
9825
|
);
|
|
9788
9826
|
return c.json(
|
|
9789
9827
|
{
|
|
@@ -9799,7 +9837,7 @@ app19.post("/navigate", async (c) => {
|
|
|
9799
9837
|
const cdpOk = await ensureCdp(transport);
|
|
9800
9838
|
if (!cdpOk) {
|
|
9801
9839
|
console.error(
|
|
9802
|
-
`${
|
|
9840
|
+
`${TAG20} intent=${JSON.stringify(intent)} browser=fallback navigateResult=cdp-unreachable hostname=${JSON.stringify(hostname2)}`
|
|
9803
9841
|
);
|
|
9804
9842
|
return c.json(
|
|
9805
9843
|
{
|
|
@@ -9815,7 +9853,7 @@ app19.post("/navigate", async (c) => {
|
|
|
9815
9853
|
const browser = outcome.result === "ok" ? "vnc" : "fallback";
|
|
9816
9854
|
const detailStr = outcome.detail ? ` detail=${JSON.stringify(outcome.detail.length > 230 ? outcome.detail.slice(0, 227) + "..." : outcome.detail)}` : "";
|
|
9817
9855
|
console.error(
|
|
9818
|
-
`${
|
|
9856
|
+
`${TAG20} intent=${JSON.stringify(intent)} browser=${browser} navigateResult=${outcome.result} hostname=${JSON.stringify(hostname2)} targetId=${outcome.targetId ?? "none"}${detailStr}`
|
|
9819
9857
|
);
|
|
9820
9858
|
if (outcome.result !== "ok") {
|
|
9821
9859
|
return c.json(
|
|
@@ -9846,18 +9884,18 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
|
9846
9884
|
]);
|
|
9847
9885
|
var app20 = new Hono();
|
|
9848
9886
|
app20.post("/", async (c) => {
|
|
9849
|
-
const
|
|
9887
|
+
const TAG20 = "[admin:events]";
|
|
9850
9888
|
let body;
|
|
9851
9889
|
try {
|
|
9852
9890
|
body = await c.req.json();
|
|
9853
9891
|
} catch (err) {
|
|
9854
9892
|
const detail = err instanceof Error ? err.message : String(err);
|
|
9855
|
-
console.error(`${
|
|
9893
|
+
console.error(`${TAG20} reject reason=body-not-json detail=${detail}`);
|
|
9856
9894
|
return c.json({ ok: false, detail: "Request body was not valid JSON" }, 400);
|
|
9857
9895
|
}
|
|
9858
9896
|
const event = typeof body.event === "string" ? body.event : "";
|
|
9859
9897
|
if (!ALLOWED_EVENTS.has(event)) {
|
|
9860
|
-
console.error(`${
|
|
9898
|
+
console.error(`${TAG20} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
|
|
9861
9899
|
return c.json({ ok: false, detail: `Event "${event}" is not allowed` }, 400);
|
|
9862
9900
|
}
|
|
9863
9901
|
const rawFields = body.fields && typeof body.fields === "object" ? body.fields : {};
|
|
@@ -9881,7 +9919,7 @@ var events_default = app20;
|
|
|
9881
9919
|
// server/routes/admin/cloudflare.ts
|
|
9882
9920
|
import { homedir } from "os";
|
|
9883
9921
|
import { resolve as resolve17 } from "path";
|
|
9884
|
-
import { readFileSync as
|
|
9922
|
+
import { readFileSync as readFileSync16 } from "fs";
|
|
9885
9923
|
|
|
9886
9924
|
// app/lib/dns-label.ts
|
|
9887
9925
|
var VALID_LABEL = /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
@@ -9919,14 +9957,131 @@ function addAliasDomain(hostname2) {
|
|
|
9919
9957
|
writeFileSync9(ALIAS_DOMAINS_PATH, JSON.stringify([...existing], null, 2) + "\n", "utf-8");
|
|
9920
9958
|
}
|
|
9921
9959
|
|
|
9960
|
+
// app/lib/action-relay-queue.ts
|
|
9961
|
+
import {
|
|
9962
|
+
existsSync as existsSync20,
|
|
9963
|
+
mkdirSync as mkdirSync9,
|
|
9964
|
+
readdirSync as readdirSync5,
|
|
9965
|
+
readFileSync as readFileSync15,
|
|
9966
|
+
unlinkSync as unlinkSync2,
|
|
9967
|
+
writeFileSync as writeFileSync10
|
|
9968
|
+
} from "fs";
|
|
9969
|
+
import { join as join9 } from "path";
|
|
9970
|
+
var TAG19 = "[action-relay-queue]";
|
|
9971
|
+
var FILE_PREFIX = "action-completion-relay-";
|
|
9972
|
+
var FILE_SUFFIX = ".json";
|
|
9973
|
+
function queueDir(accountDir) {
|
|
9974
|
+
return join9(accountDir, "queue");
|
|
9975
|
+
}
|
|
9976
|
+
function relayFilePath(accountDir, actionId) {
|
|
9977
|
+
return join9(queueDir(accountDir), `${FILE_PREFIX}${actionId}${FILE_SUFFIX}`);
|
|
9978
|
+
}
|
|
9979
|
+
function enqueueActionCompletionRelay(opts) {
|
|
9980
|
+
const dir = queueDir(opts.accountDir);
|
|
9981
|
+
mkdirSync9(dir, { recursive: true });
|
|
9982
|
+
const filePath = relayFilePath(opts.accountDir, opts.actionId);
|
|
9983
|
+
const record = {
|
|
9984
|
+
actionId: opts.actionId,
|
|
9985
|
+
conversationId: opts.conversationId,
|
|
9986
|
+
message: opts.message,
|
|
9987
|
+
queuedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
9988
|
+
};
|
|
9989
|
+
const body = JSON.stringify(record);
|
|
9990
|
+
try {
|
|
9991
|
+
writeFileSync10(filePath, body, { flag: "wx", encoding: "utf-8" });
|
|
9992
|
+
console.log(
|
|
9993
|
+
`${TAG19} phase=enqueued actionId=${opts.actionId} conversationId=${opts.conversationId} path=${filePath} bytes=${Buffer.byteLength(body, "utf-8")}`
|
|
9994
|
+
);
|
|
9995
|
+
return { enqueued: true, path: filePath };
|
|
9996
|
+
} catch (e) {
|
|
9997
|
+
if (e.code === "EEXIST") {
|
|
9998
|
+
console.log(
|
|
9999
|
+
`${TAG19} phase=enqueue-skipped actionId=${opts.actionId} reason=already-queued`
|
|
10000
|
+
);
|
|
10001
|
+
return { enqueued: false, reason: "already-queued", path: filePath };
|
|
10002
|
+
}
|
|
10003
|
+
throw e;
|
|
10004
|
+
}
|
|
10005
|
+
}
|
|
10006
|
+
function consumeActionCompletionRelays(accountDir) {
|
|
10007
|
+
const dir = queueDir(accountDir);
|
|
10008
|
+
if (!existsSync20(dir)) return [];
|
|
10009
|
+
let entries;
|
|
10010
|
+
try {
|
|
10011
|
+
entries = readdirSync5(dir);
|
|
10012
|
+
} catch (e) {
|
|
10013
|
+
console.error(
|
|
10014
|
+
`${TAG19} phase=readdir-failed dir=${dir} error=${e instanceof Error ? e.message : String(e)}`
|
|
10015
|
+
);
|
|
10016
|
+
return [];
|
|
10017
|
+
}
|
|
10018
|
+
const records = [];
|
|
10019
|
+
for (const name of entries) {
|
|
10020
|
+
if (!name.startsWith(FILE_PREFIX) || !name.endsWith(FILE_SUFFIX)) continue;
|
|
10021
|
+
const filePath = join9(dir, name);
|
|
10022
|
+
let raw;
|
|
10023
|
+
try {
|
|
10024
|
+
raw = readFileSync15(filePath, "utf-8");
|
|
10025
|
+
} catch (e) {
|
|
10026
|
+
console.error(
|
|
10027
|
+
`${TAG19} phase=read-failed file=${name} error=${e instanceof Error ? e.message : String(e)}`
|
|
10028
|
+
);
|
|
10029
|
+
continue;
|
|
10030
|
+
}
|
|
10031
|
+
let parsed;
|
|
10032
|
+
try {
|
|
10033
|
+
parsed = JSON.parse(raw);
|
|
10034
|
+
} catch (e) {
|
|
10035
|
+
console.error(
|
|
10036
|
+
`${TAG19} phase=parse-failed file=${name} error=${e instanceof Error ? e.message : String(e)}`
|
|
10037
|
+
);
|
|
10038
|
+
continue;
|
|
10039
|
+
}
|
|
10040
|
+
if (!isActionCompletionRelay(parsed)) {
|
|
10041
|
+
console.error(
|
|
10042
|
+
`${TAG19} phase=shape-invalid file=${name} keys=${parsed && typeof parsed === "object" ? Object.keys(parsed).join(",") : "non-object"}`
|
|
10043
|
+
);
|
|
10044
|
+
continue;
|
|
10045
|
+
}
|
|
10046
|
+
records.push({ rec: parsed, filePath });
|
|
10047
|
+
}
|
|
10048
|
+
records.sort((a, b) => a.rec.queuedAt.localeCompare(b.rec.queuedAt));
|
|
10049
|
+
const out = [];
|
|
10050
|
+
const now = Date.now();
|
|
10051
|
+
for (const { rec, filePath } of records) {
|
|
10052
|
+
const queuedAtMs = Date.parse(rec.queuedAt);
|
|
10053
|
+
const ageMs = Number.isFinite(queuedAtMs) ? now - queuedAtMs : 0;
|
|
10054
|
+
out.push({ ...rec, ageMs, filePath });
|
|
10055
|
+
}
|
|
10056
|
+
return out;
|
|
10057
|
+
}
|
|
10058
|
+
function deleteConsumedRelay(filePath) {
|
|
10059
|
+
try {
|
|
10060
|
+
unlinkSync2(filePath);
|
|
10061
|
+
} catch (e) {
|
|
10062
|
+
const code = e.code;
|
|
10063
|
+
if (code !== "ENOENT") {
|
|
10064
|
+
console.error(
|
|
10065
|
+
`${TAG19} phase=unlink-failed file=${filePath} error=${e instanceof Error ? e.message : String(e)}`
|
|
10066
|
+
);
|
|
10067
|
+
}
|
|
10068
|
+
}
|
|
10069
|
+
}
|
|
10070
|
+
function isActionCompletionRelay(value) {
|
|
10071
|
+
if (!value || typeof value !== "object") return false;
|
|
10072
|
+
const v = value;
|
|
10073
|
+
return typeof v.actionId === "string" && typeof v.conversationId === "string" && typeof v.message === "string" && typeof v.queuedAt === "string";
|
|
10074
|
+
}
|
|
10075
|
+
|
|
9922
10076
|
// server/routes/admin/cloudflare.ts
|
|
10077
|
+
import { existsSync as existsSyncFs, readFileSync as readFileSyncFs } from "fs";
|
|
9923
10078
|
var SETUP_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
9924
10079
|
var DOMAINS_TIMEOUT_MS = 40 * 1e3;
|
|
9925
10080
|
function loadBrandInfo() {
|
|
9926
10081
|
const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? resolve17(process.cwd(), "..");
|
|
9927
10082
|
const brandPath = resolve17(platformRoot2, "config", "brand.json");
|
|
9928
10083
|
try {
|
|
9929
|
-
const parsed = JSON.parse(
|
|
10084
|
+
const parsed = JSON.parse(readFileSync16(brandPath, "utf-8"));
|
|
9930
10085
|
const hostname2 = typeof parsed.hostname === "string" && parsed.hostname ? parsed.hostname : "maxy";
|
|
9931
10086
|
const configDir2 = typeof parsed.configDir === "string" && parsed.configDir ? parsed.configDir : ".maxy";
|
|
9932
10087
|
return { hostname: hostname2, configDir: configDir2 };
|
|
@@ -10222,13 +10377,79 @@ actionId: ${actionId}`,
|
|
|
10222
10377
|
};
|
|
10223
10378
|
return ok(success);
|
|
10224
10379
|
});
|
|
10380
|
+
var RELAY_MAX_BODY = 8 * 1024;
|
|
10381
|
+
var RELAY_MAX_MESSAGE = 2048;
|
|
10382
|
+
var ACTION_ID_RE = /^[a-z0-9-]+$/;
|
|
10383
|
+
app21.post("/relay-completion", requireAdminSession, async (c) => {
|
|
10384
|
+
const sessionKey = c.var.sessionKey;
|
|
10385
|
+
let raw;
|
|
10386
|
+
try {
|
|
10387
|
+
raw = await c.req.text();
|
|
10388
|
+
} catch {
|
|
10389
|
+
return c.json({ ok: false, reason: "invalid-body" }, 400);
|
|
10390
|
+
}
|
|
10391
|
+
if (Buffer.byteLength(raw, "utf-8") > RELAY_MAX_BODY) {
|
|
10392
|
+
return c.json({ ok: false, reason: "body-too-large" }, 413);
|
|
10393
|
+
}
|
|
10394
|
+
let body;
|
|
10395
|
+
try {
|
|
10396
|
+
body = JSON.parse(raw);
|
|
10397
|
+
} catch {
|
|
10398
|
+
return c.json({ ok: false, reason: "invalid-json" }, 400);
|
|
10399
|
+
}
|
|
10400
|
+
if (!body || typeof body !== "object") {
|
|
10401
|
+
return c.json({ ok: false, reason: "invalid-body" }, 400);
|
|
10402
|
+
}
|
|
10403
|
+
const { actionId, message } = body;
|
|
10404
|
+
if (typeof actionId !== "string" || !ACTION_ID_RE.test(actionId) || actionId.length > 200) {
|
|
10405
|
+
console.error(`[cloudflare-relay-completion] phase=enqueue-skipped reason=invalid-actionid sessionKey=${sessionKey.slice(-8)}`);
|
|
10406
|
+
return c.json({ ok: false, reason: "invalid-actionid" }, 400);
|
|
10407
|
+
}
|
|
10408
|
+
if (typeof message !== "string" || message.length === 0 || message.length > RELAY_MAX_MESSAGE) {
|
|
10409
|
+
return c.json({ ok: false, reason: "invalid-message" }, 400);
|
|
10410
|
+
}
|
|
10411
|
+
const conversationId = getConversationIdForSession(sessionKey);
|
|
10412
|
+
if (!conversationId) {
|
|
10413
|
+
console.error(`[cloudflare-relay-completion] phase=enqueue-skipped reason=missing-conversation-id sessionKey=${sessionKey.slice(-8)}`);
|
|
10414
|
+
return c.json({ ok: false, reason: "missing-conversation-id" }, 400);
|
|
10415
|
+
}
|
|
10416
|
+
const account = resolveAccount();
|
|
10417
|
+
if (!account) {
|
|
10418
|
+
console.error(`[cloudflare-relay-completion] phase=enqueue-skipped reason=missing-account-dir actionId=${actionId}`);
|
|
10419
|
+
return c.json({ ok: false, reason: "missing-account-dir" }, 500);
|
|
10420
|
+
}
|
|
10421
|
+
const logPath2 = actionLogPath(actionId);
|
|
10422
|
+
let auditOutcome = "log-absent";
|
|
10423
|
+
if (existsSyncFs(logPath2)) {
|
|
10424
|
+
try {
|
|
10425
|
+
const lines = readFileSyncFs(logPath2, "utf-8").split("\n");
|
|
10426
|
+
const reconciled = reconcileCloudflareSetupFromLog(lines);
|
|
10427
|
+
auditOutcome = reconciled ? reconciled.kind : "log-incomplete";
|
|
10428
|
+
} catch (e) {
|
|
10429
|
+
auditOutcome = `read-failed:${e instanceof Error ? e.message : String(e)}`;
|
|
10430
|
+
}
|
|
10431
|
+
}
|
|
10432
|
+
console.log(`[cloudflare-relay-completion] phase=enqueue-attempt actionId=${actionId} auditOutcome=${auditOutcome} conversationId=${conversationId}`);
|
|
10433
|
+
try {
|
|
10434
|
+
enqueueActionCompletionRelay({
|
|
10435
|
+
accountDir: account.accountDir,
|
|
10436
|
+
actionId,
|
|
10437
|
+
conversationId,
|
|
10438
|
+
message
|
|
10439
|
+
});
|
|
10440
|
+
} catch (e) {
|
|
10441
|
+
console.error(`[cloudflare-relay-completion] phase=enqueue-failed actionId=${actionId} error=${e instanceof Error ? e.message : String(e)}`);
|
|
10442
|
+
return c.json({ ok: false, reason: "enqueue-failed" }, 500);
|
|
10443
|
+
}
|
|
10444
|
+
return c.body(null, 204);
|
|
10445
|
+
});
|
|
10225
10446
|
var cloudflare_default = app21;
|
|
10226
10447
|
|
|
10227
10448
|
// server/routes/admin/files.ts
|
|
10228
10449
|
import { createReadStream as createReadStream3 } from "fs";
|
|
10229
10450
|
import { readdir as readdir2, readFile as readFile4, stat as stat4, mkdir as mkdir3, writeFile as writeFile4, unlink as unlink2 } from "fs/promises";
|
|
10230
10451
|
import { realpathSync as realpathSync4 } from "fs";
|
|
10231
|
-
import { basename as basename6, dirname as dirname8, join as
|
|
10452
|
+
import { basename as basename6, dirname as dirname8, join as join10, resolve as resolve19, sep as sep2 } from "path";
|
|
10232
10453
|
import { Readable as Readable2 } from "stream";
|
|
10233
10454
|
|
|
10234
10455
|
// app/lib/data-path.ts
|
|
@@ -10586,7 +10807,7 @@ async function cascadeDeleteDocument(params) {
|
|
|
10586
10807
|
var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
10587
10808
|
async function readMeta(absDir, baseName) {
|
|
10588
10809
|
try {
|
|
10589
|
-
const raw = await readFile4(
|
|
10810
|
+
const raw = await readFile4(join10(absDir, `${baseName}.meta.json`), "utf8");
|
|
10590
10811
|
const parsed = JSON.parse(raw);
|
|
10591
10812
|
if (typeof parsed?.filename === "string") {
|
|
10592
10813
|
return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
|
|
@@ -10624,7 +10845,7 @@ async function readAccountNames() {
|
|
|
10624
10845
|
}
|
|
10625
10846
|
async function enrich(absolute, entry, accountNames) {
|
|
10626
10847
|
if (entry.kind === "directory" && UUID_RE3.test(entry.name)) {
|
|
10627
|
-
const meta = await readMeta(
|
|
10848
|
+
const meta = await readMeta(join10(absolute, entry.name), entry.name);
|
|
10628
10849
|
if (meta?.filename) {
|
|
10629
10850
|
entry.displayName = meta.filename;
|
|
10630
10851
|
entry.mimeType = meta.mimeType;
|
|
@@ -10683,7 +10904,7 @@ app22.get("/", requireAdminSession, async (c) => {
|
|
|
10683
10904
|
continue;
|
|
10684
10905
|
}
|
|
10685
10906
|
try {
|
|
10686
|
-
const entryPath =
|
|
10907
|
+
const entryPath = join10(absolute, name);
|
|
10687
10908
|
const s = await stat4(entryPath);
|
|
10688
10909
|
entries.push({
|
|
10689
10910
|
name,
|
|
@@ -10856,7 +11077,7 @@ app22.delete("/", requireAdminSession, async (c) => {
|
|
|
10856
11077
|
}
|
|
10857
11078
|
const dot = base.lastIndexOf(".");
|
|
10858
11079
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
10859
|
-
const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ?
|
|
11080
|
+
const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join10(dirname8(absolute), `${stem}.meta.json`) : null;
|
|
10860
11081
|
await unlink2(absolute);
|
|
10861
11082
|
if (sidecarPath) {
|
|
10862
11083
|
try {
|
|
@@ -12314,7 +12535,7 @@ var adherence_default = app30;
|
|
|
12314
12535
|
import neo4j3 from "neo4j-driver";
|
|
12315
12536
|
import { readFile as readFile5, readdir as readdir3, stat as stat5 } from "fs/promises";
|
|
12316
12537
|
import { resolve as resolve20, relative as relative2, isAbsolute } from "path";
|
|
12317
|
-
import { existsSync as
|
|
12538
|
+
import { existsSync as existsSync21 } from "fs";
|
|
12318
12539
|
var LIMIT = 50;
|
|
12319
12540
|
var TEXT_MIME_PREFIXES = ["text/", "application/json", "application/markdown"];
|
|
12320
12541
|
var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
|
|
@@ -12462,7 +12683,7 @@ async function fetchAgentTemplateRows(accountDir) {
|
|
|
12462
12683
|
async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
12463
12684
|
const names = /* @__PURE__ */ new Set();
|
|
12464
12685
|
for (const dir of [overrideDir, bundledDir]) {
|
|
12465
|
-
if (!
|
|
12686
|
+
if (!existsSync21(dir)) continue;
|
|
12466
12687
|
try {
|
|
12467
12688
|
const entries = await readdir3(dir);
|
|
12468
12689
|
for (const entry of entries) {
|
|
@@ -12477,7 +12698,7 @@ async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
|
12477
12698
|
}
|
|
12478
12699
|
async function readAgentTemplateRow(inp) {
|
|
12479
12700
|
let chosenPath = null;
|
|
12480
|
-
if (
|
|
12701
|
+
if (existsSync21(inp.overridePath)) {
|
|
12481
12702
|
try {
|
|
12482
12703
|
validateFilePathInAccount(inp.overridePath, inp.overrideRoot);
|
|
12483
12704
|
chosenPath = inp.overridePath;
|
|
@@ -12488,7 +12709,7 @@ async function readAgentTemplateRow(inp) {
|
|
|
12488
12709
|
);
|
|
12489
12710
|
return null;
|
|
12490
12711
|
}
|
|
12491
|
-
} else if (
|
|
12712
|
+
} else if (existsSync21(inp.bundledPath)) {
|
|
12492
12713
|
if (!isWithin(inp.bundledPath, inp.bundledRoot)) {
|
|
12493
12714
|
console.error(
|
|
12494
12715
|
`[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="bundled path outside PLATFORM_ROOT"`
|
|
@@ -12530,7 +12751,7 @@ var sidebar_artefacts_default = app31;
|
|
|
12530
12751
|
// server/routes/admin/sidebar-artefact-save.ts
|
|
12531
12752
|
import { mkdir as mkdir4, readdir as readdir4, stat as stat6, writeFile as writeFile5 } from "fs/promises";
|
|
12532
12753
|
import { resolve as resolve21 } from "path";
|
|
12533
|
-
import { existsSync as
|
|
12754
|
+
import { existsSync as existsSync22 } from "fs";
|
|
12534
12755
|
var ADMIN_AGENT_FILES2 = /* @__PURE__ */ new Set(["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"]);
|
|
12535
12756
|
var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
12536
12757
|
var app32 = new Hono();
|
|
@@ -12594,7 +12815,7 @@ async function resolveSavePath(id, accountId, accountDir) {
|
|
|
12594
12815
|
}
|
|
12595
12816
|
if (UUID_RE4.test(id)) {
|
|
12596
12817
|
const dir = resolve21(ATTACHMENTS_ROOT, accountId, id);
|
|
12597
|
-
if (!
|
|
12818
|
+
if (!existsSync22(dir)) {
|
|
12598
12819
|
return { kind: "reject", status: 400, reason: "not-found" };
|
|
12599
12820
|
}
|
|
12600
12821
|
try {
|
|
@@ -12618,7 +12839,7 @@ var sidebar_artefact_save_default = app32;
|
|
|
12618
12839
|
|
|
12619
12840
|
// server/routes/admin/sidebar-artefact-content.ts
|
|
12620
12841
|
import { readFile as readFile6, readdir as readdir5 } from "fs/promises";
|
|
12621
|
-
import { existsSync as
|
|
12842
|
+
import { existsSync as existsSync23 } from "fs";
|
|
12622
12843
|
import { resolve as resolve22 } from "path";
|
|
12623
12844
|
var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
12624
12845
|
var app33 = new Hono();
|
|
@@ -12632,7 +12853,7 @@ app33.get("/", requireAdminSession, async (c) => {
|
|
|
12632
12853
|
return new Response("Not found", { status: 404 });
|
|
12633
12854
|
}
|
|
12634
12855
|
const dir = resolve22(ATTACHMENTS_ROOT, accountId, id);
|
|
12635
|
-
if (!
|
|
12856
|
+
if (!existsSync23(dir)) {
|
|
12636
12857
|
console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
|
|
12637
12858
|
return new Response("Not found", { status: 404 });
|
|
12638
12859
|
}
|
|
@@ -12694,7 +12915,7 @@ app34.route("/sidebar-artefact-content", sidebar_artefact_content_default);
|
|
|
12694
12915
|
var admin_default = app34;
|
|
12695
12916
|
|
|
12696
12917
|
// server/routes/sites.ts
|
|
12697
|
-
import { existsSync as
|
|
12918
|
+
import { existsSync as existsSync24, readFileSync as readFileSync17, realpathSync as realpathSync5, statSync as statSync8 } from "fs";
|
|
12698
12919
|
import { resolve as resolve23 } from "path";
|
|
12699
12920
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
12700
12921
|
var MIME = {
|
|
@@ -12761,7 +12982,7 @@ app35.get("/:rel{.*}", (c) => {
|
|
|
12761
12982
|
}
|
|
12762
12983
|
let stat7;
|
|
12763
12984
|
try {
|
|
12764
|
-
stat7 =
|
|
12985
|
+
stat7 = existsSync24(filePath) ? statSync8(filePath) : null;
|
|
12765
12986
|
} catch {
|
|
12766
12987
|
stat7 = null;
|
|
12767
12988
|
}
|
|
@@ -12774,7 +12995,7 @@ app35.get("/:rel{.*}", (c) => {
|
|
|
12774
12995
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
12775
12996
|
return c.text("Forbidden", 403);
|
|
12776
12997
|
}
|
|
12777
|
-
if (!
|
|
12998
|
+
if (!existsSync24(filePath)) {
|
|
12778
12999
|
console.error(`[sites] not-found path=${reqPath} status=404`);
|
|
12779
13000
|
return c.text("Not found", 404);
|
|
12780
13001
|
}
|
|
@@ -12793,7 +13014,7 @@ app35.get("/:rel{.*}", (c) => {
|
|
|
12793
13014
|
}
|
|
12794
13015
|
let body;
|
|
12795
13016
|
try {
|
|
12796
|
-
body =
|
|
13017
|
+
body = readFileSync17(realPath);
|
|
12797
13018
|
} catch (err) {
|
|
12798
13019
|
const code = err?.code;
|
|
12799
13020
|
if (code === "EISDIR") {
|
|
@@ -12925,14 +13146,14 @@ function clientFrom(c) {
|
|
|
12925
13146
|
);
|
|
12926
13147
|
}
|
|
12927
13148
|
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
12928
|
-
var BRAND_JSON_PATH = PLATFORM_ROOT7 ?
|
|
13149
|
+
var BRAND_JSON_PATH = PLATFORM_ROOT7 ? join11(PLATFORM_ROOT7, "config", "brand.json") : "";
|
|
12929
13150
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", domain: "getmaxy.com" };
|
|
12930
|
-
if (BRAND_JSON_PATH && !
|
|
13151
|
+
if (BRAND_JSON_PATH && !existsSync25(BRAND_JSON_PATH)) {
|
|
12931
13152
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
12932
13153
|
}
|
|
12933
|
-
if (BRAND_JSON_PATH &&
|
|
13154
|
+
if (BRAND_JSON_PATH && existsSync25(BRAND_JSON_PATH)) {
|
|
12934
13155
|
try {
|
|
12935
|
-
const parsed = JSON.parse(
|
|
13156
|
+
const parsed = JSON.parse(readFileSync18(BRAND_JSON_PATH, "utf-8"));
|
|
12936
13157
|
BRAND = { ...BRAND, ...parsed };
|
|
12937
13158
|
} catch (err) {
|
|
12938
13159
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -12951,11 +13172,11 @@ var brandLoginOpts = {
|
|
|
12951
13172
|
bodyFont: BRAND.defaultFonts?.body,
|
|
12952
13173
|
logoContainsName: !!BRAND.logoContainsName
|
|
12953
13174
|
};
|
|
12954
|
-
var ALIAS_DOMAINS_PATH2 =
|
|
13175
|
+
var ALIAS_DOMAINS_PATH2 = join11(homedir2(), BRAND.configDir, "alias-domains.json");
|
|
12955
13176
|
function loadAliasDomains() {
|
|
12956
13177
|
try {
|
|
12957
|
-
if (!
|
|
12958
|
-
const parsed = JSON.parse(
|
|
13178
|
+
if (!existsSync25(ALIAS_DOMAINS_PATH2)) return null;
|
|
13179
|
+
const parsed = JSON.parse(readFileSync18(ALIAS_DOMAINS_PATH2, "utf-8"));
|
|
12959
13180
|
if (!Array.isArray(parsed)) {
|
|
12960
13181
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
12961
13182
|
return null;
|
|
@@ -13301,14 +13522,14 @@ app36.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
13301
13522
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
13302
13523
|
return c.text("Forbidden", 403);
|
|
13303
13524
|
}
|
|
13304
|
-
if (!
|
|
13525
|
+
if (!existsSync25(filePath)) {
|
|
13305
13526
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
13306
13527
|
return c.text("Not found", 404);
|
|
13307
13528
|
}
|
|
13308
13529
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
13309
13530
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
13310
13531
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
13311
|
-
const body =
|
|
13532
|
+
const body = readFileSync18(filePath);
|
|
13312
13533
|
return c.body(body, 200, {
|
|
13313
13534
|
"Content-Type": contentType,
|
|
13314
13535
|
"Cache-Control": "public, max-age=3600"
|
|
@@ -13331,14 +13552,14 @@ app36.get("/generated/:filename", (c) => {
|
|
|
13331
13552
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
13332
13553
|
return c.text("Forbidden", 403);
|
|
13333
13554
|
}
|
|
13334
|
-
if (!
|
|
13555
|
+
if (!existsSync25(filePath)) {
|
|
13335
13556
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
13336
13557
|
return c.text("Not found", 404);
|
|
13337
13558
|
}
|
|
13338
13559
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
13339
13560
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
13340
13561
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
13341
|
-
const body =
|
|
13562
|
+
const body = readFileSync18(filePath);
|
|
13342
13563
|
return c.body(body, 200, {
|
|
13343
13564
|
"Content-Type": contentType,
|
|
13344
13565
|
"Cache-Control": "public, max-age=86400"
|
|
@@ -13348,9 +13569,9 @@ app36.route("/sites", sites_default);
|
|
|
13348
13569
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
13349
13570
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
13350
13571
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
13351
|
-
if (BRAND_JSON_PATH &&
|
|
13572
|
+
if (BRAND_JSON_PATH && existsSync25(BRAND_JSON_PATH)) {
|
|
13352
13573
|
try {
|
|
13353
|
-
const fullBrand = JSON.parse(
|
|
13574
|
+
const fullBrand = JSON.parse(readFileSync18(BRAND_JSON_PATH, "utf-8"));
|
|
13354
13575
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
13355
13576
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
13356
13577
|
} catch {
|
|
@@ -13367,9 +13588,9 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
13367
13588
|
function readInstalledVersion() {
|
|
13368
13589
|
try {
|
|
13369
13590
|
if (!PLATFORM_ROOT7) return "unknown";
|
|
13370
|
-
const versionFile =
|
|
13371
|
-
if (!
|
|
13372
|
-
const content =
|
|
13591
|
+
const versionFile = join11(PLATFORM_ROOT7, "config", `.${BRAND.hostname}-version`);
|
|
13592
|
+
if (!existsSync25(versionFile)) return "unknown";
|
|
13593
|
+
const content = readFileSync18(versionFile, "utf-8").trim();
|
|
13373
13594
|
return content || "unknown";
|
|
13374
13595
|
} catch {
|
|
13375
13596
|
return "unknown";
|
|
@@ -13410,7 +13631,7 @@ var clientErrorReporterScript = `<script>
|
|
|
13410
13631
|
function cachedHtml(file) {
|
|
13411
13632
|
let html = htmlCache.get(file);
|
|
13412
13633
|
if (!html) {
|
|
13413
|
-
html =
|
|
13634
|
+
html = readFileSync18(resolve24(process.cwd(), "public", file), "utf-8");
|
|
13414
13635
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
13415
13636
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
13416
13637
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -13426,26 +13647,26 @@ ${clientErrorReporterScript}
|
|
|
13426
13647
|
}
|
|
13427
13648
|
var brandedHtmlCache = /* @__PURE__ */ new Map();
|
|
13428
13649
|
function loadBrandingCache(agentSlug) {
|
|
13429
|
-
const configDir2 =
|
|
13650
|
+
const configDir2 = join11(homedir2(), BRAND.configDir);
|
|
13430
13651
|
try {
|
|
13431
|
-
const accountJsonPath =
|
|
13432
|
-
if (!
|
|
13433
|
-
const account = JSON.parse(
|
|
13652
|
+
const accountJsonPath = join11(configDir2, "account.json");
|
|
13653
|
+
if (!existsSync25(accountJsonPath)) return null;
|
|
13654
|
+
const account = JSON.parse(readFileSync18(accountJsonPath, "utf-8"));
|
|
13434
13655
|
const accountId = account.accountId;
|
|
13435
13656
|
if (!accountId) return null;
|
|
13436
|
-
const cachePath =
|
|
13437
|
-
if (!
|
|
13438
|
-
return JSON.parse(
|
|
13657
|
+
const cachePath = join11(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
13658
|
+
if (!existsSync25(cachePath)) return null;
|
|
13659
|
+
return JSON.parse(readFileSync18(cachePath, "utf-8"));
|
|
13439
13660
|
} catch {
|
|
13440
13661
|
return null;
|
|
13441
13662
|
}
|
|
13442
13663
|
}
|
|
13443
13664
|
function resolveDefaultSlug() {
|
|
13444
13665
|
try {
|
|
13445
|
-
const configDir2 =
|
|
13446
|
-
const accountJsonPath =
|
|
13447
|
-
if (!
|
|
13448
|
-
const account = JSON.parse(
|
|
13666
|
+
const configDir2 = join11(homedir2(), BRAND.configDir);
|
|
13667
|
+
const accountJsonPath = join11(configDir2, "account.json");
|
|
13668
|
+
if (!existsSync25(accountJsonPath)) return null;
|
|
13669
|
+
const account = JSON.parse(readFileSync18(accountJsonPath, "utf-8"));
|
|
13449
13670
|
return account.defaultAgent || null;
|
|
13450
13671
|
} catch {
|
|
13451
13672
|
return null;
|
|
@@ -13518,7 +13739,7 @@ app36.use("/vnc-popout.html", logViewerFetch);
|
|
|
13518
13739
|
app36.get("/vnc-popout.html", (c) => {
|
|
13519
13740
|
let html = htmlCache.get("vnc-popout.html");
|
|
13520
13741
|
if (!html) {
|
|
13521
|
-
html =
|
|
13742
|
+
html = readFileSync18(resolve24(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
13522
13743
|
const name = escapeHtml(BRAND.productName);
|
|
13523
13744
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
13524
13745
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -13608,8 +13829,8 @@ try {
|
|
|
13608
13829
|
(async () => {
|
|
13609
13830
|
try {
|
|
13610
13831
|
let userId = "";
|
|
13611
|
-
if (
|
|
13612
|
-
const users = JSON.parse(
|
|
13832
|
+
if (existsSync25(USERS_FILE)) {
|
|
13833
|
+
const users = JSON.parse(readFileSync18(USERS_FILE, "utf-8").trim() || "[]");
|
|
13613
13834
|
userId = users[0]?.userId ?? "";
|
|
13614
13835
|
}
|
|
13615
13836
|
await backfillNullUserIdConversations(userId);
|
|
@@ -13669,6 +13890,48 @@ for (const dir of bootEnabled) {
|
|
|
13669
13890
|
bootDelivered.push(dir);
|
|
13670
13891
|
}
|
|
13671
13892
|
console.error(`[plugins] readiness enabled=${bootEnabled.length} delivered=${bootDelivered.length} dist-missing=[${bootDistMissing.join(",")}] missing=[${bootMissing.join(",")}]`);
|
|
13893
|
+
(async () => {
|
|
13894
|
+
if (!bootAccount) {
|
|
13895
|
+
console.log("[action-completion-relay] phase=consumed-skip reason=no-account");
|
|
13896
|
+
return;
|
|
13897
|
+
}
|
|
13898
|
+
let records;
|
|
13899
|
+
try {
|
|
13900
|
+
records = consumeActionCompletionRelays(bootAccount.accountDir);
|
|
13901
|
+
} catch (err) {
|
|
13902
|
+
console.error(`[action-completion-relay] phase=consume-failed error=${err instanceof Error ? err.message : String(err)}`);
|
|
13903
|
+
return;
|
|
13904
|
+
}
|
|
13905
|
+
if (records.length === 0) {
|
|
13906
|
+
console.log(`[action-completion-relay] phase=consumed-empty accountId=${bootAccount.accountId.slice(0, 8)}\u2026`);
|
|
13907
|
+
return;
|
|
13908
|
+
}
|
|
13909
|
+
console.log(`[action-completion-relay] phase=consume-batch count=${records.length} accountId=${bootAccount.accountId.slice(0, 8)}\u2026`);
|
|
13910
|
+
for (const rec of records) {
|
|
13911
|
+
const sessionKey = `cloudflare-relay-boot:${rec.actionId}`;
|
|
13912
|
+
let outcome = "injected";
|
|
13913
|
+
let dispatchError;
|
|
13914
|
+
try {
|
|
13915
|
+
registerSession(sessionKey, "admin", bootAccount.accountId);
|
|
13916
|
+
setConversationIdForSession(sessionKey, rec.conversationId);
|
|
13917
|
+
for await (const _ev of invokeAgent({ type: "admin" }, rec.message, sessionKey)) {
|
|
13918
|
+
}
|
|
13919
|
+
} catch (err) {
|
|
13920
|
+
outcome = "dispatch-failed";
|
|
13921
|
+
dispatchError = err instanceof Error ? err.message : String(err);
|
|
13922
|
+
} finally {
|
|
13923
|
+
unregisterSession(sessionKey);
|
|
13924
|
+
}
|
|
13925
|
+
if (outcome === "injected") {
|
|
13926
|
+
deleteConsumedRelay(rec.filePath);
|
|
13927
|
+
console.log(`[action-completion-relay] phase=consumed actionId=${rec.actionId} conversationId=${rec.conversationId} ageMs=${rec.ageMs} outcome=injected`);
|
|
13928
|
+
} else {
|
|
13929
|
+
console.error(`[action-completion-relay] phase=consumed actionId=${rec.actionId} conversationId=${rec.conversationId} ageMs=${rec.ageMs} outcome=${outcome} reason=${JSON.stringify(dispatchError ?? "")} fileRetained=${JSON.stringify(rec.filePath)}`);
|
|
13930
|
+
}
|
|
13931
|
+
}
|
|
13932
|
+
})().catch((err) => {
|
|
13933
|
+
console.error(`[action-completion-relay] boot-drain rejected: ${err instanceof Error ? err.message : String(err)}`);
|
|
13934
|
+
});
|
|
13672
13935
|
if (bootAccountConfig?.whatsapp) {
|
|
13673
13936
|
console.error(`[whatsapp:boot] loading whatsapp config from account.json publicAgent=${bootPublicAgent ?? "none"}`);
|
|
13674
13937
|
} else {
|
|
@@ -13676,7 +13939,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
13676
13939
|
}
|
|
13677
13940
|
init({
|
|
13678
13941
|
configDir: configDirForWhatsApp,
|
|
13679
|
-
platformRoot: resolve24(process.env.MAXY_PLATFORM_ROOT ??
|
|
13942
|
+
platformRoot: resolve24(process.env.MAXY_PLATFORM_ROOT ?? join11(__dirname, "..")),
|
|
13680
13943
|
accountConfig: bootAccountConfig,
|
|
13681
13944
|
onMessage: async (msg) => {
|
|
13682
13945
|
try {
|