@rubytech/create-maxy-code 0.1.274 → 0.1.276
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/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +1 -4
- package/payload/platform/plugins/admin/mcp/dist/index.js +0 -8
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/docs/references/admin-identity-gate.md +40 -81
- package/payload/platform/scripts/setup-account.sh +0 -5
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +0 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +0 -17
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +4 -5
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/server.js +51 -28
- package/payload/platform/services/whatsapp-channel/dist/server.js.map +1 -1
- package/payload/platform/templates/agents/admin/IDENTITY.md +1 -1
- package/payload/premium-plugins/writer-craft/mcp/dist/index.js +1 -1
- package/payload/premium-plugins/writer-craft/mcp/dist/index.js.map +1 -1
- package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.d.ts +2 -0
- package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.d.ts.map +1 -1
- package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.js +1 -1
- package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.js.map +1 -1
- package/payload/premium-plugins/writer-craft/mcp/src/index.ts +1 -1
- package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-distil-profile.ts +3 -1
- package/payload/server/server.js +287 -463
- package/payload/platform/plugins/admin/hooks/__tests__/pin-identity-gate.test.sh +0 -96
- package/payload/platform/plugins/admin/hooks/pin-identity-gate.sh +0 -146
package/payload/server/server.js
CHANGED
|
@@ -604,46 +604,6 @@ var require_dist2 = __commonJS({
|
|
|
604
604
|
}
|
|
605
605
|
});
|
|
606
606
|
|
|
607
|
-
// ../lib/require-port-env/dist/index.js
|
|
608
|
-
var require_dist3 = __commonJS({
|
|
609
|
-
"../lib/require-port-env/dist/index.js"(exports) {
|
|
610
|
-
"use strict";
|
|
611
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
612
|
-
exports.MissingPortEnvError = void 0;
|
|
613
|
-
exports.requirePortEnv = requirePortEnv3;
|
|
614
|
-
var MissingPortEnvError = class extends Error {
|
|
615
|
-
envName;
|
|
616
|
-
tag;
|
|
617
|
-
failLine;
|
|
618
|
-
constructor(envName, tag, failLine, message) {
|
|
619
|
-
super(message);
|
|
620
|
-
this.name = "MissingPortEnvError";
|
|
621
|
-
this.envName = envName;
|
|
622
|
-
this.tag = tag;
|
|
623
|
-
this.failLine = failLine;
|
|
624
|
-
}
|
|
625
|
-
};
|
|
626
|
-
exports.MissingPortEnvError = MissingPortEnvError;
|
|
627
|
-
var VALID_PORT_MIN = 1;
|
|
628
|
-
var VALID_PORT_MAX = 65535;
|
|
629
|
-
function requirePortEnv3(envName, options = {}) {
|
|
630
|
-
const tag = options.tag ?? "port-env";
|
|
631
|
-
const failLine = options.failLine ?? "missing-port-env";
|
|
632
|
-
const raw = process.env[envName];
|
|
633
|
-
if (raw === void 0 || raw === "") {
|
|
634
|
-
const msg = `[${tag}] ${failLine} reason=missing-env env=${envName}`;
|
|
635
|
-
throw new MissingPortEnvError(envName, tag, failLine, msg);
|
|
636
|
-
}
|
|
637
|
-
const parsed = Number.parseInt(raw, 10);
|
|
638
|
-
if (!Number.isInteger(parsed) || parsed < VALID_PORT_MIN || parsed > VALID_PORT_MAX || String(parsed) !== raw.trim()) {
|
|
639
|
-
const msg = `[${tag}] ${failLine} reason=invalid-port-env env=${envName} value=${JSON.stringify(raw)}`;
|
|
640
|
-
throw new MissingPortEnvError(envName, tag, failLine, msg);
|
|
641
|
-
}
|
|
642
|
-
return parsed;
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
});
|
|
646
|
-
|
|
647
607
|
// ../lib/graph-write/dist/audit.js
|
|
648
608
|
var require_audit = __commonJS({
|
|
649
609
|
"../lib/graph-write/dist/audit.js"(exports) {
|
|
@@ -725,7 +685,7 @@ var require_conversation_provenance = __commonJS({
|
|
|
725
685
|
"use strict";
|
|
726
686
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
727
687
|
exports.injectConversationProvenance = injectConversationProvenance;
|
|
728
|
-
var index_js_1 =
|
|
688
|
+
var index_js_1 = require_dist3();
|
|
729
689
|
async function injectConversationProvenance(params) {
|
|
730
690
|
const { session, relationships, accountId, writeLabels, conversationNodeId, logNamespace, tool } = params;
|
|
731
691
|
const original = [...relationships];
|
|
@@ -775,7 +735,7 @@ var require_conversation_provenance = __commonJS({
|
|
|
775
735
|
});
|
|
776
736
|
|
|
777
737
|
// ../lib/graph-write/dist/index.js
|
|
778
|
-
var
|
|
738
|
+
var require_dist3 = __commonJS({
|
|
779
739
|
"../lib/graph-write/dist/index.js"(exports) {
|
|
780
740
|
"use strict";
|
|
781
741
|
var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
@@ -5526,21 +5486,6 @@ function handlePublicSessionExit(sessionId) {
|
|
|
5526
5486
|
});
|
|
5527
5487
|
}
|
|
5528
5488
|
|
|
5529
|
-
// app/lib/channel-pty-bridge/inbound-outcome.ts
|
|
5530
|
-
var TAG17 = "[whatsapp-adaptor]";
|
|
5531
|
-
var tallies = /* @__PURE__ */ new Map();
|
|
5532
|
-
function recordInboundOutcome(senderId, outcome) {
|
|
5533
|
-
let t = tallies.get(senderId);
|
|
5534
|
-
if (!t) {
|
|
5535
|
-
t = { "relay-ok": 0, "timeout-no-turn": 0, "timeout-relay-missed": 0 };
|
|
5536
|
-
tallies.set(senderId, t);
|
|
5537
|
-
}
|
|
5538
|
-
t[outcome] += 1;
|
|
5539
|
-
console.error(
|
|
5540
|
-
`${TAG17} op=inbound-outcome sender=${senderId} relay-ok=${t["relay-ok"]} timeout-no-turn=${t["timeout-no-turn"]} timeout-relay-missed=${t["timeout-relay-missed"]}`
|
|
5541
|
-
);
|
|
5542
|
-
}
|
|
5543
|
-
|
|
5544
5489
|
// app/lib/access-session-store.ts
|
|
5545
5490
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
5546
5491
|
var sessions = /* @__PURE__ */ new Map();
|
|
@@ -5816,7 +5761,7 @@ import { randomUUID as randomUUID6 } from "crypto";
|
|
|
5816
5761
|
// app/lib/whatsapp/config-persist.ts
|
|
5817
5762
|
import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync3 } from "fs";
|
|
5818
5763
|
import { resolve as resolve6, join as join4 } from "path";
|
|
5819
|
-
var
|
|
5764
|
+
var TAG17 = "[whatsapp:config]";
|
|
5820
5765
|
function configPath(accountDir) {
|
|
5821
5766
|
return resolve6(accountDir, "account.json");
|
|
5822
5767
|
}
|
|
@@ -5833,9 +5778,9 @@ function reloadManagerConfig(accountDir) {
|
|
|
5833
5778
|
try {
|
|
5834
5779
|
const config = readConfig(accountDir);
|
|
5835
5780
|
reloadConfig(config);
|
|
5836
|
-
console.error(`${
|
|
5781
|
+
console.error(`${TAG17} reloaded manager config`);
|
|
5837
5782
|
} catch (err) {
|
|
5838
|
-
console.error(`${
|
|
5783
|
+
console.error(`${TAG17} manager config reload failed: ${String(err)}`);
|
|
5839
5784
|
}
|
|
5840
5785
|
}
|
|
5841
5786
|
var E164_PATTERN = /^\+\d{7,15}$/;
|
|
@@ -5861,25 +5806,25 @@ function persistAfterPairing(accountDir, accountId, selfPhone) {
|
|
|
5861
5806
|
const adminPhones = wa.adminPhones;
|
|
5862
5807
|
if (!adminPhones.includes(normalized)) {
|
|
5863
5808
|
adminPhones.push(normalized);
|
|
5864
|
-
console.error(`${
|
|
5809
|
+
console.error(`${TAG17} added selfPhone=${normalized} to adminPhones`);
|
|
5865
5810
|
}
|
|
5866
5811
|
} else {
|
|
5867
|
-
console.error(`${
|
|
5812
|
+
console.error(`${TAG17} skipping adminPhones \u2014 selfPhone is null account=${accountId}`);
|
|
5868
5813
|
}
|
|
5869
5814
|
const parsed = WhatsAppConfigSchema.safeParse(wa);
|
|
5870
5815
|
if (!parsed.success) {
|
|
5871
5816
|
const msg = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
|
|
5872
|
-
console.error(`${
|
|
5817
|
+
console.error(`${TAG17} validation failed after pairing: ${msg}`);
|
|
5873
5818
|
return { ok: false, error: `Validation failed: ${msg}` };
|
|
5874
5819
|
}
|
|
5875
5820
|
config.whatsapp = parsed.data;
|
|
5876
5821
|
writeConfig(accountDir, config);
|
|
5877
|
-
console.error(`${
|
|
5822
|
+
console.error(`${TAG17} persisted after pairing account=${accountId} phone=${selfPhone ?? "null"}`);
|
|
5878
5823
|
reloadManagerConfig(accountDir);
|
|
5879
5824
|
return { ok: true };
|
|
5880
5825
|
} catch (err) {
|
|
5881
5826
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5882
|
-
console.error(`${
|
|
5827
|
+
console.error(`${TAG17} persist failed account=${accountId}: ${msg}`);
|
|
5883
5828
|
return { ok: false, error: msg };
|
|
5884
5829
|
}
|
|
5885
5830
|
}
|
|
@@ -5909,12 +5854,12 @@ function addAdminPhone(accountDir, phone) {
|
|
|
5909
5854
|
}
|
|
5910
5855
|
config.whatsapp = parsed.data;
|
|
5911
5856
|
writeConfig(accountDir, config);
|
|
5912
|
-
console.error(`${
|
|
5857
|
+
console.error(`${TAG17} added admin phone=${normalized}`);
|
|
5913
5858
|
reloadManagerConfig(accountDir);
|
|
5914
5859
|
return { ok: true, message: `Added ${normalized} as admin phone. Messages from this number will route to the admin agent.` };
|
|
5915
5860
|
} catch (err) {
|
|
5916
5861
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5917
|
-
console.error(`${
|
|
5862
|
+
console.error(`${TAG17} addAdminPhone failed: ${msg}`);
|
|
5918
5863
|
return { ok: false, error: msg };
|
|
5919
5864
|
}
|
|
5920
5865
|
}
|
|
@@ -5942,12 +5887,12 @@ function removeAdminPhone(accountDir, phone) {
|
|
|
5942
5887
|
}
|
|
5943
5888
|
config.whatsapp = parsed.data;
|
|
5944
5889
|
writeConfig(accountDir, config);
|
|
5945
|
-
console.error(`${
|
|
5890
|
+
console.error(`${TAG17} removed admin phone=${normalized}`);
|
|
5946
5891
|
reloadManagerConfig(accountDir);
|
|
5947
5892
|
return { ok: true, message: `Removed ${normalized} from admin phones. Messages from this number will now route to the public agent.` };
|
|
5948
5893
|
} catch (err) {
|
|
5949
5894
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5950
|
-
console.error(`${
|
|
5895
|
+
console.error(`${TAG17} removeAdminPhone failed: ${msg}`);
|
|
5951
5896
|
return { ok: false, error: msg };
|
|
5952
5897
|
}
|
|
5953
5898
|
}
|
|
@@ -5985,12 +5930,12 @@ function setPublicAgent(accountDir, slug) {
|
|
|
5985
5930
|
}
|
|
5986
5931
|
config.whatsapp = parsed.data;
|
|
5987
5932
|
writeConfig(accountDir, config);
|
|
5988
|
-
console.error(`${
|
|
5933
|
+
console.error(`${TAG17} publicAgent set to ${trimmed}`);
|
|
5989
5934
|
reloadManagerConfig(accountDir);
|
|
5990
5935
|
return { ok: true, message: `Public agent set to "${trimmed}". WhatsApp messages from non-admin phones will be handled by this agent.` };
|
|
5991
5936
|
} catch (err) {
|
|
5992
5937
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5993
|
-
console.error(`${
|
|
5938
|
+
console.error(`${TAG17} setPublicAgent failed: ${msg}`);
|
|
5994
5939
|
return { ok: false, error: msg };
|
|
5995
5940
|
}
|
|
5996
5941
|
}
|
|
@@ -6054,12 +5999,12 @@ function setGroupPublicAgent(accountDir, accountId, groupJid, slug) {
|
|
|
6054
5999
|
}
|
|
6055
6000
|
config.whatsapp = parsed.data;
|
|
6056
6001
|
writeConfig(accountDir, config);
|
|
6057
|
-
console.error(`${
|
|
6002
|
+
console.error(`${TAG17} setGroupPublicAgent account=${trimmedAccount} groupJid=${trimmedGroup} slug=${trimmedSlug}`);
|
|
6058
6003
|
reloadManagerConfig(accountDir);
|
|
6059
6004
|
return { ok: true, message: `Per-group public agent set to "${trimmedSlug}" for group ${trimmedGroup}.` };
|
|
6060
6005
|
} catch (err) {
|
|
6061
6006
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6062
|
-
console.error(`${
|
|
6007
|
+
console.error(`${TAG17} setGroupPublicAgent failed: ${msg}`);
|
|
6063
6008
|
return { ok: false, error: msg };
|
|
6064
6009
|
}
|
|
6065
6010
|
}
|
|
@@ -6086,12 +6031,12 @@ function unsetGroupPublicAgent(accountDir, accountId, groupJid) {
|
|
|
6086
6031
|
}
|
|
6087
6032
|
config.whatsapp = parsed.data;
|
|
6088
6033
|
writeConfig(accountDir, config);
|
|
6089
|
-
console.error(`${
|
|
6034
|
+
console.error(`${TAG17} unsetGroupPublicAgent account=${trimmedAccount} groupJid=${trimmedGroup}`);
|
|
6090
6035
|
reloadManagerConfig(accountDir);
|
|
6091
6036
|
return { ok: true, message: `Per-group public agent override removed for group ${trimmedGroup}.` };
|
|
6092
6037
|
} catch (err) {
|
|
6093
6038
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6094
|
-
console.error(`${
|
|
6039
|
+
console.error(`${TAG17} unsetGroupPublicAgent failed: ${msg}`);
|
|
6095
6040
|
return { ok: false, error: msg };
|
|
6096
6041
|
}
|
|
6097
6042
|
}
|
|
@@ -6112,17 +6057,17 @@ function updateConfig(accountDir, fields) {
|
|
|
6112
6057
|
const parsed = WhatsAppConfigSchema.safeParse(wa);
|
|
6113
6058
|
if (!parsed.success) {
|
|
6114
6059
|
const msg = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
|
|
6115
|
-
console.error(`${
|
|
6060
|
+
console.error(`${TAG17} update validation failed: ${msg}`);
|
|
6116
6061
|
return { ok: false, error: `Validation failed: ${msg}` };
|
|
6117
6062
|
}
|
|
6118
6063
|
config.whatsapp = parsed.data;
|
|
6119
6064
|
writeConfig(accountDir, config);
|
|
6120
|
-
console.error(`${
|
|
6065
|
+
console.error(`${TAG17} updated fields=[${fieldNames.join(",")}]`);
|
|
6121
6066
|
reloadManagerConfig(accountDir);
|
|
6122
6067
|
return { ok: true, message: `Updated WhatsApp config: ${fieldNames.join(", ")}.` };
|
|
6123
6068
|
} catch (err) {
|
|
6124
6069
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6125
|
-
console.error(`${
|
|
6070
|
+
console.error(`${TAG17} updateConfig failed: ${msg}`);
|
|
6126
6071
|
return { ok: false, error: msg };
|
|
6127
6072
|
}
|
|
6128
6073
|
}
|
|
@@ -6140,7 +6085,7 @@ function getConfig(accountDir) {
|
|
|
6140
6085
|
}
|
|
6141
6086
|
|
|
6142
6087
|
// app/lib/whatsapp/login.ts
|
|
6143
|
-
var
|
|
6088
|
+
var TAG18 = "[whatsapp:login]";
|
|
6144
6089
|
function maskPhone(digits) {
|
|
6145
6090
|
if (digits.length <= 4) return "*".repeat(digits.length);
|
|
6146
6091
|
return digits.slice(0, 2) + "*".repeat(digits.length - 4) + digits.slice(-2);
|
|
@@ -6151,7 +6096,7 @@ function closeSocket(sock) {
|
|
|
6151
6096
|
try {
|
|
6152
6097
|
sock.ws?.close?.();
|
|
6153
6098
|
} catch (err) {
|
|
6154
|
-
console.warn(`${
|
|
6099
|
+
console.warn(`${TAG18} socket close error during cleanup: ${String(err)}`);
|
|
6155
6100
|
}
|
|
6156
6101
|
}
|
|
6157
6102
|
function resetActiveLogin(accountId) {
|
|
@@ -6178,18 +6123,18 @@ async function runPostPairing(login) {
|
|
|
6178
6123
|
const masked = selfPhone ? `${selfPhone.slice(0, 4)}***` : "null";
|
|
6179
6124
|
console.error(`[whatsapp-persist] wa-persist-on-connect account=${login.accountId} phone=${masked}`);
|
|
6180
6125
|
} else {
|
|
6181
|
-
console.error(`${
|
|
6126
|
+
console.error(`${TAG18} wa-persist-on-connect FAILED account=${login.accountId}: ${result.error}`);
|
|
6182
6127
|
}
|
|
6183
6128
|
} catch (err) {
|
|
6184
|
-
console.error(`${
|
|
6129
|
+
console.error(`${TAG18} wa-persist-on-connect error account=${login.accountId}: ${String(err)}`);
|
|
6185
6130
|
}
|
|
6186
6131
|
} else {
|
|
6187
|
-
console.error(`${
|
|
6132
|
+
console.error(`${TAG18} wa-persist-on-connect skipped \u2014 no accountDir account=${login.accountId}`);
|
|
6188
6133
|
}
|
|
6189
6134
|
try {
|
|
6190
6135
|
await registerLoginSocket(login.accountId, login.sock, login.authDir);
|
|
6191
6136
|
} catch (err) {
|
|
6192
|
-
console.error(`${
|
|
6137
|
+
console.error(`${TAG18} registerLoginSocket failed account=${login.accountId}: ${String(err)}`);
|
|
6193
6138
|
}
|
|
6194
6139
|
}
|
|
6195
6140
|
async function loginConnectionLoop(accountId, login) {
|
|
@@ -6201,7 +6146,7 @@ async function loginConnectionLoop(accountId, login) {
|
|
|
6201
6146
|
if (current?.id === login.id) {
|
|
6202
6147
|
await runPostPairing(current);
|
|
6203
6148
|
current.connected = true;
|
|
6204
|
-
console.error(`${
|
|
6149
|
+
console.error(`${TAG18} loginConnectionLoop: connected account=${accountId} attempt=${attempt} configPersisted=${current.configPersisted}`);
|
|
6205
6150
|
}
|
|
6206
6151
|
return;
|
|
6207
6152
|
} catch (err) {
|
|
@@ -6211,7 +6156,7 @@ async function loginConnectionLoop(accountId, login) {
|
|
|
6211
6156
|
if (!classification.shouldRetry || attempt >= LOGIN_MAX_RECONNECTS) {
|
|
6212
6157
|
if (attempt >= LOGIN_MAX_RECONNECTS) {
|
|
6213
6158
|
console.error(
|
|
6214
|
-
`${
|
|
6159
|
+
`${TAG18} login reconnect attempts exhausted (${attempt}/${LOGIN_MAX_RECONNECTS}) \u2014 surfacing error to agent`
|
|
6215
6160
|
);
|
|
6216
6161
|
current.error = `Login failed after ${attempt} reconnect attempts: ${formatError(err)}`;
|
|
6217
6162
|
} else {
|
|
@@ -6223,7 +6168,7 @@ async function loginConnectionLoop(accountId, login) {
|
|
|
6223
6168
|
attempt++;
|
|
6224
6169
|
const delay = LOGIN_RECONNECT_DELAYS[attempt - 1] ?? 8e3;
|
|
6225
6170
|
console.error(
|
|
6226
|
-
`${
|
|
6171
|
+
`${TAG18} status=${classification.statusCode ?? "unknown"} restart required \u2014 reconnecting with saved creds (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}) delay=${delay}ms`
|
|
6227
6172
|
);
|
|
6228
6173
|
closeSocket(current.sock);
|
|
6229
6174
|
await new Promise((r) => setTimeout(r, delay));
|
|
@@ -6234,7 +6179,7 @@ async function loginConnectionLoop(accountId, login) {
|
|
|
6234
6179
|
current.sock = newSock;
|
|
6235
6180
|
} catch (sockErr) {
|
|
6236
6181
|
console.error(
|
|
6237
|
-
`${
|
|
6182
|
+
`${TAG18} reconnect socket creation failed (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}): ${String(sockErr)}`
|
|
6238
6183
|
);
|
|
6239
6184
|
current.error = `Reconnection failed: ${String(sockErr)}`;
|
|
6240
6185
|
return;
|
|
@@ -6248,7 +6193,7 @@ async function startLogin(opts) {
|
|
|
6248
6193
|
const hasAuth = await authExists(authDir);
|
|
6249
6194
|
const selfId = readSelfId(authDir);
|
|
6250
6195
|
console.error(
|
|
6251
|
-
`${
|
|
6196
|
+
`${TAG18} startLogin account=${accountId} force=${!!force} hasAuth=${hasAuth}` + (existing0 ? ` activeLogin={id=${existing0.id.slice(0, 8)},age=${Math.round((Date.now() - existing0.startedAt) / 1e3)}s,hasCode=${!!existing0.pairingCode}}` : " activeLogin=none")
|
|
6252
6197
|
);
|
|
6253
6198
|
if (hasAuth && !force) {
|
|
6254
6199
|
const who = selfId.e164 ?? selfId.jid ?? "unknown";
|
|
@@ -6263,7 +6208,7 @@ async function startLogin(opts) {
|
|
|
6263
6208
|
}
|
|
6264
6209
|
const existing = activeLogins.get(accountId);
|
|
6265
6210
|
if (existing && isLoginFresh(existing) && existing.pairingCode && !force) {
|
|
6266
|
-
console.error(`${
|
|
6211
|
+
console.error(`${TAG18} startLogin account=${accountId} guard: returning existing pairing code (age=${Math.round((Date.now() - existing.startedAt) / 1e3)}s)`);
|
|
6267
6212
|
return {
|
|
6268
6213
|
pairingCode: existing.pairingCode,
|
|
6269
6214
|
phone: existing.phone,
|
|
@@ -6271,7 +6216,7 @@ async function startLogin(opts) {
|
|
|
6271
6216
|
};
|
|
6272
6217
|
}
|
|
6273
6218
|
if (existing) {
|
|
6274
|
-
console.error(`${
|
|
6219
|
+
console.error(`${TAG18} startLogin account=${accountId} ${force ? "force override" : "stale/no-code"}, resetting active login`);
|
|
6275
6220
|
}
|
|
6276
6221
|
resetActiveLogin(accountId);
|
|
6277
6222
|
await clearAuth(authDir);
|
|
@@ -6301,7 +6246,7 @@ async function startLogin(opts) {
|
|
|
6301
6246
|
const current = activeLogins.get(accountId);
|
|
6302
6247
|
if (current?.id !== login.id) return;
|
|
6303
6248
|
if (!current.pairingCode) current.pairingCode = code;
|
|
6304
|
-
console.error(`${
|
|
6249
|
+
console.error(`${TAG18} pairing-code-issued account=${accountId} phone=${maskPhone(digits)} codeLen=${code.length}`);
|
|
6305
6250
|
resolveCode?.(code);
|
|
6306
6251
|
}).catch((err) => {
|
|
6307
6252
|
clearTimeout(codeTimer);
|
|
@@ -6330,7 +6275,7 @@ async function startLogin(opts) {
|
|
|
6330
6275
|
const ttlTimer = setTimeout(() => {
|
|
6331
6276
|
const current = activeLogins.get(accountId);
|
|
6332
6277
|
if (current?.id === login.id && !current.connected) {
|
|
6333
|
-
console.error(`${
|
|
6278
|
+
console.error(`${TAG18} pairing-window-elapsed account=${accountId} (ttl sweep)`);
|
|
6334
6279
|
resetActiveLogin(accountId);
|
|
6335
6280
|
}
|
|
6336
6281
|
}, ACTIVE_LOGIN_TTL_MS);
|
|
@@ -6338,7 +6283,7 @@ async function startLogin(opts) {
|
|
|
6338
6283
|
ttlTimer.unref();
|
|
6339
6284
|
}
|
|
6340
6285
|
loginConnectionLoop(accountId, login).catch((err) => {
|
|
6341
|
-
console.error(`${
|
|
6286
|
+
console.error(`${TAG18} loginConnectionLoop unexpected error: ${String(err)}`);
|
|
6342
6287
|
const current = activeLogins.get(accountId);
|
|
6343
6288
|
if (current?.id === login.id) {
|
|
6344
6289
|
current.error = `Unexpected login error: ${String(err)}`;
|
|
@@ -6363,13 +6308,13 @@ async function waitForLogin(opts) {
|
|
|
6363
6308
|
const { accountId, timeoutMs = 6e4 } = opts;
|
|
6364
6309
|
const login = activeLogins.get(accountId);
|
|
6365
6310
|
console.error(
|
|
6366
|
-
`${
|
|
6311
|
+
`${TAG18} waitForLogin account=${accountId} timeout=${timeoutMs}ms` + (login ? ` login={id=${login.id.slice(0, 8)},age=${Math.round((Date.now() - login.startedAt) / 1e3)}s,connected=${login.connected},hasCode=${!!login.pairingCode}}` : " login=none")
|
|
6367
6312
|
);
|
|
6368
6313
|
if (!login) {
|
|
6369
6314
|
return { connected: false, message: "No active WhatsApp login in progress.", configPersisted: false };
|
|
6370
6315
|
}
|
|
6371
6316
|
if (!isLoginFresh(login)) {
|
|
6372
|
-
console.error(`${
|
|
6317
|
+
console.error(`${TAG18} pairing-window-elapsed account=${accountId}`);
|
|
6373
6318
|
resetActiveLogin(accountId);
|
|
6374
6319
|
return { connected: false, message: "The pairing window expired. Ask me to generate a new code.", configPersisted: false };
|
|
6375
6320
|
}
|
|
@@ -6377,8 +6322,8 @@ async function waitForLogin(opts) {
|
|
|
6377
6322
|
while (Date.now() < deadline) {
|
|
6378
6323
|
if (login.connected) {
|
|
6379
6324
|
const selfId = readSelfId(login.authDir);
|
|
6380
|
-
console.error(`${
|
|
6381
|
-
console.error(`${
|
|
6325
|
+
console.error(`${TAG18} pairing-connected account=${accountId} phone=${selfId.e164 ?? "unknown"}`);
|
|
6326
|
+
console.error(`${TAG18} login complete for account=${accountId} phone=${selfId.e164 ?? "unknown"} configPersisted=${login.configPersisted}`);
|
|
6382
6327
|
const configPersisted = login.configPersisted;
|
|
6383
6328
|
activeLogins.delete(accountId);
|
|
6384
6329
|
return {
|
|
@@ -6396,7 +6341,7 @@ async function waitForLogin(opts) {
|
|
|
6396
6341
|
await new Promise((r) => setTimeout(r, 1e3));
|
|
6397
6342
|
}
|
|
6398
6343
|
const elapsed = Math.round((Date.now() - (deadline - timeoutMs)) / 1e3);
|
|
6399
|
-
console.error(`${
|
|
6344
|
+
console.error(`${TAG18} waitForLogin poll timeout account=${accountId} elapsed=${elapsed}s \u2014 login kept alive (pairing code still valid)`);
|
|
6400
6345
|
return { connected: false, message: "Still waiting for you to enter the pairing code. The code is still valid \u2014 ask me to keep waiting, or request a new code.", configPersisted: false };
|
|
6401
6346
|
}
|
|
6402
6347
|
|
|
@@ -6511,7 +6456,7 @@ function serializeWhatsAppSchema() {
|
|
|
6511
6456
|
// app/lib/whatsapp/status-reconcile.ts
|
|
6512
6457
|
import { readdirSync as readdirSync2 } from "fs";
|
|
6513
6458
|
import { join as join5 } from "path";
|
|
6514
|
-
var
|
|
6459
|
+
var TAG19 = "[whatsapp:reconcile]";
|
|
6515
6460
|
function listCredsAccountIds(credsRoot) {
|
|
6516
6461
|
try {
|
|
6517
6462
|
return readdirSync2(credsRoot, { withFileTypes: true }).filter((e) => e.isDirectory() && hasCredsSync(join5(credsRoot, e.name))).map((e) => e.name);
|
|
@@ -6533,14 +6478,14 @@ function reconcileCredsOnDisk(opts) {
|
|
|
6533
6478
|
const selfPhone = readSelfId(authDir).e164 ?? void 0;
|
|
6534
6479
|
const configured = accountDir ? isAccountConfigured(accountDir, accountId) : false;
|
|
6535
6480
|
console.error(
|
|
6536
|
-
`${
|
|
6481
|
+
`${TAG19} wa-link-unconfigured account=${accountId} creds=present config=${configured ? "present" : "absent"}`
|
|
6537
6482
|
);
|
|
6538
6483
|
if (!configured && accountDir) {
|
|
6539
6484
|
const result = persistAfterPairing(accountDir, accountId, selfPhone ?? null);
|
|
6540
6485
|
if (result.ok) {
|
|
6541
|
-
console.error(`${
|
|
6486
|
+
console.error(`${TAG19} self-healed account=${accountId}`);
|
|
6542
6487
|
} else {
|
|
6543
|
-
console.error(`${
|
|
6488
|
+
console.error(`${TAG19} self-heal FAILED account=${accountId}: ${result.error}`);
|
|
6544
6489
|
}
|
|
6545
6490
|
}
|
|
6546
6491
|
entries.push({ accountId, selfPhone, connected: false, linkedUnconfigured: !configured });
|
|
@@ -6549,7 +6494,7 @@ function reconcileCredsOnDisk(opts) {
|
|
|
6549
6494
|
}
|
|
6550
6495
|
|
|
6551
6496
|
// server/routes/whatsapp.ts
|
|
6552
|
-
var
|
|
6497
|
+
var TAG20 = "[whatsapp:api]";
|
|
6553
6498
|
var PLATFORM_ROOT4 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
6554
6499
|
var app3 = new Hono();
|
|
6555
6500
|
app3.get("/status", (c) => {
|
|
@@ -6561,10 +6506,10 @@ app3.get("/status", (c) => {
|
|
|
6561
6506
|
const reconciled = reconcileCredsOnDisk({ credsRoot, accountDir, liveAccountIds: liveIds });
|
|
6562
6507
|
const accounts = [...live, ...reconciled];
|
|
6563
6508
|
const summary = accounts.map((a) => `${a.accountId}:${a.connected ? "up" : a.linkedUnconfigured ? "linked-unconfigured" : "down"}`).join(", ");
|
|
6564
|
-
console.error(`${
|
|
6509
|
+
console.error(`${TAG20} status accounts=${accounts.length} [${summary}]`);
|
|
6565
6510
|
return c.json({ accounts });
|
|
6566
6511
|
} catch (err) {
|
|
6567
|
-
console.error(`${
|
|
6512
|
+
console.error(`${TAG20} status error: ${String(err)}`);
|
|
6568
6513
|
return c.json({ error: String(err) }, 500);
|
|
6569
6514
|
}
|
|
6570
6515
|
});
|
|
@@ -6580,10 +6525,10 @@ app3.post("/login/start", async (c) => {
|
|
|
6580
6525
|
const authDir = join6(MAXY_DIR, "credentials", "whatsapp", accountId);
|
|
6581
6526
|
const accountDir = resolveAccount()?.accountDir ?? null;
|
|
6582
6527
|
const result = await startLogin({ accountId, authDir, phone, accountDir, force });
|
|
6583
|
-
console.error(`${
|
|
6528
|
+
console.error(`${TAG20} login/start result account=${accountId} hasCode=${!!result.pairingCode}${result.selfPhone ? ` phone=${result.selfPhone}` : ""}`);
|
|
6584
6529
|
return c.json(result);
|
|
6585
6530
|
} catch (err) {
|
|
6586
|
-
console.error(`${
|
|
6531
|
+
console.error(`${TAG20} login/start error: ${String(err)}`);
|
|
6587
6532
|
return c.json({ error: String(err) }, 500);
|
|
6588
6533
|
}
|
|
6589
6534
|
});
|
|
@@ -6593,7 +6538,7 @@ app3.post("/login/wait", async (c) => {
|
|
|
6593
6538
|
const accountId = validateAccountId(body.accountId);
|
|
6594
6539
|
const timeoutMs = body.timeoutMs ?? 6e4;
|
|
6595
6540
|
const result = await waitForLogin({ accountId, timeoutMs });
|
|
6596
|
-
console.error(`${
|
|
6541
|
+
console.error(`${TAG20} login/wait result account=${accountId} connected=${result.connected}${result.selfPhone ? ` phone=${result.selfPhone}` : ""} configPersisted=${result.configPersisted}`);
|
|
6597
6542
|
return c.json({
|
|
6598
6543
|
connected: result.connected,
|
|
6599
6544
|
message: result.message,
|
|
@@ -6601,7 +6546,7 @@ app3.post("/login/wait", async (c) => {
|
|
|
6601
6546
|
configPersisted: result.configPersisted
|
|
6602
6547
|
});
|
|
6603
6548
|
} catch (err) {
|
|
6604
|
-
console.error(`${
|
|
6549
|
+
console.error(`${TAG20} login/wait error: ${String(err)}`);
|
|
6605
6550
|
return c.json({ error: String(err) }, 500);
|
|
6606
6551
|
}
|
|
6607
6552
|
});
|
|
@@ -6612,7 +6557,7 @@ app3.post("/disconnect", async (c) => {
|
|
|
6612
6557
|
await stopConnection(accountId);
|
|
6613
6558
|
return c.json({ disconnected: true, accountId });
|
|
6614
6559
|
} catch (err) {
|
|
6615
|
-
console.error(`${
|
|
6560
|
+
console.error(`${TAG20} disconnect error: ${String(err)}`);
|
|
6616
6561
|
return c.json({ error: String(err) }, 500);
|
|
6617
6562
|
}
|
|
6618
6563
|
});
|
|
@@ -6623,7 +6568,7 @@ app3.post("/reconnect", async (c) => {
|
|
|
6623
6568
|
await startConnection(accountId);
|
|
6624
6569
|
return c.json({ reconnecting: true, accountId });
|
|
6625
6570
|
} catch (err) {
|
|
6626
|
-
console.error(`${
|
|
6571
|
+
console.error(`${TAG20} reconnect error: ${String(err)}`);
|
|
6627
6572
|
return c.json({ error: String(err) }, 500);
|
|
6628
6573
|
}
|
|
6629
6574
|
});
|
|
@@ -6642,7 +6587,7 @@ app3.post("/send", async (c) => {
|
|
|
6642
6587
|
const result = await sendTextMessage(sock, to, text, { accountId });
|
|
6643
6588
|
return c.json(result);
|
|
6644
6589
|
} catch (err) {
|
|
6645
|
-
console.error(`${
|
|
6590
|
+
console.error(`${TAG20} send error: ${String(err)}`);
|
|
6646
6591
|
return c.json({ error: String(err) }, 500);
|
|
6647
6592
|
}
|
|
6648
6593
|
});
|
|
@@ -6663,7 +6608,7 @@ app3.post("/config", async (c) => {
|
|
|
6663
6608
|
return c.json({ ok: false, error: 'Missing required field "phone" (E.164 format, e.g. +441234567890).' }, 400);
|
|
6664
6609
|
}
|
|
6665
6610
|
const result = addAdminPhone(account.accountDir, phone);
|
|
6666
|
-
console.error(`${
|
|
6611
|
+
console.error(`${TAG20} config action=add-admin-phone phone=${phone} ok=${result.ok}`);
|
|
6667
6612
|
return c.json(result, result.ok ? 200 : 400);
|
|
6668
6613
|
}
|
|
6669
6614
|
case "remove-admin-phone": {
|
|
@@ -6671,12 +6616,12 @@ app3.post("/config", async (c) => {
|
|
|
6671
6616
|
return c.json({ ok: false, error: 'Missing required field "phone".' }, 400);
|
|
6672
6617
|
}
|
|
6673
6618
|
const result = removeAdminPhone(account.accountDir, phone);
|
|
6674
|
-
console.error(`${
|
|
6619
|
+
console.error(`${TAG20} config action=remove-admin-phone phone=${phone} ok=${result.ok}`);
|
|
6675
6620
|
return c.json(result, result.ok ? 200 : 400);
|
|
6676
6621
|
}
|
|
6677
6622
|
case "list-admin-phones": {
|
|
6678
6623
|
const phones = readAdminPhones(account.accountDir);
|
|
6679
|
-
console.error(`${
|
|
6624
|
+
console.error(`${TAG20} config action=list-admin-phones count=${phones.length}`);
|
|
6680
6625
|
return c.json({ ok: true, phones });
|
|
6681
6626
|
}
|
|
6682
6627
|
case "set-public-agent": {
|
|
@@ -6684,14 +6629,14 @@ app3.post("/config", async (c) => {
|
|
|
6684
6629
|
return c.json({ ok: false, error: 'Missing required field "slug" (the agent directory name, e.g. "my-agent").' }, 400);
|
|
6685
6630
|
}
|
|
6686
6631
|
const result = setPublicAgent(account.accountDir, slug);
|
|
6687
|
-
console.error(`${
|
|
6632
|
+
console.error(`${TAG20} config action=set-public-agent slug=${slug} ok=${result.ok}`);
|
|
6688
6633
|
return c.json(result, result.ok ? 200 : 400);
|
|
6689
6634
|
}
|
|
6690
6635
|
case "get-public-agent": {
|
|
6691
6636
|
const targetAccount = typeof accountId === "string" && accountId.trim() ? accountId.trim() : "default";
|
|
6692
6637
|
const targetGroup = typeof groupJid === "string" && groupJid.trim() ? groupJid.trim() : void 0;
|
|
6693
6638
|
const resolved = resolvePublicAgent(account.accountDir, { accountId: targetAccount, groupJid: targetGroup });
|
|
6694
|
-
console.error(`${
|
|
6639
|
+
console.error(`${TAG20} config action=get-public-agent accountId=${targetAccount} groupJid=${targetGroup ?? "none"} slug=${resolved?.slug ?? "none"} source=${resolved?.source ?? "none"}`);
|
|
6695
6640
|
return c.json({ ok: true, slug: resolved?.slug ?? null, source: resolved?.source ?? null });
|
|
6696
6641
|
}
|
|
6697
6642
|
case "set-group-public-agent": {
|
|
@@ -6703,7 +6648,7 @@ app3.post("/config", async (c) => {
|
|
|
6703
6648
|
}
|
|
6704
6649
|
const targetAccount = typeof accountId === "string" && accountId.trim() ? accountId.trim() : "default";
|
|
6705
6650
|
const result = setGroupPublicAgent(account.accountDir, targetAccount, groupJid, slug);
|
|
6706
|
-
console.error(`${
|
|
6651
|
+
console.error(`${TAG20} config action=set-group-public-agent accountId=${targetAccount} groupJid=${groupJid} slug=${slug} ok=${result.ok}`);
|
|
6707
6652
|
return c.json(result, result.ok ? 200 : 400);
|
|
6708
6653
|
}
|
|
6709
6654
|
case "unset-group-public-agent": {
|
|
@@ -6712,7 +6657,7 @@ app3.post("/config", async (c) => {
|
|
|
6712
6657
|
}
|
|
6713
6658
|
const targetAccount = typeof accountId === "string" && accountId.trim() ? accountId.trim() : "default";
|
|
6714
6659
|
const result = unsetGroupPublicAgent(account.accountDir, targetAccount, groupJid);
|
|
6715
|
-
console.error(`${
|
|
6660
|
+
console.error(`${TAG20} config action=unset-group-public-agent accountId=${targetAccount} groupJid=${groupJid} ok=${result.ok}`);
|
|
6716
6661
|
return c.json(result, result.ok ? 200 : 400);
|
|
6717
6662
|
}
|
|
6718
6663
|
case "list-public-agents": {
|
|
@@ -6729,26 +6674,26 @@ app3.post("/config", async (c) => {
|
|
|
6729
6674
|
const config = JSON.parse(readFileSync6(configPath2, "utf-8"));
|
|
6730
6675
|
agents.push({ slug: entry.name, displayName: config.displayName ?? entry.name });
|
|
6731
6676
|
} catch {
|
|
6732
|
-
console.error(`${
|
|
6677
|
+
console.error(`${TAG20} config action=list-public-agents error="failed to parse config.json for agent ${entry.name}" \u2014 skipping`);
|
|
6733
6678
|
}
|
|
6734
6679
|
}
|
|
6735
6680
|
} catch (err) {
|
|
6736
|
-
console.error(`${
|
|
6681
|
+
console.error(`${TAG20} config action=list-public-agents error="failed to scan agents directory: ${String(err)}"`);
|
|
6737
6682
|
}
|
|
6738
6683
|
}
|
|
6739
|
-
console.error(`${
|
|
6684
|
+
console.error(`${TAG20} config action=list-public-agents count=${agents.length}`);
|
|
6740
6685
|
return c.json({ ok: true, agents });
|
|
6741
6686
|
}
|
|
6742
6687
|
case "schema": {
|
|
6743
6688
|
const text = serializeWhatsAppSchema();
|
|
6744
|
-
console.error(`${
|
|
6689
|
+
console.error(`${TAG20} config action=schema`);
|
|
6745
6690
|
return c.json({ ok: true, text });
|
|
6746
6691
|
}
|
|
6747
6692
|
case "list-groups": {
|
|
6748
6693
|
const groupAccountId = accountId ?? "default";
|
|
6749
6694
|
const sock = getSocket(groupAccountId);
|
|
6750
6695
|
if (!sock) {
|
|
6751
|
-
console.error(`${
|
|
6696
|
+
console.error(`${TAG20} config action=list-groups error="not connected" accountId=${groupAccountId}`);
|
|
6752
6697
|
return c.json({ ok: false, error: `WhatsApp account "${groupAccountId}" is not connected. Connect first, then retry.` });
|
|
6753
6698
|
}
|
|
6754
6699
|
try {
|
|
@@ -6758,10 +6703,10 @@ app3.post("/config", async (c) => {
|
|
|
6758
6703
|
name: g.subject ?? g.id,
|
|
6759
6704
|
participantCount: Array.isArray(g.participants) ? g.participants.length : 0
|
|
6760
6705
|
}));
|
|
6761
|
-
console.error(`${
|
|
6706
|
+
console.error(`${TAG20} config action=list-groups count=${groups.length} accountId=${groupAccountId}`);
|
|
6762
6707
|
return c.json({ ok: true, groups });
|
|
6763
6708
|
} catch (err) {
|
|
6764
|
-
console.error(`${
|
|
6709
|
+
console.error(`${TAG20} config action=list-groups error="${String(err)}" accountId=${groupAccountId}`);
|
|
6765
6710
|
return c.json({ ok: false, error: `Failed to fetch groups: ${String(err)}` });
|
|
6766
6711
|
}
|
|
6767
6712
|
}
|
|
@@ -6771,12 +6716,12 @@ app3.post("/config", async (c) => {
|
|
|
6771
6716
|
}
|
|
6772
6717
|
const result = updateConfig(account.accountDir, fields);
|
|
6773
6718
|
const fieldNames = Object.keys(fields);
|
|
6774
|
-
console.error(`${
|
|
6719
|
+
console.error(`${TAG20} config action=update-config fields=[${fieldNames.join(",")}] ok=${result.ok}`);
|
|
6775
6720
|
return c.json(result, result.ok ? 200 : 400);
|
|
6776
6721
|
}
|
|
6777
6722
|
case "get-config": {
|
|
6778
6723
|
const waConfig = getConfig(account.accountDir);
|
|
6779
|
-
console.error(`${
|
|
6724
|
+
console.error(`${TAG20} config action=get-config`);
|
|
6780
6725
|
return c.json({ ok: true, config: waConfig });
|
|
6781
6726
|
}
|
|
6782
6727
|
default:
|
|
@@ -6786,7 +6731,7 @@ app3.post("/config", async (c) => {
|
|
|
6786
6731
|
);
|
|
6787
6732
|
}
|
|
6788
6733
|
} catch (err) {
|
|
6789
|
-
console.error(`${
|
|
6734
|
+
console.error(`${TAG20} config error: ${String(err)}`);
|
|
6790
6735
|
return c.json({ ok: false, error: String(err) }, 500);
|
|
6791
6736
|
}
|
|
6792
6737
|
});
|
|
@@ -6807,7 +6752,7 @@ app3.post("/send-document", async (c) => {
|
|
|
6807
6752
|
recordRouteDocumentOutbound(to, filePath);
|
|
6808
6753
|
return c.json({ success: true, messageId: result.messageId });
|
|
6809
6754
|
} catch (err) {
|
|
6810
|
-
console.error(`${
|
|
6755
|
+
console.error(`${TAG20} send-document error: ${String(err)}`);
|
|
6811
6756
|
return c.json({ error: String(err) }, 500);
|
|
6812
6757
|
}
|
|
6813
6758
|
});
|
|
@@ -6817,11 +6762,11 @@ app3.get("/activity", (c) => {
|
|
|
6817
6762
|
const result = getChannelActivity(accountId);
|
|
6818
6763
|
const total = result.accounts.reduce((sum, a) => sum + a.total, 0);
|
|
6819
6764
|
console.error(
|
|
6820
|
-
`${
|
|
6765
|
+
`${TAG20} activity accounts=${result.accounts.length} total=${total} recentEvents=${result.recentEvents.length}` + (accountId ? ` filter=${accountId}` : "")
|
|
6821
6766
|
);
|
|
6822
6767
|
return c.json(result);
|
|
6823
6768
|
} catch (err) {
|
|
6824
|
-
console.error(`${
|
|
6769
|
+
console.error(`${TAG20} activity error: ${String(err)}`);
|
|
6825
6770
|
return c.json({ error: String(err) }, 500);
|
|
6826
6771
|
}
|
|
6827
6772
|
});
|
|
@@ -6840,10 +6785,10 @@ app3.get("/conversations", (c) => {
|
|
|
6840
6785
|
};
|
|
6841
6786
|
});
|
|
6842
6787
|
conversations.sort((a, b) => (b.lastMessageTimestamp ?? 0) - (a.lastMessageTimestamp ?? 0));
|
|
6843
|
-
console.error(`${
|
|
6788
|
+
console.error(`${TAG20} conversations account=${accountId} count=${conversations.length}`);
|
|
6844
6789
|
return c.json({ conversations });
|
|
6845
6790
|
} catch (err) {
|
|
6846
|
-
console.error(`${
|
|
6791
|
+
console.error(`${TAG20} conversations error: ${String(err)}`);
|
|
6847
6792
|
return c.json({ error: String(err) }, 500);
|
|
6848
6793
|
}
|
|
6849
6794
|
});
|
|
@@ -6858,10 +6803,10 @@ app3.get("/messages", (c) => {
|
|
|
6858
6803
|
const limit = limitParam ? parseInt(limitParam, 10) : void 0;
|
|
6859
6804
|
const effectiveLimit = limit && !Number.isNaN(limit) && limit > 0 ? limit : void 0;
|
|
6860
6805
|
const messages = getMessages(accountId, jid, effectiveLimit);
|
|
6861
|
-
console.error(`${
|
|
6806
|
+
console.error(`${TAG20} messages account=${accountId} jid=${jid} limit=${effectiveLimit ?? "all"} returned=${messages.length}`);
|
|
6862
6807
|
return c.json({ messages });
|
|
6863
6808
|
} catch (err) {
|
|
6864
|
-
console.error(`${
|
|
6809
|
+
console.error(`${TAG20} messages error: ${String(err)}`);
|
|
6865
6810
|
return c.json({ error: String(err) }, 500);
|
|
6866
6811
|
}
|
|
6867
6812
|
});
|
|
@@ -6942,7 +6887,7 @@ app3.get("/conversation-graph-state", async (c) => {
|
|
|
6942
6887
|
}
|
|
6943
6888
|
} catch (err) {
|
|
6944
6889
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6945
|
-
console.error(`${
|
|
6890
|
+
console.error(`${TAG20} conversation-graph-state ERR cacheKey=${cacheKey} reason=${msg}`);
|
|
6946
6891
|
return c.json({ error: `Graph query failed: ${msg}`, cacheKey, cypher: cypher.trim() }, 500);
|
|
6947
6892
|
}
|
|
6948
6893
|
const ms = Date.now() - t0;
|
|
@@ -6955,7 +6900,7 @@ app3.get("/conversation-graph-state", async (c) => {
|
|
|
6955
6900
|
ms
|
|
6956
6901
|
});
|
|
6957
6902
|
} catch (err) {
|
|
6958
|
-
console.error(`${
|
|
6903
|
+
console.error(`${TAG20} conversation-graph-state error: ${String(err)}`);
|
|
6959
6904
|
return c.json({ error: String(err) }, 500);
|
|
6960
6905
|
}
|
|
6961
6906
|
});
|
|
@@ -6967,12 +6912,12 @@ app3.get("/group-info", async (c) => {
|
|
|
6967
6912
|
return c.json({ error: "Missing required parameter: jid" }, 400);
|
|
6968
6913
|
}
|
|
6969
6914
|
if (!isGroupJid(jid)) {
|
|
6970
|
-
console.error(`${
|
|
6915
|
+
console.error(`${TAG20} group-info error="not a group JID" jid=${jid} account=${accountId}`);
|
|
6971
6916
|
return c.json({ error: `"${jid}" is not a group JID. Group JIDs end with @g.us.` }, 400);
|
|
6972
6917
|
}
|
|
6973
6918
|
const sock = getSocket(accountId);
|
|
6974
6919
|
if (!sock) {
|
|
6975
|
-
console.error(`${
|
|
6920
|
+
console.error(`${TAG20} group-info error="not connected" account=${accountId}`);
|
|
6976
6921
|
return c.json({ error: `WhatsApp account "${accountId}" is not connected. Connect first, then retry.` }, 400);
|
|
6977
6922
|
}
|
|
6978
6923
|
const meta = await sock.groupMetadata(jid);
|
|
@@ -6985,10 +6930,10 @@ app3.get("/group-info", async (c) => {
|
|
|
6985
6930
|
participantCount: meta.participants.length,
|
|
6986
6931
|
participants: meta.participants.map((p) => ({ jid: p.id, admin: p.admin ?? null }))
|
|
6987
6932
|
};
|
|
6988
|
-
console.error(`${
|
|
6933
|
+
console.error(`${TAG20} group-info jid=${jid} subject="${meta.subject}" participants=${meta.participants.length} account=${accountId}`);
|
|
6989
6934
|
return c.json(result);
|
|
6990
6935
|
} catch (err) {
|
|
6991
|
-
console.error(`${
|
|
6936
|
+
console.error(`${TAG20} group-info error="${String(err)}" jid=${jid} account=${accountId}`);
|
|
6992
6937
|
return c.json({ error: `Failed to fetch group info: ${String(err)}` }, 500);
|
|
6993
6938
|
}
|
|
6994
6939
|
});
|
|
@@ -8449,11 +8394,11 @@ app11.delete("/:id", requireAdminSession, async (c) => {
|
|
|
8449
8394
|
const owned = await verifyConversationOwnership(sessionId, accountId);
|
|
8450
8395
|
if (!owned) return c.json({ error: "Conversation not found" }, 404);
|
|
8451
8396
|
const managerPort = requirePortEnv("CLAUDE_SESSION_MANAGER_PORT", { tag: "admin-conversation-delete" });
|
|
8452
|
-
const
|
|
8397
|
+
const managerBase5 = `http://127.0.0.1:${managerPort}`;
|
|
8453
8398
|
const outcome = await cascadeAdminConversationDelete({
|
|
8454
8399
|
sessionId,
|
|
8455
8400
|
accountId,
|
|
8456
|
-
managerBase:
|
|
8401
|
+
managerBase: managerBase5
|
|
8457
8402
|
});
|
|
8458
8403
|
if (outcome.ok) return c.json({ ok: true, claudeSessionIds: outcome.claudeSessionIds });
|
|
8459
8404
|
if (outcome.reason === "pty-still-alive") {
|
|
@@ -9095,7 +9040,7 @@ function resolveTunnelUrl() {
|
|
|
9095
9040
|
if (!state) return null;
|
|
9096
9041
|
return `https://${hostname2}.${state.domain}`;
|
|
9097
9042
|
}
|
|
9098
|
-
var
|
|
9043
|
+
var TAG21 = "[claude-session-manager:wrapper]";
|
|
9099
9044
|
async function refuseIfClaudeAuthDead(c, route, sessionId) {
|
|
9100
9045
|
const auth = await ensureAuth();
|
|
9101
9046
|
if (auth.status !== "dead" && auth.status !== "missing") return null;
|
|
@@ -9117,12 +9062,12 @@ async function performSpawnWithInitialMessage(args) {
|
|
|
9117
9062
|
const aboutOwner = await resolveOwnerProfileBlock(args.senderId, args.userId);
|
|
9118
9063
|
const ownerMs = Date.now() - ownerStart;
|
|
9119
9064
|
const aboutOwnerStatus = aboutOwner == null ? "absent" : "ok" in aboutOwner && aboutOwner.ok === false ? `unresolved:${aboutOwner.reason}` : "ok";
|
|
9120
|
-
console.log(`${
|
|
9065
|
+
console.log(`${TAG21} about-owner-resolved status=${aboutOwnerStatus} ms=${ownerMs}`);
|
|
9121
9066
|
const dormantPlugins = computeDormantPlugins(args.senderId);
|
|
9122
9067
|
const activePlugins = computeActivePlugins(args.senderId);
|
|
9123
9068
|
const specialistDomains = computeSpecialistDomains(args.senderId);
|
|
9124
9069
|
const tunnelUrl = resolveTunnelUrl();
|
|
9125
|
-
console.log(`${
|
|
9070
|
+
console.log(`${TAG21} tunnel-url-resolved value=${tunnelUrl ?? "null"}`);
|
|
9126
9071
|
const upstreamPayload = JSON.stringify({
|
|
9127
9072
|
senderId: args.senderId,
|
|
9128
9073
|
// Task 205 — pass userId through to the manager so it lands as
|
|
@@ -9149,24 +9094,24 @@ async function performSpawnWithInitialMessage(args) {
|
|
|
9149
9094
|
// unshapely values.
|
|
9150
9095
|
conversationNodeId: args.conversationNodeId
|
|
9151
9096
|
});
|
|
9152
|
-
console.log(`${
|
|
9097
|
+
console.log(`${TAG21} forward-spawn-start managerBase=${managerBase3()} bytes=${upstreamPayload.length} hidden=${args.hidden} specialist=${args.specialist ?? "none"}`);
|
|
9153
9098
|
const forwardStart = Date.now();
|
|
9154
9099
|
const upstream = await fetch(`${managerBase3()}/public-spawn`, {
|
|
9155
9100
|
method: "POST",
|
|
9156
9101
|
headers: { "content-type": "application/json" },
|
|
9157
9102
|
body: upstreamPayload
|
|
9158
9103
|
}).catch((err) => {
|
|
9159
|
-
console.error(`${
|
|
9104
|
+
console.error(`${TAG21} fetch-failed op=spawn message=${err instanceof Error ? err.message : String(err)} ms=${Date.now() - forwardStart}`);
|
|
9160
9105
|
return null;
|
|
9161
9106
|
});
|
|
9162
9107
|
if (!upstream) return {
|
|
9163
9108
|
response: new Response(JSON.stringify({ error: "manager-unreachable" }), { status: 503, headers: { "content-type": "application/json" } }),
|
|
9164
9109
|
claudeSessionId: null
|
|
9165
9110
|
};
|
|
9166
|
-
console.log(`${
|
|
9111
|
+
console.log(`${TAG21} forward-spawn-done status=${upstream.status} ms=${Date.now() - forwardStart}`);
|
|
9167
9112
|
if (args.initialMessage) {
|
|
9168
9113
|
const inputBytes = Buffer.byteLength(args.initialMessage, "utf8");
|
|
9169
|
-
console.log(`${
|
|
9114
|
+
console.log(`${TAG21} initial-message-inlined bytes=${inputBytes}`);
|
|
9170
9115
|
}
|
|
9171
9116
|
const bodyText = await upstream.text().catch(() => "");
|
|
9172
9117
|
let claudeSessionId = null;
|
|
@@ -9201,7 +9146,7 @@ app12.post("/", async (c) => {
|
|
|
9201
9146
|
if (refusal) return refusal;
|
|
9202
9147
|
const senderId = getAccountIdForSession(cacheKey) ?? "";
|
|
9203
9148
|
if (!senderId) {
|
|
9204
|
-
console.error(`${
|
|
9149
|
+
console.error(`${TAG21} reject reason=no-account-id cacheKey-prefix=${cacheKey.slice(0, 8)}`);
|
|
9205
9150
|
return c.json({ error: "admin-account-not-resolved" }, 500);
|
|
9206
9151
|
}
|
|
9207
9152
|
const userId = getUserIdForSession(cacheKey) ?? void 0;
|
|
@@ -9210,7 +9155,7 @@ app12.post("/", async (c) => {
|
|
|
9210
9155
|
const permissionMode = typeof body.permissionMode === "string" ? body.permissionMode : void 0;
|
|
9211
9156
|
const specialist = typeof body.specialist === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(body.specialist) ? body.specialist : void 0;
|
|
9212
9157
|
const model = typeof body.model === "string" && /^[A-Za-z0-9._-]{1,64}$/.test(body.model) ? body.model : void 0;
|
|
9213
|
-
console.log(`${
|
|
9158
|
+
console.log(`${TAG21} spawn-request-in surface=cookie accountId=${senderId.slice(0, 8)} userId=${userId ? userId.slice(0, 8) : "absent"} channel=${channel} permissionMode=${permissionMode ?? "default"} specialist=${specialist ?? "none"} model=${model ?? "default"} initialMessage=${initialMessage ? "yes" : "no"}`);
|
|
9214
9159
|
const conversationNodeId = cacheKey ? getSessionIdForSession(cacheKey) : void 0;
|
|
9215
9160
|
const { response, claudeSessionId } = await performSpawnWithInitialMessage({
|
|
9216
9161
|
senderId,
|
|
@@ -9229,13 +9174,13 @@ app12.post("/", async (c) => {
|
|
|
9229
9174
|
claudeSessionId,
|
|
9230
9175
|
senderId
|
|
9231
9176
|
);
|
|
9232
|
-
console.log(`${
|
|
9177
|
+
console.log(`${TAG21} route-done surface=cookie status=${response.status} route-ms=${Date.now() - routeStart}`);
|
|
9233
9178
|
return response;
|
|
9234
9179
|
});
|
|
9235
9180
|
var claude_sessions_default = app12;
|
|
9236
9181
|
|
|
9237
9182
|
// server/routes/admin/log-ingest.ts
|
|
9238
|
-
var
|
|
9183
|
+
var TAG22 = "[log-ingest]";
|
|
9239
9184
|
var TAG_PATTERN = /^[A-Za-z0-9_:-]{1,32}$/;
|
|
9240
9185
|
var LEVELS = /* @__PURE__ */ new Set(["debug", "info", "warn", "error"]);
|
|
9241
9186
|
var MAX_LINE_BYTES = 4096;
|
|
@@ -9246,7 +9191,7 @@ function isLoopbackAddr(addr) {
|
|
|
9246
9191
|
app13.post("/", async (c) => {
|
|
9247
9192
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
9248
9193
|
if (!isLoopbackAddr(remoteAddr)) {
|
|
9249
|
-
console.error(`${
|
|
9194
|
+
console.error(`${TAG22} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
9250
9195
|
return c.json({ error: "log-ingest-loopback-only" }, 403);
|
|
9251
9196
|
}
|
|
9252
9197
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -9255,7 +9200,7 @@ app13.post("/", async (c) => {
|
|
|
9255
9200
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
9256
9201
|
const offender = tokens.find((t) => !isLoopbackAddr(t));
|
|
9257
9202
|
if (offender !== void 0) {
|
|
9258
|
-
console.error(`${
|
|
9203
|
+
console.error(`${TAG22} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
9259
9204
|
return c.json({ error: "log-ingest-loopback-only" }, 403);
|
|
9260
9205
|
}
|
|
9261
9206
|
}
|
|
@@ -9297,18 +9242,18 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
|
9297
9242
|
]);
|
|
9298
9243
|
var app14 = new Hono();
|
|
9299
9244
|
app14.post("/", async (c) => {
|
|
9300
|
-
const
|
|
9245
|
+
const TAG30 = "[admin:events]";
|
|
9301
9246
|
let body;
|
|
9302
9247
|
try {
|
|
9303
9248
|
body = await c.req.json();
|
|
9304
9249
|
} catch (err) {
|
|
9305
9250
|
const detail = err instanceof Error ? err.message : String(err);
|
|
9306
|
-
console.error(`${
|
|
9251
|
+
console.error(`${TAG30} reject reason=body-not-json detail=${detail}`);
|
|
9307
9252
|
return c.json({ ok: false, detail: "Request body was not valid JSON" }, 400);
|
|
9308
9253
|
}
|
|
9309
9254
|
const event = typeof body.event === "string" ? body.event : "";
|
|
9310
9255
|
if (!ALLOWED_EVENTS.has(event)) {
|
|
9311
|
-
console.error(`${
|
|
9256
|
+
console.error(`${TAG30} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
|
|
9312
9257
|
return c.json({ ok: false, detail: `Event "${event}" is not allowed` }, 400);
|
|
9313
9258
|
}
|
|
9314
9259
|
const rawFields = body.fields && typeof body.fields === "object" ? body.fields : {};
|
|
@@ -12121,7 +12066,7 @@ app18.post("/", requireAdminSession, async (c) => {
|
|
|
12121
12066
|
return c.json({ error: "AdminConversation node is missing sessionId" }, 500);
|
|
12122
12067
|
}
|
|
12123
12068
|
const managerPort = requirePortEnv("CLAUDE_SESSION_MANAGER_PORT", { tag: "graph-page-cascade" });
|
|
12124
|
-
const
|
|
12069
|
+
const managerBase5 = `http://127.0.0.1:${managerPort}`;
|
|
12125
12070
|
try {
|
|
12126
12071
|
await session.close();
|
|
12127
12072
|
} catch {
|
|
@@ -12129,7 +12074,7 @@ app18.post("/", requireAdminSession, async (c) => {
|
|
|
12129
12074
|
const outcome = await cascadeAdminConversationDelete({
|
|
12130
12075
|
sessionId,
|
|
12131
12076
|
accountId,
|
|
12132
|
-
managerBase:
|
|
12077
|
+
managerBase: managerBase5
|
|
12133
12078
|
});
|
|
12134
12079
|
const elapsed2 = Date.now() - started;
|
|
12135
12080
|
const labelSummary2 = preflightLabels.join(",");
|
|
@@ -13345,7 +13290,7 @@ var health_default2 = app27;
|
|
|
13345
13290
|
|
|
13346
13291
|
// server/routes/admin/linkedin-ingest.ts
|
|
13347
13292
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
13348
|
-
var
|
|
13293
|
+
var TAG23 = "[linkedin-ingest-route]";
|
|
13349
13294
|
var UUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
13350
13295
|
var ISO = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
13351
13296
|
var LINKEDIN_URL = /^https:\/\/www\.linkedin\.com\//;
|
|
@@ -13449,29 +13394,29 @@ app28.post("/", requireAdminSession, async (c) => {
|
|
|
13449
13394
|
try {
|
|
13450
13395
|
body = await c.req.json();
|
|
13451
13396
|
} catch {
|
|
13452
|
-
console.error(
|
|
13397
|
+
console.error(TAG23 + " rejected status=400 reason=schema:body-not-json");
|
|
13453
13398
|
return c.json({ ok: false, error: "schema", reason: "body-not-json" }, 400);
|
|
13454
13399
|
}
|
|
13455
13400
|
const v = validate(body);
|
|
13456
13401
|
if (!v.ok) {
|
|
13457
|
-
console.error(
|
|
13402
|
+
console.error(TAG23 + " rejected status=" + v.status + " reason=" + v.reason + " missing=" + v.missing.join(","));
|
|
13458
13403
|
return c.json({ ok: false, error: v.error, reason: v.reason, missing: v.missing }, v.status);
|
|
13459
13404
|
}
|
|
13460
13405
|
const envelope = v.envelope;
|
|
13461
13406
|
const cacheKey = c.var.cacheKey ?? "";
|
|
13462
13407
|
const senderId = getAccountIdForSession(cacheKey) ?? "";
|
|
13463
13408
|
if (!senderId) {
|
|
13464
|
-
console.error(
|
|
13409
|
+
console.error(TAG23 + " rejected status=500 reason=admin-account-not-resolved");
|
|
13465
13410
|
return c.json({ ok: false, error: "admin-account-not-resolved" }, 500);
|
|
13466
13411
|
}
|
|
13467
13412
|
const payloadBytes = JSON.stringify(envelope).length;
|
|
13468
13413
|
console.log(
|
|
13469
|
-
|
|
13414
|
+
TAG23 + " received kind=" + envelope.kind + " account=" + senderId.slice(0, 8) + " pageUrl=" + envelope.pageUrl + " dispatchId=" + envelope.dispatchId + " payloadBytes=" + payloadBytes
|
|
13470
13415
|
);
|
|
13471
13416
|
const initialMessage = buildInitialMessage(envelope);
|
|
13472
13417
|
const spawnStart = Date.now();
|
|
13473
13418
|
const sessionId = randomUUID9();
|
|
13474
|
-
console.log(
|
|
13419
|
+
console.log(TAG23 + " route target=rc-spawn dispatchId=" + envelope.dispatchId + " sessionId=" + sessionId.slice(0, 8));
|
|
13475
13420
|
const spawned = await managerRcSpawn({
|
|
13476
13421
|
sessionId,
|
|
13477
13422
|
initialMessage,
|
|
@@ -13480,12 +13425,12 @@ app28.post("/", requireAdminSession, async (c) => {
|
|
|
13480
13425
|
});
|
|
13481
13426
|
if ("error" in spawned) {
|
|
13482
13427
|
console.error(
|
|
13483
|
-
|
|
13428
|
+
TAG23 + " dispatch-failed dispatchId=" + envelope.dispatchId + " status=" + spawned.status + " ms=" + (Date.now() - spawnStart) + " message=" + spawned.error
|
|
13484
13429
|
);
|
|
13485
13430
|
return c.json({ ok: false, error: "dispatch-failed", upstreamStatus: spawned.status, detail: spawned.error }, 502);
|
|
13486
13431
|
}
|
|
13487
13432
|
console.log(
|
|
13488
|
-
|
|
13433
|
+
TAG23 + " dispatched dispatchId=" + envelope.dispatchId + " taskId=" + spawned.sessionId + " ms=" + (Date.now() - spawnStart)
|
|
13489
13434
|
);
|
|
13490
13435
|
return c.json({ ok: true, dispatchId: envelope.dispatchId, taskId: spawned.sessionId }, 202);
|
|
13491
13436
|
});
|
|
@@ -13493,7 +13438,7 @@ var linkedin_ingest_default = app28;
|
|
|
13493
13438
|
|
|
13494
13439
|
// server/routes/admin/post-turn-context.ts
|
|
13495
13440
|
import neo4j2 from "neo4j-driver";
|
|
13496
|
-
var
|
|
13441
|
+
var TAG24 = "[post-turn-context]";
|
|
13497
13442
|
var STRIPPED_PROPERTIES2 = /* @__PURE__ */ new Set([
|
|
13498
13443
|
"embedding",
|
|
13499
13444
|
"passwordHash",
|
|
@@ -13535,7 +13480,7 @@ var app29 = new Hono();
|
|
|
13535
13480
|
app29.get("/", async (c) => {
|
|
13536
13481
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
13537
13482
|
if (!isLoopbackAddr2(remoteAddr)) {
|
|
13538
|
-
console.error(`${
|
|
13483
|
+
console.error(`${TAG24} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
13539
13484
|
return c.json({ error: "post-turn-context-loopback-only" }, 403);
|
|
13540
13485
|
}
|
|
13541
13486
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -13544,7 +13489,7 @@ app29.get("/", async (c) => {
|
|
|
13544
13489
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
13545
13490
|
const offender = tokens.find((t) => !isLoopbackAddr2(t));
|
|
13546
13491
|
if (offender !== void 0) {
|
|
13547
|
-
console.error(`${
|
|
13492
|
+
console.error(`${TAG24} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
13548
13493
|
return c.json({ error: "post-turn-context-loopback-only" }, 403);
|
|
13549
13494
|
}
|
|
13550
13495
|
}
|
|
@@ -13576,7 +13521,7 @@ app29.get("/", async (c) => {
|
|
|
13576
13521
|
writes.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
|
|
13577
13522
|
const total = Date.now() - started;
|
|
13578
13523
|
console.log(
|
|
13579
|
-
`${
|
|
13524
|
+
`${TAG24} sessionId=${sessionId} accountId=${accountId} writes=${writes.length} ms=${total}`
|
|
13580
13525
|
);
|
|
13581
13526
|
return c.json({
|
|
13582
13527
|
writes: writes.map(({ elementId, labels, properties }) => ({ elementId, labels, properties }))
|
|
@@ -13585,7 +13530,7 @@ app29.get("/", async (c) => {
|
|
|
13585
13530
|
const elapsed = Date.now() - started;
|
|
13586
13531
|
const message = err instanceof Error ? err.message : String(err);
|
|
13587
13532
|
console.error(
|
|
13588
|
-
`${
|
|
13533
|
+
`${TAG24} neo4j-unreachable sessionId=${sessionId} ms=${elapsed} err="${message}"`
|
|
13589
13534
|
);
|
|
13590
13535
|
return c.json({ error: `post-turn-context unavailable: ${message}` }, 503);
|
|
13591
13536
|
} finally {
|
|
@@ -13596,7 +13541,7 @@ var post_turn_context_default = app29;
|
|
|
13596
13541
|
|
|
13597
13542
|
// server/routes/admin/public-session-context.ts
|
|
13598
13543
|
import neo4j3 from "neo4j-driver";
|
|
13599
|
-
var
|
|
13544
|
+
var TAG25 = "[public-session-context]";
|
|
13600
13545
|
var STRIPPED_PROPERTIES3 = /* @__PURE__ */ new Set([
|
|
13601
13546
|
"embedding",
|
|
13602
13547
|
"passwordHash",
|
|
@@ -13638,7 +13583,7 @@ var app30 = new Hono();
|
|
|
13638
13583
|
app30.get("/", async (c) => {
|
|
13639
13584
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
13640
13585
|
if (!isLoopbackAddr3(remoteAddr)) {
|
|
13641
|
-
console.error(`${
|
|
13586
|
+
console.error(`${TAG25} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
13642
13587
|
return c.json({ error: "public-session-context-loopback-only" }, 403);
|
|
13643
13588
|
}
|
|
13644
13589
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -13647,7 +13592,7 @@ app30.get("/", async (c) => {
|
|
|
13647
13592
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
13648
13593
|
const offender = tokens.find((t) => !isLoopbackAddr3(t));
|
|
13649
13594
|
if (offender !== void 0) {
|
|
13650
|
-
console.error(`${
|
|
13595
|
+
console.error(`${TAG25} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
13651
13596
|
return c.json({ error: "public-session-context-loopback-only" }, 403);
|
|
13652
13597
|
}
|
|
13653
13598
|
}
|
|
@@ -13678,7 +13623,7 @@ app30.get("/", async (c) => {
|
|
|
13678
13623
|
writes.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
|
|
13679
13624
|
const total = Date.now() - started;
|
|
13680
13625
|
console.log(
|
|
13681
|
-
`${
|
|
13626
|
+
`${TAG25} sliceToken=${sliceToken.slice(0, 8)} writes=${writes.length} ms=${total}`
|
|
13682
13627
|
);
|
|
13683
13628
|
return c.json({
|
|
13684
13629
|
writes: writes.map(({ elementId, labels, properties }) => ({ elementId, labels, properties }))
|
|
@@ -13687,7 +13632,7 @@ app30.get("/", async (c) => {
|
|
|
13687
13632
|
const elapsed = Date.now() - started;
|
|
13688
13633
|
const message = err instanceof Error ? err.message : String(err);
|
|
13689
13634
|
console.error(
|
|
13690
|
-
`${
|
|
13635
|
+
`${TAG25} neo4j-unreachable sliceToken=${sliceToken.slice(0, 8)} ms=${elapsed} err="${message}"`
|
|
13691
13636
|
);
|
|
13692
13637
|
return c.json({ error: `public-session-context unavailable: ${message}` }, 503);
|
|
13693
13638
|
} finally {
|
|
@@ -13697,7 +13642,7 @@ app30.get("/", async (c) => {
|
|
|
13697
13642
|
var public_session_context_default = app30;
|
|
13698
13643
|
|
|
13699
13644
|
// server/routes/admin/public-session-exit.ts
|
|
13700
|
-
var
|
|
13645
|
+
var TAG26 = "[public-session-exit-route]";
|
|
13701
13646
|
function isLoopbackAddr4(addr) {
|
|
13702
13647
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
13703
13648
|
}
|
|
@@ -13705,7 +13650,7 @@ var app31 = new Hono();
|
|
|
13705
13650
|
app31.post("/", async (c) => {
|
|
13706
13651
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
13707
13652
|
if (!isLoopbackAddr4(remoteAddr)) {
|
|
13708
|
-
console.error(`${
|
|
13653
|
+
console.error(`${TAG26} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
13709
13654
|
return c.json({ error: "public-session-exit-loopback-only" }, 403);
|
|
13710
13655
|
}
|
|
13711
13656
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -13714,7 +13659,7 @@ app31.post("/", async (c) => {
|
|
|
13714
13659
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
13715
13660
|
const offender = tokens.find((t) => !isLoopbackAddr4(t));
|
|
13716
13661
|
if (offender !== void 0) {
|
|
13717
|
-
console.error(`${
|
|
13662
|
+
console.error(`${TAG26} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
13718
13663
|
return c.json({ error: "public-session-exit-loopback-only" }, 403);
|
|
13719
13664
|
}
|
|
13720
13665
|
}
|
|
@@ -13732,7 +13677,7 @@ app31.post("/", async (c) => {
|
|
|
13732
13677
|
var public_session_exit_default = app31;
|
|
13733
13678
|
|
|
13734
13679
|
// server/routes/admin/access-session-evict.ts
|
|
13735
|
-
var
|
|
13680
|
+
var TAG27 = "[access-session-evict]";
|
|
13736
13681
|
function isLoopbackAddr5(addr) {
|
|
13737
13682
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
13738
13683
|
}
|
|
@@ -13740,7 +13685,7 @@ var app32 = new Hono();
|
|
|
13740
13685
|
app32.post("/", async (c) => {
|
|
13741
13686
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
13742
13687
|
if (!isLoopbackAddr5(remoteAddr)) {
|
|
13743
|
-
console.error(`${
|
|
13688
|
+
console.error(`${TAG27} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
13744
13689
|
return c.json({ error: "access-session-evict-loopback-only" }, 403);
|
|
13745
13690
|
}
|
|
13746
13691
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -13749,7 +13694,7 @@ app32.post("/", async (c) => {
|
|
|
13749
13694
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
13750
13695
|
const offender = tokens.find((t) => !isLoopbackAddr5(t));
|
|
13751
13696
|
if (offender !== void 0) {
|
|
13752
|
-
console.error(`${
|
|
13697
|
+
console.error(`${TAG27} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
13753
13698
|
return c.json({ error: "access-session-evict-loopback-only" }, 403);
|
|
13754
13699
|
}
|
|
13755
13700
|
}
|
|
@@ -13762,66 +13707,14 @@ app32.post("/", async (c) => {
|
|
|
13762
13707
|
const grantId = typeof body.grantId === "string" ? body.grantId.trim() : "";
|
|
13763
13708
|
if (!grantId) return c.json({ error: "grantId required" }, 400);
|
|
13764
13709
|
const dropped = evictAccessSessionsByGrant(grantId);
|
|
13765
|
-
console.log(`${
|
|
13710
|
+
console.log(`${TAG27} grantId=${grantId} dropped=${dropped}`);
|
|
13766
13711
|
return c.json({ ok: true, dropped });
|
|
13767
13712
|
});
|
|
13768
13713
|
var access_session_evict_default = app32;
|
|
13769
13714
|
|
|
13770
|
-
// server/routes/admin/identity.ts
|
|
13771
|
-
var import_dist4 = __toESM(require_dist3(), 1);
|
|
13772
|
-
var app33 = new Hono();
|
|
13773
|
-
var TAG29 = "[admin-identity]";
|
|
13774
|
-
function managerBase5() {
|
|
13775
|
-
const port2 = (0, import_dist4.requirePortEnv)("CLAUDE_SESSION_MANAGER_PORT", { tag: "admin-identity" });
|
|
13776
|
-
return `http://127.0.0.1:${port2}`;
|
|
13777
|
-
}
|
|
13778
|
-
app33.post("/validate", async (c) => {
|
|
13779
|
-
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
13780
|
-
const isLoopback = remoteAddr === "127.0.0.1" || remoteAddr === "::1" || remoteAddr === "::ffff:127.0.0.1";
|
|
13781
|
-
if (!isLoopback || c.req.header("x-forwarded-for")) {
|
|
13782
|
-
return c.json({ error: "forbidden" }, 403);
|
|
13783
|
-
}
|
|
13784
|
-
let body;
|
|
13785
|
-
try {
|
|
13786
|
-
body = await c.req.json();
|
|
13787
|
-
} catch {
|
|
13788
|
-
return c.json({ error: "bad-request" }, 400);
|
|
13789
|
-
}
|
|
13790
|
-
const pin = typeof body.pin === "string" ? body.pin : "";
|
|
13791
|
-
const sessionId = typeof body.sessionId === "string" ? body.sessionId : void 0;
|
|
13792
|
-
if (!pin) return c.json({ error: "bad-request" }, 400);
|
|
13793
|
-
const fireStop = () => {
|
|
13794
|
-
if (sessionId) {
|
|
13795
|
-
void fetch(`${managerBase5()}/${encodeURIComponent(sessionId)}/stop`, { method: "POST" }).catch(
|
|
13796
|
-
() => {
|
|
13797
|
-
}
|
|
13798
|
-
);
|
|
13799
|
-
}
|
|
13800
|
-
};
|
|
13801
|
-
const verdict = validatePin(pin, USERS_FILE);
|
|
13802
|
-
if (verdict.kind !== "match") {
|
|
13803
|
-
if (verdict.kind === "miss") fireStop();
|
|
13804
|
-
console.log(`${TAG29} op=endpoint-validate result=${verdict.kind}${sessionId ? ` sessionId=${sessionId.slice(0, 8)}` : ""}`);
|
|
13805
|
-
return c.json({ kind: verdict.kind });
|
|
13806
|
-
}
|
|
13807
|
-
const { userId } = verdict;
|
|
13808
|
-
const accounts = resolveUserAccounts(userId);
|
|
13809
|
-
if (accounts.length === 0) {
|
|
13810
|
-
fireStop();
|
|
13811
|
-
console.log(`${TAG29} op=endpoint-validate result=no-account userId=${userId.slice(0, 8)}`);
|
|
13812
|
-
return c.json({ kind: "miss" });
|
|
13813
|
-
}
|
|
13814
|
-
const accountId = accounts[0].accountId;
|
|
13815
|
-
const { userName } = await resolveUserIdentity(accountId, userId);
|
|
13816
|
-
const aboutOwner = await resolveOwnerProfileBlock(accountId, userId);
|
|
13817
|
-
console.log(`${TAG29} op=endpoint-validate result=match userId=${userId.slice(0, 8)} aboutOwner=${aboutOwner.ok ? "ok" : `unresolved:${aboutOwner.reason}`}`);
|
|
13818
|
-
return c.json({ kind: "match", userId, userName, aboutOwner });
|
|
13819
|
-
});
|
|
13820
|
-
var identity_default = app33;
|
|
13821
|
-
|
|
13822
13715
|
// server/routes/admin/browser.ts
|
|
13823
|
-
var
|
|
13824
|
-
|
|
13716
|
+
var app33 = new Hono();
|
|
13717
|
+
app33.post("/launch", requireAdminSession, async (c) => {
|
|
13825
13718
|
try {
|
|
13826
13719
|
const transport = resolveBrowserTransport(c.req.raw, c.env?.incoming?.socket?.remoteAddress);
|
|
13827
13720
|
console.error(`[admin/browser/launch] op=request transport=${transport}`);
|
|
@@ -13849,40 +13742,39 @@ app34.post("/launch", requireAdminSession, async (c) => {
|
|
|
13849
13742
|
);
|
|
13850
13743
|
}
|
|
13851
13744
|
});
|
|
13852
|
-
var browser_default =
|
|
13745
|
+
var browser_default = app33;
|
|
13853
13746
|
|
|
13854
13747
|
// server/routes/admin/index.ts
|
|
13855
|
-
var
|
|
13856
|
-
|
|
13857
|
-
|
|
13858
|
-
|
|
13859
|
-
|
|
13860
|
-
|
|
13861
|
-
|
|
13862
|
-
|
|
13863
|
-
|
|
13864
|
-
|
|
13865
|
-
|
|
13866
|
-
|
|
13867
|
-
|
|
13868
|
-
|
|
13869
|
-
|
|
13870
|
-
|
|
13871
|
-
|
|
13872
|
-
|
|
13873
|
-
|
|
13874
|
-
|
|
13875
|
-
|
|
13876
|
-
|
|
13877
|
-
|
|
13878
|
-
|
|
13879
|
-
|
|
13880
|
-
|
|
13881
|
-
|
|
13882
|
-
|
|
13883
|
-
|
|
13884
|
-
|
|
13885
|
-
var admin_default = app35;
|
|
13748
|
+
var app34 = new Hono();
|
|
13749
|
+
app34.route("/session", session_default);
|
|
13750
|
+
app34.route("/logs", logs_default);
|
|
13751
|
+
app34.route("/claude-info", claude_info_default);
|
|
13752
|
+
app34.route("/attachment", attachment_default);
|
|
13753
|
+
app34.route("/agents", agents_default);
|
|
13754
|
+
app34.route("/sessions", sessions_default);
|
|
13755
|
+
app34.route("/claude-sessions", claude_sessions_default);
|
|
13756
|
+
app34.route("/log-ingest", log_ingest_default);
|
|
13757
|
+
app34.route("/events", events_default);
|
|
13758
|
+
app34.route("/files", files_default);
|
|
13759
|
+
app34.route("/graph-search", graph_search_default);
|
|
13760
|
+
app34.route("/graph-subgraph", graph_subgraph_default);
|
|
13761
|
+
app34.route("/graph-delete", graph_delete_default);
|
|
13762
|
+
app34.route("/graph-restore", graph_restore_default);
|
|
13763
|
+
app34.route("/graph-labels-in-graph", graph_labels_in_graph_default);
|
|
13764
|
+
app34.route("/graph-default-view", graph_default_view_default);
|
|
13765
|
+
app34.route("/sidebar-artefacts", sidebar_artefacts_default);
|
|
13766
|
+
app34.route("/sidebar-sessions", sidebar_sessions_default);
|
|
13767
|
+
app34.route("/session-delete", session_delete_default);
|
|
13768
|
+
app34.route("/browser", browser_default);
|
|
13769
|
+
app34.route("/session-rc-spawn", session_rc_spawn_default);
|
|
13770
|
+
app34.route("/system-stats", system_stats_default);
|
|
13771
|
+
app34.route("/health-brand", health_default2);
|
|
13772
|
+
app34.route("/linkedin-ingest", linkedin_ingest_default);
|
|
13773
|
+
app34.route("/post-turn-context", post_turn_context_default);
|
|
13774
|
+
app34.route("/public-session-context", public_session_context_default);
|
|
13775
|
+
app34.route("/public-session-exit", public_session_exit_default);
|
|
13776
|
+
app34.route("/access-session-evict", access_session_evict_default);
|
|
13777
|
+
var admin_default = app34;
|
|
13886
13778
|
|
|
13887
13779
|
// app/lib/access-gate.ts
|
|
13888
13780
|
import neo4j4 from "neo4j-driver";
|
|
@@ -14093,11 +13985,11 @@ async function generateNewMagicToken(grantId) {
|
|
|
14093
13985
|
}
|
|
14094
13986
|
|
|
14095
13987
|
// server/routes/access/verify-token.ts
|
|
14096
|
-
var
|
|
13988
|
+
var TAG28 = "[access-verify]";
|
|
14097
13989
|
var MINT_TAG = "[access-session-mint]";
|
|
14098
13990
|
var COOKIE_NAME = "__access_session";
|
|
14099
|
-
var
|
|
14100
|
-
|
|
13991
|
+
var app35 = new Hono();
|
|
13992
|
+
app35.post("/", async (c) => {
|
|
14101
13993
|
const ip = c.var.clientIp || "unknown";
|
|
14102
13994
|
let body;
|
|
14103
13995
|
try {
|
|
@@ -14112,39 +14004,39 @@ app36.post("/", async (c) => {
|
|
|
14112
14004
|
}
|
|
14113
14005
|
const rateMsg = checkAccessRateLimit(ip, agentSlug);
|
|
14114
14006
|
if (rateMsg) {
|
|
14115
|
-
console.error(`${
|
|
14007
|
+
console.error(`${TAG28} grantId=- agentSlug=${agentSlug} result=rate-limited ip=${ip}`);
|
|
14116
14008
|
return c.json({ error: rateMsg }, 429);
|
|
14117
14009
|
}
|
|
14118
14010
|
const grant = await findGrantByMagicToken(token);
|
|
14119
14011
|
if (!grant) {
|
|
14120
14012
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
14121
|
-
console.error(`${
|
|
14013
|
+
console.error(`${TAG28} grantId=- agentSlug=${agentSlug} result=notfound ip=${ip}`);
|
|
14122
14014
|
return c.json({ error: "invalid-or-expired-link" }, 401);
|
|
14123
14015
|
}
|
|
14124
14016
|
if (grant.agentSlug !== agentSlug) {
|
|
14125
14017
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
14126
14018
|
console.error(
|
|
14127
|
-
`${
|
|
14019
|
+
`${TAG28} grantId=${grant.grantId} agentSlug=${agentSlug} result=agent-mismatch grantAgent=${grant.agentSlug} ip=${ip}`
|
|
14128
14020
|
);
|
|
14129
14021
|
return c.json({ error: "invalid-or-expired-link" }, 401);
|
|
14130
14022
|
}
|
|
14131
14023
|
if (grant.status === "expired" || grant.status === "revoked") {
|
|
14132
14024
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
14133
14025
|
console.error(
|
|
14134
|
-
`${
|
|
14026
|
+
`${TAG28} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired status=${grant.status} ip=${ip}`
|
|
14135
14027
|
);
|
|
14136
14028
|
return c.json({ error: "access-no-longer-valid" }, 401);
|
|
14137
14029
|
}
|
|
14138
14030
|
if (grant.expiresAt !== null && grant.expiresAt < Date.now()) {
|
|
14139
14031
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
14140
14032
|
console.error(
|
|
14141
|
-
`${
|
|
14033
|
+
`${TAG28} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired reason=expiresAt-past ip=${ip}`
|
|
14142
14034
|
);
|
|
14143
14035
|
return c.json({ error: "access-no-longer-valid" }, 401);
|
|
14144
14036
|
}
|
|
14145
14037
|
if (!grant.sliceToken) {
|
|
14146
14038
|
console.error(
|
|
14147
|
-
`${
|
|
14039
|
+
`${TAG28} grantId=${grant.grantId} agentSlug=${agentSlug} result=no-slice-token reason=schema-violation`
|
|
14148
14040
|
);
|
|
14149
14041
|
return c.json({ error: "grant-misconfigured" }, 500);
|
|
14150
14042
|
}
|
|
@@ -14160,12 +14052,12 @@ app36.post("/", async (c) => {
|
|
|
14160
14052
|
await consumeMagicTokenAndActivate(grant.grantId);
|
|
14161
14053
|
} catch (err) {
|
|
14162
14054
|
console.error(
|
|
14163
|
-
`${
|
|
14055
|
+
`${TAG28} grantId=${grant.grantId} agentSlug=${agentSlug} result=consume-failed err="${err instanceof Error ? err.message : String(err)}"`
|
|
14164
14056
|
);
|
|
14165
14057
|
return c.json({ error: "verification-failed" }, 500);
|
|
14166
14058
|
}
|
|
14167
14059
|
clearAccessRateLimit(ip, agentSlug);
|
|
14168
|
-
console.log(`${
|
|
14060
|
+
console.log(`${TAG28} grantId=${grant.grantId} agentSlug=${agentSlug} result=ok ip=${ip}`);
|
|
14169
14061
|
console.log(
|
|
14170
14062
|
`${MINT_TAG} grantId=${grant.grantId} sliceToken=${grant.sliceToken.slice(0, 8)} agentSlug=${agentSlug} personId=${grant.personId ?? "none"}`
|
|
14171
14063
|
);
|
|
@@ -14179,7 +14071,7 @@ app36.post("/", async (c) => {
|
|
|
14179
14071
|
displayName: grant.displayName
|
|
14180
14072
|
});
|
|
14181
14073
|
});
|
|
14182
|
-
var verify_token_default =
|
|
14074
|
+
var verify_token_default = app35;
|
|
14183
14075
|
|
|
14184
14076
|
// app/lib/access-email.ts
|
|
14185
14077
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -14241,10 +14133,10 @@ async function sendMagicLinkEmail(payload) {
|
|
|
14241
14133
|
}
|
|
14242
14134
|
|
|
14243
14135
|
// server/routes/access/request-magic-link.ts
|
|
14244
|
-
var
|
|
14245
|
-
var
|
|
14136
|
+
var TAG29 = "[access-request-link]";
|
|
14137
|
+
var app36 = new Hono();
|
|
14246
14138
|
var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
|
|
14247
|
-
|
|
14139
|
+
app36.post("/", async (c) => {
|
|
14248
14140
|
let body;
|
|
14249
14141
|
try {
|
|
14250
14142
|
body = await c.req.json();
|
|
@@ -14258,18 +14150,18 @@ app37.post("/", async (c) => {
|
|
|
14258
14150
|
}
|
|
14259
14151
|
const rateMsg = checkRequestLinkRateLimit(contactValue);
|
|
14260
14152
|
if (rateMsg) {
|
|
14261
|
-
console.error(`${
|
|
14153
|
+
console.error(`${TAG29} contactValue=${maskContact(contactValue)} result=rate-limited`);
|
|
14262
14154
|
return c.json({ error: rateMsg }, 429);
|
|
14263
14155
|
}
|
|
14264
14156
|
recordRequestLinkAttempt(contactValue);
|
|
14265
14157
|
const accountId = process.env.ACCOUNT_ID ?? "";
|
|
14266
14158
|
if (!accountId) {
|
|
14267
|
-
console.error(`${
|
|
14159
|
+
console.error(`${TAG29} contactValue=${maskContact(contactValue)} result=no-account-id`);
|
|
14268
14160
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
14269
14161
|
}
|
|
14270
14162
|
const grant = await findActiveGrantByContact(contactValue, agentSlug, accountId);
|
|
14271
14163
|
if (!grant) {
|
|
14272
|
-
console.log(`${
|
|
14164
|
+
console.log(`${TAG29} contactValue=${maskContact(contactValue)} result=notfound`);
|
|
14273
14165
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
14274
14166
|
}
|
|
14275
14167
|
let token;
|
|
@@ -14277,7 +14169,7 @@ app37.post("/", async (c) => {
|
|
|
14277
14169
|
token = await generateNewMagicToken(grant.grantId);
|
|
14278
14170
|
} catch (err) {
|
|
14279
14171
|
console.error(
|
|
14280
|
-
`${
|
|
14172
|
+
`${TAG29} contactValue=${maskContact(contactValue)} result=mint-failed err="${err instanceof Error ? err.message : String(err)}"`
|
|
14281
14173
|
);
|
|
14282
14174
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
14283
14175
|
}
|
|
@@ -14309,22 +14201,22 @@ app37.post("/", async (c) => {
|
|
|
14309
14201
|
});
|
|
14310
14202
|
if (!sendResult.ok) {
|
|
14311
14203
|
console.error(
|
|
14312
|
-
`${
|
|
14204
|
+
`${TAG29} contactValue=${maskContact(contactValue)} result=send-failed err="${sendResult.error}"`
|
|
14313
14205
|
);
|
|
14314
14206
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
14315
14207
|
}
|
|
14316
14208
|
console.log(
|
|
14317
|
-
`${
|
|
14209
|
+
`${TAG29} contactValue=${maskContact(contactValue)} result=ok messageId=${sendResult.messageId}`
|
|
14318
14210
|
);
|
|
14319
14211
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
14320
14212
|
});
|
|
14321
|
-
var request_magic_link_default =
|
|
14213
|
+
var request_magic_link_default = app36;
|
|
14322
14214
|
|
|
14323
14215
|
// server/routes/access/index.ts
|
|
14324
|
-
var
|
|
14325
|
-
|
|
14326
|
-
|
|
14327
|
-
var access_default =
|
|
14216
|
+
var app37 = new Hono();
|
|
14217
|
+
app37.route("/verify-token", verify_token_default);
|
|
14218
|
+
app37.route("/request-magic-link", request_magic_link_default);
|
|
14219
|
+
var access_default = app37;
|
|
14328
14220
|
|
|
14329
14221
|
// server/routes/sites.ts
|
|
14330
14222
|
import { existsSync as existsSync19, readFileSync as readFileSync18, realpathSync as realpathSync5, statSync as statSync8 } from "fs";
|
|
@@ -14359,8 +14251,8 @@ function getExt(p) {
|
|
|
14359
14251
|
if (idx < p.lastIndexOf("/")) return "";
|
|
14360
14252
|
return p.slice(idx).toLowerCase();
|
|
14361
14253
|
}
|
|
14362
|
-
var
|
|
14363
|
-
|
|
14254
|
+
var app38 = new Hono();
|
|
14255
|
+
app38.get("/:rel{.*}", (c) => {
|
|
14364
14256
|
const reqPath = c.req.path;
|
|
14365
14257
|
const rawRel = c.req.param("rel") ?? "";
|
|
14366
14258
|
const trimmed = rawRel.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
@@ -14463,7 +14355,7 @@ app39.get("/:rel{.*}", (c) => {
|
|
|
14463
14355
|
"X-Content-Type-Options": "nosniff"
|
|
14464
14356
|
});
|
|
14465
14357
|
});
|
|
14466
|
-
var sites_default =
|
|
14358
|
+
var sites_default = app38;
|
|
14467
14359
|
|
|
14468
14360
|
// app/lib/visitor-token.ts
|
|
14469
14361
|
import { createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
@@ -14563,7 +14455,7 @@ function readBrandConfig() {
|
|
|
14563
14455
|
}
|
|
14564
14456
|
|
|
14565
14457
|
// server/routes/visitor-consent.ts
|
|
14566
|
-
var
|
|
14458
|
+
var app39 = new Hono();
|
|
14567
14459
|
var CONSENT_COOKIE_NAME = "mxy_consent";
|
|
14568
14460
|
var CONSENT_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365;
|
|
14569
14461
|
var DEFAULT_CONSENT_COPY = {
|
|
@@ -14608,17 +14500,17 @@ function siteSlugFromReferer(referer) {
|
|
|
14608
14500
|
return "";
|
|
14609
14501
|
}
|
|
14610
14502
|
}
|
|
14611
|
-
|
|
14503
|
+
app39.options("/consent", (c) => {
|
|
14612
14504
|
const origin = getOrigin(c);
|
|
14613
14505
|
setCorsHeaders(c, origin);
|
|
14614
14506
|
return c.body(null, 204);
|
|
14615
14507
|
});
|
|
14616
|
-
|
|
14508
|
+
app39.options("/brand-config", (c) => {
|
|
14617
14509
|
const origin = getOrigin(c);
|
|
14618
14510
|
setCorsHeaders(c, origin);
|
|
14619
14511
|
return c.body(null, 204);
|
|
14620
14512
|
});
|
|
14621
|
-
|
|
14513
|
+
app39.post("/consent", async (c) => {
|
|
14622
14514
|
const origin = getOrigin(c);
|
|
14623
14515
|
setCorsHeaders(c, origin);
|
|
14624
14516
|
let raw;
|
|
@@ -14658,7 +14550,7 @@ app40.post("/consent", async (c) => {
|
|
|
14658
14550
|
console.log(`[consent] ${parsed.decision} site=${site} brand=${brandName} tokenBound=${tokenBound}`);
|
|
14659
14551
|
return c.body(null, 204);
|
|
14660
14552
|
});
|
|
14661
|
-
|
|
14553
|
+
app39.get("/brand-config", (c) => {
|
|
14662
14554
|
const origin = getOrigin(c);
|
|
14663
14555
|
setCorsHeaders(c, origin);
|
|
14664
14556
|
const brand = readBrandConfig();
|
|
@@ -14668,7 +14560,7 @@ app40.get("/brand-config", (c) => {
|
|
|
14668
14560
|
c.header("Cache-Control", "public, max-age=300");
|
|
14669
14561
|
return c.json({ consent: { copy, palette } });
|
|
14670
14562
|
});
|
|
14671
|
-
var visitor_consent_default =
|
|
14563
|
+
var visitor_consent_default = app39;
|
|
14672
14564
|
|
|
14673
14565
|
// server/routes/listings.ts
|
|
14674
14566
|
function getCookie(headerValue, name) {
|
|
@@ -14695,8 +14587,8 @@ function appendConsentParams(pageUrl, token) {
|
|
|
14695
14587
|
}
|
|
14696
14588
|
var SAFE_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,118}[a-z0-9])?$/;
|
|
14697
14589
|
var CHAT_SESSION_KEY_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{7,127}$/;
|
|
14698
|
-
var
|
|
14699
|
-
|
|
14590
|
+
var app40 = new Hono();
|
|
14591
|
+
app40.get("/:slug/click", async (c) => {
|
|
14700
14592
|
const slug = c.req.param("slug") ?? "";
|
|
14701
14593
|
const rawSession = c.req.query("session") ?? "";
|
|
14702
14594
|
const sessionKey = CHAT_SESSION_KEY_RE.test(rawSession) ? rawSession : "invalid";
|
|
@@ -14760,10 +14652,10 @@ app41.get("/:slug/click", async (c) => {
|
|
|
14760
14652
|
console.log(`[property-card-click] sessionKey=${sessionKey} listingSlug=${slug} consent=${consentCookie ?? "absent"} ts=${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
14761
14653
|
return c.redirect(redirectUrl, 302);
|
|
14762
14654
|
});
|
|
14763
|
-
var listings_default =
|
|
14655
|
+
var listings_default = app40;
|
|
14764
14656
|
|
|
14765
14657
|
// server/routes/visitor-event.ts
|
|
14766
|
-
var
|
|
14658
|
+
var app41 = new Hono();
|
|
14767
14659
|
var BOT_UA_RE = /\b(bot|crawl|spider|slurp|headlesschrome|phantomjs|googlebot|bingbot|yandex|baiduspider|ahrefsbot|semrushbot|mj12bot|dotbot|petalbot)\b/i;
|
|
14768
14660
|
var buckets = /* @__PURE__ */ new Map();
|
|
14769
14661
|
var RATE_LIMIT = 60;
|
|
@@ -14830,12 +14722,12 @@ function originAllowed(origin, allowlist) {
|
|
|
14830
14722
|
return false;
|
|
14831
14723
|
}
|
|
14832
14724
|
}
|
|
14833
|
-
|
|
14725
|
+
app41.options("/event", (c) => {
|
|
14834
14726
|
const origin = getOrigin2(c);
|
|
14835
14727
|
setCorsHeaders2(c, origin);
|
|
14836
14728
|
return c.body(null, 204);
|
|
14837
14729
|
});
|
|
14838
|
-
|
|
14730
|
+
app41.post("/event", async (c) => {
|
|
14839
14731
|
const origin = getOrigin2(c);
|
|
14840
14732
|
setCorsHeaders2(c, origin);
|
|
14841
14733
|
const ua = c.req.header("user-agent") ?? "";
|
|
@@ -15040,7 +14932,7 @@ async function writeEvent(opts) {
|
|
|
15040
14932
|
);
|
|
15041
14933
|
}
|
|
15042
14934
|
}
|
|
15043
|
-
var visitor_event_default =
|
|
14935
|
+
var visitor_event_default = app41;
|
|
15044
14936
|
|
|
15045
14937
|
// server/routes/session.ts
|
|
15046
14938
|
import { resolve as resolve23 } from "path";
|
|
@@ -15086,8 +14978,8 @@ function withVisitorCookie(response, visitorId) {
|
|
|
15086
14978
|
headers
|
|
15087
14979
|
});
|
|
15088
14980
|
}
|
|
15089
|
-
var
|
|
15090
|
-
|
|
14981
|
+
var app42 = new Hono();
|
|
14982
|
+
app42.post("/", async (c) => {
|
|
15091
14983
|
let body;
|
|
15092
14984
|
try {
|
|
15093
14985
|
body = await c.req.json();
|
|
@@ -15298,10 +15190,10 @@ app43.post("/", async (c) => {
|
|
|
15298
15190
|
newVisitorId
|
|
15299
15191
|
);
|
|
15300
15192
|
});
|
|
15301
|
-
var session_default2 =
|
|
15193
|
+
var session_default2 = app42;
|
|
15302
15194
|
|
|
15303
15195
|
// app/lib/graph-health.ts
|
|
15304
|
-
var
|
|
15196
|
+
var import_dist4 = __toESM(require_dist3(), 1);
|
|
15305
15197
|
var HOUR_MS = 60 * 60 * 1e3;
|
|
15306
15198
|
function renderLabelTop(rows) {
|
|
15307
15199
|
return rows.map((b) => {
|
|
@@ -15346,7 +15238,7 @@ async function runGraphHealthTick() {
|
|
|
15346
15238
|
console.error(
|
|
15347
15239
|
`[graph-health] userprofile-multi accounts=${upAccounts} top=${upTop.length > 0 ? upTop.join(",") : "none"}`
|
|
15348
15240
|
);
|
|
15349
|
-
const indexed = [...
|
|
15241
|
+
const indexed = [...import_dist4.VECTOR_INDEXED_LABELS];
|
|
15350
15242
|
const embCount = await session.run(
|
|
15351
15243
|
`MATCH (n) WHERE n.embedding IS NULL AND any(l IN labels(n) WHERE l IN $indexed)
|
|
15352
15244
|
RETURN count(n) AS total`,
|
|
@@ -15521,51 +15413,6 @@ async function startFileWatcher(opts = {}) {
|
|
|
15521
15413
|
}
|
|
15522
15414
|
|
|
15523
15415
|
// app/lib/whatsapp/inbound/claude-bridge.ts
|
|
15524
|
-
var TAG32 = "[whatsapp-adaptor]";
|
|
15525
|
-
function whatsappTurnTimeoutMs() {
|
|
15526
|
-
return Number(process.env.WHATSAPP_PTY_TURN_TIMEOUT_MS ?? String(5 * 6e4));
|
|
15527
|
-
}
|
|
15528
|
-
function composeTurn(input) {
|
|
15529
|
-
const caption = input.text.trim();
|
|
15530
|
-
const hasFileMedia = !!input.mediaPath && input.mediaType !== "audio";
|
|
15531
|
-
if (!hasFileMedia) return caption;
|
|
15532
|
-
const type = input.mediaType ?? "file";
|
|
15533
|
-
const note = input.role === "admin" ? `[Inbound WhatsApp ${type}: ${input.mediaPath}${input.mediaMimetype ? ` (${input.mediaMimetype})` : ""}. Read this file to see what the sender shared.]` : `[The sender shared a ${type}. You cannot open shared files in this session \u2014 ask them to describe or paste the relevant content.]`;
|
|
15534
|
-
return caption ? `${caption}
|
|
15535
|
-
|
|
15536
|
-
${note}` : note;
|
|
15537
|
-
}
|
|
15538
|
-
async function dispatchToClaude(input) {
|
|
15539
|
-
const hasFileMedia = !!input.mediaPath && input.mediaType !== "audio";
|
|
15540
|
-
const mediaField = hasFileMedia ? `media=${input.mediaType} mediaPath=${input.mediaPath}` : input.mediaType === "audio" ? "media=audio mediaPath=transcribed" : "media=none";
|
|
15541
|
-
console.error(`${TAG32} inbound-media ${mediaField} role=${input.role} senderId=${input.senderId}`);
|
|
15542
|
-
const text = composeTurn(input);
|
|
15543
|
-
if (!text.trim()) return;
|
|
15544
|
-
const result = await dispatchOnce({
|
|
15545
|
-
accountId: input.accountId,
|
|
15546
|
-
senderId: input.senderId,
|
|
15547
|
-
role: input.role,
|
|
15548
|
-
channel: "whatsapp",
|
|
15549
|
-
agentSlug: input.agentSlug,
|
|
15550
|
-
text,
|
|
15551
|
-
timeoutMs: whatsappTurnTimeoutMs()
|
|
15552
|
-
});
|
|
15553
|
-
if ("error" in result) {
|
|
15554
|
-
if (result.error === "timeout" && result.cause === "no-turn") {
|
|
15555
|
-
recordInboundOutcome(input.senderId, "timeout-no-turn");
|
|
15556
|
-
} else if (result.error === "timeout" && result.cause === "relay-missed") {
|
|
15557
|
-
recordInboundOutcome(input.senderId, "timeout-relay-missed");
|
|
15558
|
-
}
|
|
15559
|
-
return;
|
|
15560
|
-
}
|
|
15561
|
-
recordInboundOutcome(input.senderId, "relay-ok");
|
|
15562
|
-
try {
|
|
15563
|
-
await input.reply(result.turnText);
|
|
15564
|
-
} catch (err) {
|
|
15565
|
-
const m = err instanceof Error ? err.message : String(err);
|
|
15566
|
-
console.error(`${TAG32} reject reason=reply-failed senderId=${input.senderId} message=${m}`);
|
|
15567
|
-
}
|
|
15568
|
-
}
|
|
15569
15416
|
function startReaper2() {
|
|
15570
15417
|
startReaper();
|
|
15571
15418
|
}
|
|
@@ -15767,8 +15614,8 @@ var streamSSE = (c, cb, onError) => {
|
|
|
15767
15614
|
|
|
15768
15615
|
// app/lib/whatsapp/gateway/routes.ts
|
|
15769
15616
|
function createWaChannelRoutes(deps) {
|
|
15770
|
-
const
|
|
15771
|
-
|
|
15617
|
+
const app44 = new Hono();
|
|
15618
|
+
app44.get("/wa-channel/inbound", (c) => {
|
|
15772
15619
|
const senderId = c.req.query("senderId");
|
|
15773
15620
|
if (!senderId) return c.json({ error: "senderId required" }, 400);
|
|
15774
15621
|
return streamSSE(c, async (stream2) => {
|
|
@@ -15786,7 +15633,7 @@ function createWaChannelRoutes(deps) {
|
|
|
15786
15633
|
}
|
|
15787
15634
|
});
|
|
15788
15635
|
});
|
|
15789
|
-
|
|
15636
|
+
app44.post("/wa-channel/reply", async (c) => {
|
|
15790
15637
|
const body = await c.req.json().catch(() => null);
|
|
15791
15638
|
const senderId = body?.senderId;
|
|
15792
15639
|
const text = body?.text;
|
|
@@ -15805,7 +15652,7 @@ function createWaChannelRoutes(deps) {
|
|
|
15805
15652
|
console.error(`[whatsapp-native] op=reply-dispatch senderId=${senderId} bytes=${bytes}`);
|
|
15806
15653
|
return c.json({ ok: true });
|
|
15807
15654
|
});
|
|
15808
|
-
|
|
15655
|
+
app44.post("/wa-channel/ready", async (c) => {
|
|
15809
15656
|
const body = await c.req.json().catch(() => null);
|
|
15810
15657
|
const senderId = body?.senderId;
|
|
15811
15658
|
if (typeof senderId !== "string") {
|
|
@@ -15814,7 +15661,7 @@ function createWaChannelRoutes(deps) {
|
|
|
15814
15661
|
deps.onReady?.(senderId);
|
|
15815
15662
|
return c.json({ ok: true });
|
|
15816
15663
|
});
|
|
15817
|
-
return
|
|
15664
|
+
return app44;
|
|
15818
15665
|
}
|
|
15819
15666
|
|
|
15820
15667
|
// app/lib/whatsapp/gateway/wa-gateway.ts
|
|
@@ -16187,7 +16034,7 @@ watchFile(ALIAS_DOMAINS_PATH, { interval: 2e3 }, () => {
|
|
|
16187
16034
|
function isPublicHost(host) {
|
|
16188
16035
|
return host.startsWith("public.") || aliasDomains.has(host);
|
|
16189
16036
|
}
|
|
16190
|
-
var
|
|
16037
|
+
var app43 = new Hono();
|
|
16191
16038
|
var waGateway = new WaGateway({
|
|
16192
16039
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
16193
16040
|
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve26(process.env.MAXY_PLATFORM_ROOT ?? join18(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
@@ -16202,9 +16049,9 @@ var waGateway = new WaGateway({
|
|
|
16202
16049
|
}
|
|
16203
16050
|
}
|
|
16204
16051
|
});
|
|
16205
|
-
|
|
16206
|
-
|
|
16207
|
-
|
|
16052
|
+
app43.route("/", waGateway.routes());
|
|
16053
|
+
app43.use("*", clientIpMiddleware);
|
|
16054
|
+
app43.use("*", async (c, next) => {
|
|
16208
16055
|
await next();
|
|
16209
16056
|
c.header("X-Content-Type-Options", "nosniff");
|
|
16210
16057
|
c.header("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
@@ -16214,7 +16061,7 @@ app44.use("*", async (c, next) => {
|
|
|
16214
16061
|
);
|
|
16215
16062
|
});
|
|
16216
16063
|
var HTTP_LOG_PATHS = /* @__PURE__ */ new Set(["/vnc-viewer.html", "/vnc-popout.html"]);
|
|
16217
|
-
|
|
16064
|
+
app43.use("*", async (c, next) => {
|
|
16218
16065
|
if (!HTTP_LOG_PATHS.has(c.req.path)) {
|
|
16219
16066
|
await next();
|
|
16220
16067
|
return;
|
|
@@ -16232,7 +16079,7 @@ app44.use("*", async (c, next) => {
|
|
|
16232
16079
|
});
|
|
16233
16080
|
}
|
|
16234
16081
|
});
|
|
16235
|
-
|
|
16082
|
+
app43.use("*", async (c, next) => {
|
|
16236
16083
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16237
16084
|
if (!isPublicHost(host)) {
|
|
16238
16085
|
await next();
|
|
@@ -16263,7 +16110,7 @@ function resolveRemoteAuthOpts() {
|
|
|
16263
16110
|
return brandLoginOpts;
|
|
16264
16111
|
}
|
|
16265
16112
|
var MAX_LOGIN_BODY = 8 * 1024;
|
|
16266
|
-
|
|
16113
|
+
app43.post("/__remote-auth/login", async (c) => {
|
|
16267
16114
|
const client = clientFrom(c);
|
|
16268
16115
|
const clientIp = client.ip || "unknown";
|
|
16269
16116
|
if (!requestIsTlsTerminated(c)) {
|
|
@@ -16308,7 +16155,7 @@ app44.post("/__remote-auth/login", async (c) => {
|
|
|
16308
16155
|
}
|
|
16309
16156
|
});
|
|
16310
16157
|
});
|
|
16311
|
-
|
|
16158
|
+
app43.get("/__remote-auth/logout", (c) => {
|
|
16312
16159
|
const client = clientFrom(c);
|
|
16313
16160
|
const clientIp = client.ip || "unknown";
|
|
16314
16161
|
console.error(`[remote-auth] logout ip=${clientIp}`);
|
|
@@ -16321,7 +16168,7 @@ app44.get("/__remote-auth/logout", (c) => {
|
|
|
16321
16168
|
}
|
|
16322
16169
|
});
|
|
16323
16170
|
});
|
|
16324
|
-
|
|
16171
|
+
app43.post("/__remote-auth/change-password", async (c) => {
|
|
16325
16172
|
const client = clientFrom(c);
|
|
16326
16173
|
const clientIp = client.ip || "unknown";
|
|
16327
16174
|
const rateLimited = checkRateLimit(client);
|
|
@@ -16372,13 +16219,13 @@ app44.post("/__remote-auth/change-password", async (c) => {
|
|
|
16372
16219
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "change", changeError: "Failed to save password", redirect }), 200);
|
|
16373
16220
|
}
|
|
16374
16221
|
});
|
|
16375
|
-
|
|
16222
|
+
app43.get("/__remote-auth/setup", (c) => {
|
|
16376
16223
|
if (isRemoteAuthConfigured()) {
|
|
16377
16224
|
return c.redirect("/");
|
|
16378
16225
|
}
|
|
16379
16226
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup" }), 200);
|
|
16380
16227
|
});
|
|
16381
|
-
|
|
16228
|
+
app43.post("/__remote-auth/set-initial-password", async (c) => {
|
|
16382
16229
|
if (isRemoteAuthConfigured()) {
|
|
16383
16230
|
return c.redirect("/");
|
|
16384
16231
|
}
|
|
@@ -16416,10 +16263,10 @@ app44.post("/__remote-auth/set-initial-password", async (c) => {
|
|
|
16416
16263
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
|
|
16417
16264
|
}
|
|
16418
16265
|
});
|
|
16419
|
-
|
|
16266
|
+
app43.get("/api/remote-auth/status", (c) => {
|
|
16420
16267
|
return c.json({ configured: isRemoteAuthConfigured() });
|
|
16421
16268
|
});
|
|
16422
|
-
|
|
16269
|
+
app43.post("/api/remote-auth/set-password", async (c) => {
|
|
16423
16270
|
let body;
|
|
16424
16271
|
try {
|
|
16425
16272
|
body = await c.req.json();
|
|
@@ -16450,9 +16297,9 @@ app44.post("/api/remote-auth/set-password", async (c) => {
|
|
|
16450
16297
|
return c.json({ error: "Failed to save password" }, 500);
|
|
16451
16298
|
}
|
|
16452
16299
|
});
|
|
16453
|
-
|
|
16300
|
+
app43.route("/api/_client-error", client_error_default);
|
|
16454
16301
|
console.log("[client-error-route] mounted");
|
|
16455
|
-
|
|
16302
|
+
app43.use("*", async (c, next) => {
|
|
16456
16303
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16457
16304
|
const path2 = c.req.path;
|
|
16458
16305
|
if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/")) {
|
|
@@ -16485,13 +16332,13 @@ app44.use("*", async (c, next) => {
|
|
|
16485
16332
|
console.error(`[remote-auth] login required ip=${clientIp} path=${path2} ${disambig}`);
|
|
16486
16333
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), redirect: path2 }), 200);
|
|
16487
16334
|
});
|
|
16488
|
-
|
|
16489
|
-
|
|
16490
|
-
|
|
16491
|
-
|
|
16492
|
-
|
|
16493
|
-
|
|
16494
|
-
|
|
16335
|
+
app43.route("/api/health", health_default);
|
|
16336
|
+
app43.route("/api/chat", chat_default);
|
|
16337
|
+
app43.route("/api/whatsapp", whatsapp_default);
|
|
16338
|
+
app43.route("/api/onboarding", onboarding_default);
|
|
16339
|
+
app43.route("/api/admin", admin_default);
|
|
16340
|
+
app43.route("/api/access", access_default);
|
|
16341
|
+
app43.route("/api/session", session_default2);
|
|
16495
16342
|
var SAFE_SLUG_RE2 = /^[a-z][a-z0-9-]{2,49}$/;
|
|
16496
16343
|
var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
16497
16344
|
var IMAGE_MIME = {
|
|
@@ -16503,7 +16350,7 @@ var IMAGE_MIME = {
|
|
|
16503
16350
|
".svg": "image/svg+xml",
|
|
16504
16351
|
".ico": "image/x-icon"
|
|
16505
16352
|
};
|
|
16506
|
-
|
|
16353
|
+
app43.get("/agent-assets/:slug/:filename", (c) => {
|
|
16507
16354
|
const slug = c.req.param("slug");
|
|
16508
16355
|
const filename = c.req.param("filename");
|
|
16509
16356
|
if (!SAFE_SLUG_RE2.test(slug)) {
|
|
@@ -16538,7 +16385,7 @@ app44.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
16538
16385
|
"Cache-Control": "public, max-age=3600"
|
|
16539
16386
|
});
|
|
16540
16387
|
});
|
|
16541
|
-
|
|
16388
|
+
app43.get("/generated/:filename", (c) => {
|
|
16542
16389
|
const filename = c.req.param("filename");
|
|
16543
16390
|
if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
|
|
16544
16391
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
@@ -16568,10 +16415,10 @@ app44.get("/generated/:filename", (c) => {
|
|
|
16568
16415
|
"Cache-Control": "public, max-age=86400"
|
|
16569
16416
|
});
|
|
16570
16417
|
});
|
|
16571
|
-
|
|
16572
|
-
|
|
16573
|
-
|
|
16574
|
-
|
|
16418
|
+
app43.route("/sites", sites_default);
|
|
16419
|
+
app43.route("/listings", listings_default);
|
|
16420
|
+
app43.route("/v", visitor_event_default);
|
|
16421
|
+
app43.route("/v", visitor_consent_default);
|
|
16575
16422
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
16576
16423
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
16577
16424
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
@@ -16702,7 +16549,7 @@ function escapeHtml(s) {
|
|
|
16702
16549
|
function agentUnavailableHtml() {
|
|
16703
16550
|
return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>${escapeHtml(BRAND.productName)}</title></head><body style="font-family:system-ui,sans-serif;max-width:32rem;margin:4rem auto;padding:0 1.5rem;color:#222"><h1 style="font-size:1.25rem">Agent unavailable</h1><p>This agent isn't available right now. If you reached this page from a saved link, the agent may have been turned off.</p></body></html>`;
|
|
16704
16551
|
}
|
|
16705
|
-
|
|
16552
|
+
app43.get("/", (c) => {
|
|
16706
16553
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16707
16554
|
if (isPublicHost(host)) {
|
|
16708
16555
|
const defaultSlug = resolveDefaultSlug();
|
|
@@ -16718,12 +16565,12 @@ app44.get("/", (c) => {
|
|
|
16718
16565
|
}
|
|
16719
16566
|
return c.html(cachedHtml("index.html"));
|
|
16720
16567
|
});
|
|
16721
|
-
|
|
16568
|
+
app43.get("/public", (c) => {
|
|
16722
16569
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16723
16570
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
16724
16571
|
return c.html(cachedHtml("public.html"));
|
|
16725
16572
|
});
|
|
16726
|
-
|
|
16573
|
+
app43.get("/chat", (c) => {
|
|
16727
16574
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16728
16575
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
16729
16576
|
return c.html(cachedHtml("public.html"));
|
|
@@ -16742,9 +16589,9 @@ async function logViewerFetch(c, next) {
|
|
|
16742
16589
|
duration_ms: Date.now() - start
|
|
16743
16590
|
});
|
|
16744
16591
|
}
|
|
16745
|
-
|
|
16746
|
-
|
|
16747
|
-
|
|
16592
|
+
app43.use("/vnc-viewer.html", logViewerFetch);
|
|
16593
|
+
app43.use("/vnc-popout.html", logViewerFetch);
|
|
16594
|
+
app43.get("/vnc-popout.html", (c) => {
|
|
16748
16595
|
let html = htmlCache.get("vnc-popout.html");
|
|
16749
16596
|
if (!html) {
|
|
16750
16597
|
html = readFileSync22(resolve26(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
@@ -16757,7 +16604,7 @@ app44.get("/vnc-popout.html", (c) => {
|
|
|
16757
16604
|
}
|
|
16758
16605
|
return c.html(html);
|
|
16759
16606
|
});
|
|
16760
|
-
|
|
16607
|
+
app43.post("/api/vnc/client-event", async (c) => {
|
|
16761
16608
|
let body;
|
|
16762
16609
|
try {
|
|
16763
16610
|
body = await c.req.json();
|
|
@@ -16778,30 +16625,30 @@ app44.post("/api/vnc/client-event", async (c) => {
|
|
|
16778
16625
|
});
|
|
16779
16626
|
return c.json({ ok: true });
|
|
16780
16627
|
});
|
|
16781
|
-
|
|
16628
|
+
app43.get("/g/:slug", (c) => {
|
|
16782
16629
|
return c.html(brandedPublicHtml());
|
|
16783
16630
|
});
|
|
16784
|
-
|
|
16631
|
+
app43.get("/graph", (c) => {
|
|
16785
16632
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16786
16633
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
16787
16634
|
return c.html(cachedHtml("graph.html"));
|
|
16788
16635
|
});
|
|
16789
|
-
|
|
16636
|
+
app43.get("/sessions", (c) => {
|
|
16790
16637
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16791
16638
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
16792
16639
|
return c.html(cachedHtml("sessions.html"));
|
|
16793
16640
|
});
|
|
16794
|
-
|
|
16641
|
+
app43.get("/data", (c) => {
|
|
16795
16642
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16796
16643
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
16797
16644
|
return c.html(cachedHtml("data.html"));
|
|
16798
16645
|
});
|
|
16799
|
-
|
|
16646
|
+
app43.get("/browser", (c) => {
|
|
16800
16647
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16801
16648
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
16802
16649
|
return c.html(cachedHtml("browser.html"));
|
|
16803
16650
|
});
|
|
16804
|
-
|
|
16651
|
+
app43.get("/:slug", async (c, next) => {
|
|
16805
16652
|
const slug = c.req.param("slug");
|
|
16806
16653
|
if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
|
|
16807
16654
|
const account = resolveAccount();
|
|
@@ -16816,13 +16663,13 @@ app44.get("/:slug", async (c, next) => {
|
|
|
16816
16663
|
await next();
|
|
16817
16664
|
});
|
|
16818
16665
|
if (brandFaviconPath !== "/favicon.ico") {
|
|
16819
|
-
|
|
16666
|
+
app43.get("/favicon.ico", (c) => {
|
|
16820
16667
|
c.header("Cache-Control", "public, max-age=300");
|
|
16821
16668
|
return c.redirect(brandFaviconPath, 302);
|
|
16822
16669
|
});
|
|
16823
16670
|
}
|
|
16824
|
-
|
|
16825
|
-
|
|
16671
|
+
app43.use("/*", serveStatic({ root: "./public" }));
|
|
16672
|
+
app43.all("*", (c) => {
|
|
16826
16673
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
16827
16674
|
const path2 = c.req.path;
|
|
16828
16675
|
if (isPublicHost(host)) {
|
|
@@ -16836,7 +16683,7 @@ app44.all("*", (c) => {
|
|
|
16836
16683
|
});
|
|
16837
16684
|
var port = requirePortEnv("MAXY_UI_INTERNAL_PORT", { tag: "ui-server" });
|
|
16838
16685
|
var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
16839
|
-
var httpServer = serve({ fetch:
|
|
16686
|
+
var httpServer = serve({ fetch: app43.fetch, port, hostname });
|
|
16840
16687
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
16841
16688
|
startAuthHealthHeartbeat();
|
|
16842
16689
|
{
|
|
@@ -16873,7 +16720,7 @@ for (const m of SUBAPP_MANIFEST) {
|
|
|
16873
16720
|
}
|
|
16874
16721
|
try {
|
|
16875
16722
|
const registered = [];
|
|
16876
|
-
for (const r of
|
|
16723
|
+
for (const r of app43.routes ?? []) {
|
|
16877
16724
|
if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
|
|
16878
16725
|
if (AGENT_SLUG_PATTERN.test(r.path)) {
|
|
16879
16726
|
registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
|
|
@@ -17014,60 +16861,37 @@ init({
|
|
|
17014
16861
|
platformRoot: resolve26(process.env.MAXY_PLATFORM_ROOT ?? join18(__dirname, "..")),
|
|
17015
16862
|
accountConfig: bootAccountConfig,
|
|
17016
16863
|
onMessage: async (msg) => {
|
|
17017
|
-
if (
|
|
17018
|
-
|
|
17019
|
-
void msg.composing().catch(() => {
|
|
17020
|
-
});
|
|
17021
|
-
await waGateway.handleInbound({
|
|
17022
|
-
accountId: msg.accountId,
|
|
17023
|
-
senderId: msg.senderPhone,
|
|
17024
|
-
text: msg.text,
|
|
17025
|
-
reply: msg.reply
|
|
17026
|
-
});
|
|
17027
|
-
} catch (err) {
|
|
17028
|
-
console.error(
|
|
17029
|
-
`[whatsapp-native] reject senderId=${msg.senderPhone} message=${err instanceof Error ? err.message : String(err)}`
|
|
17030
|
-
);
|
|
17031
|
-
}
|
|
16864
|
+
if (msg.isOwnerMirror) {
|
|
16865
|
+
console.error(`[whatsapp:route] skipped reason=owner-mirror senderId=${msg.senderPhone}`);
|
|
17032
16866
|
return;
|
|
17033
16867
|
}
|
|
17034
|
-
if (
|
|
17035
|
-
|
|
17036
|
-
void msg.composing().catch(() => {
|
|
17037
|
-
});
|
|
17038
|
-
let agentSlugForBridge;
|
|
17039
|
-
if (msg.agentType === "admin") {
|
|
17040
|
-
agentSlugForBridge = "admin";
|
|
17041
|
-
} else {
|
|
17042
|
-
const resolved = bootAccount ? resolvePublicAgent(bootAccount.accountDir, { accountId: msg.accountId, groupJid: msg.groupJid }) : null;
|
|
17043
|
-
if (!resolved) {
|
|
17044
|
-
console.error(`[whatsapp-adaptor] reject reason=no-public-agent senderId=${msg.senderPhone} accountId=${msg.accountId} groupJid=${msg.groupJid ?? "none"}`);
|
|
17045
|
-
return;
|
|
17046
|
-
}
|
|
17047
|
-
agentSlugForBridge = resolved.slug;
|
|
17048
|
-
}
|
|
17049
|
-
startReaper2();
|
|
17050
|
-
await dispatchToClaude({
|
|
17051
|
-
accountId: msg.accountId,
|
|
17052
|
-
senderId: msg.senderPhone,
|
|
17053
|
-
role: msg.agentType,
|
|
17054
|
-
agentSlug: agentSlugForBridge,
|
|
17055
|
-
text: msg.text,
|
|
17056
|
-
mediaPath: msg.mediaPath,
|
|
17057
|
-
mediaType: msg.mediaType,
|
|
17058
|
-
mediaMimetype: msg.mediaMimetype,
|
|
17059
|
-
reply: msg.reply
|
|
17060
|
-
});
|
|
17061
|
-
} catch (err) {
|
|
17062
|
-
console.error(`[whatsapp-adaptor] reject reason=bridge-throw senderId=${msg.senderPhone} message=${err instanceof Error ? err.message : String(err)}`);
|
|
17063
|
-
}
|
|
16868
|
+
if (msg.agentType !== "admin") {
|
|
16869
|
+
console.error(`[whatsapp:route] dropped reason=non-admin-sender senderId=${msg.senderPhone} agentType=${msg.agentType}`);
|
|
17064
16870
|
return;
|
|
17065
16871
|
}
|
|
17066
|
-
|
|
16872
|
+
if (!msg.text) {
|
|
16873
|
+
console.error(`[whatsapp:route] dropped reason=no-text-on-native-channel senderId=${msg.senderPhone} media=${msg.mediaType ?? "none"}`);
|
|
16874
|
+
return;
|
|
16875
|
+
}
|
|
16876
|
+
try {
|
|
16877
|
+
void msg.composing().catch(() => {
|
|
16878
|
+
});
|
|
16879
|
+
await waGateway.handleInbound({
|
|
16880
|
+
accountId: msg.accountId,
|
|
16881
|
+
senderId: msg.senderPhone,
|
|
16882
|
+
text: msg.text,
|
|
16883
|
+
reply: msg.reply
|
|
16884
|
+
});
|
|
16885
|
+
} catch (err) {
|
|
16886
|
+
console.error(
|
|
16887
|
+
`[whatsapp-native] reject senderId=${msg.senderPhone} message=${err instanceof Error ? err.message : String(err)}`
|
|
16888
|
+
);
|
|
16889
|
+
}
|
|
17067
16890
|
}
|
|
17068
16891
|
}).catch((err) => {
|
|
17069
16892
|
console.error(`[whatsapp] init failed: ${String(err)}`);
|
|
17070
16893
|
});
|
|
16894
|
+
startReaper2();
|
|
17071
16895
|
var shuttingDown = false;
|
|
17072
16896
|
process.on("SIGTERM", async () => {
|
|
17073
16897
|
if (shuttingDown) {
|