@rubytech/create-maxy-code 0.1.274 → 0.1.275
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/hooks/pin-identity-gate.sh +2 -2
- 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/server/server.js +170 -253
package/payload/server/server.js
CHANGED
|
@@ -5526,21 +5526,6 @@ function handlePublicSessionExit(sessionId) {
|
|
|
5526
5526
|
});
|
|
5527
5527
|
}
|
|
5528
5528
|
|
|
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
5529
|
// app/lib/access-session-store.ts
|
|
5545
5530
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
5546
5531
|
var sessions = /* @__PURE__ */ new Map();
|
|
@@ -5816,7 +5801,7 @@ import { randomUUID as randomUUID6 } from "crypto";
|
|
|
5816
5801
|
// app/lib/whatsapp/config-persist.ts
|
|
5817
5802
|
import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync3 } from "fs";
|
|
5818
5803
|
import { resolve as resolve6, join as join4 } from "path";
|
|
5819
|
-
var
|
|
5804
|
+
var TAG17 = "[whatsapp:config]";
|
|
5820
5805
|
function configPath(accountDir) {
|
|
5821
5806
|
return resolve6(accountDir, "account.json");
|
|
5822
5807
|
}
|
|
@@ -5833,9 +5818,9 @@ function reloadManagerConfig(accountDir) {
|
|
|
5833
5818
|
try {
|
|
5834
5819
|
const config = readConfig(accountDir);
|
|
5835
5820
|
reloadConfig(config);
|
|
5836
|
-
console.error(`${
|
|
5821
|
+
console.error(`${TAG17} reloaded manager config`);
|
|
5837
5822
|
} catch (err) {
|
|
5838
|
-
console.error(`${
|
|
5823
|
+
console.error(`${TAG17} manager config reload failed: ${String(err)}`);
|
|
5839
5824
|
}
|
|
5840
5825
|
}
|
|
5841
5826
|
var E164_PATTERN = /^\+\d{7,15}$/;
|
|
@@ -5861,25 +5846,25 @@ function persistAfterPairing(accountDir, accountId, selfPhone) {
|
|
|
5861
5846
|
const adminPhones = wa.adminPhones;
|
|
5862
5847
|
if (!adminPhones.includes(normalized)) {
|
|
5863
5848
|
adminPhones.push(normalized);
|
|
5864
|
-
console.error(`${
|
|
5849
|
+
console.error(`${TAG17} added selfPhone=${normalized} to adminPhones`);
|
|
5865
5850
|
}
|
|
5866
5851
|
} else {
|
|
5867
|
-
console.error(`${
|
|
5852
|
+
console.error(`${TAG17} skipping adminPhones \u2014 selfPhone is null account=${accountId}`);
|
|
5868
5853
|
}
|
|
5869
5854
|
const parsed = WhatsAppConfigSchema.safeParse(wa);
|
|
5870
5855
|
if (!parsed.success) {
|
|
5871
5856
|
const msg = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
|
|
5872
|
-
console.error(`${
|
|
5857
|
+
console.error(`${TAG17} validation failed after pairing: ${msg}`);
|
|
5873
5858
|
return { ok: false, error: `Validation failed: ${msg}` };
|
|
5874
5859
|
}
|
|
5875
5860
|
config.whatsapp = parsed.data;
|
|
5876
5861
|
writeConfig(accountDir, config);
|
|
5877
|
-
console.error(`${
|
|
5862
|
+
console.error(`${TAG17} persisted after pairing account=${accountId} phone=${selfPhone ?? "null"}`);
|
|
5878
5863
|
reloadManagerConfig(accountDir);
|
|
5879
5864
|
return { ok: true };
|
|
5880
5865
|
} catch (err) {
|
|
5881
5866
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5882
|
-
console.error(`${
|
|
5867
|
+
console.error(`${TAG17} persist failed account=${accountId}: ${msg}`);
|
|
5883
5868
|
return { ok: false, error: msg };
|
|
5884
5869
|
}
|
|
5885
5870
|
}
|
|
@@ -5909,12 +5894,12 @@ function addAdminPhone(accountDir, phone) {
|
|
|
5909
5894
|
}
|
|
5910
5895
|
config.whatsapp = parsed.data;
|
|
5911
5896
|
writeConfig(accountDir, config);
|
|
5912
|
-
console.error(`${
|
|
5897
|
+
console.error(`${TAG17} added admin phone=${normalized}`);
|
|
5913
5898
|
reloadManagerConfig(accountDir);
|
|
5914
5899
|
return { ok: true, message: `Added ${normalized} as admin phone. Messages from this number will route to the admin agent.` };
|
|
5915
5900
|
} catch (err) {
|
|
5916
5901
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5917
|
-
console.error(`${
|
|
5902
|
+
console.error(`${TAG17} addAdminPhone failed: ${msg}`);
|
|
5918
5903
|
return { ok: false, error: msg };
|
|
5919
5904
|
}
|
|
5920
5905
|
}
|
|
@@ -5942,12 +5927,12 @@ function removeAdminPhone(accountDir, phone) {
|
|
|
5942
5927
|
}
|
|
5943
5928
|
config.whatsapp = parsed.data;
|
|
5944
5929
|
writeConfig(accountDir, config);
|
|
5945
|
-
console.error(`${
|
|
5930
|
+
console.error(`${TAG17} removed admin phone=${normalized}`);
|
|
5946
5931
|
reloadManagerConfig(accountDir);
|
|
5947
5932
|
return { ok: true, message: `Removed ${normalized} from admin phones. Messages from this number will now route to the public agent.` };
|
|
5948
5933
|
} catch (err) {
|
|
5949
5934
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5950
|
-
console.error(`${
|
|
5935
|
+
console.error(`${TAG17} removeAdminPhone failed: ${msg}`);
|
|
5951
5936
|
return { ok: false, error: msg };
|
|
5952
5937
|
}
|
|
5953
5938
|
}
|
|
@@ -5985,12 +5970,12 @@ function setPublicAgent(accountDir, slug) {
|
|
|
5985
5970
|
}
|
|
5986
5971
|
config.whatsapp = parsed.data;
|
|
5987
5972
|
writeConfig(accountDir, config);
|
|
5988
|
-
console.error(`${
|
|
5973
|
+
console.error(`${TAG17} publicAgent set to ${trimmed}`);
|
|
5989
5974
|
reloadManagerConfig(accountDir);
|
|
5990
5975
|
return { ok: true, message: `Public agent set to "${trimmed}". WhatsApp messages from non-admin phones will be handled by this agent.` };
|
|
5991
5976
|
} catch (err) {
|
|
5992
5977
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5993
|
-
console.error(`${
|
|
5978
|
+
console.error(`${TAG17} setPublicAgent failed: ${msg}`);
|
|
5994
5979
|
return { ok: false, error: msg };
|
|
5995
5980
|
}
|
|
5996
5981
|
}
|
|
@@ -6054,12 +6039,12 @@ function setGroupPublicAgent(accountDir, accountId, groupJid, slug) {
|
|
|
6054
6039
|
}
|
|
6055
6040
|
config.whatsapp = parsed.data;
|
|
6056
6041
|
writeConfig(accountDir, config);
|
|
6057
|
-
console.error(`${
|
|
6042
|
+
console.error(`${TAG17} setGroupPublicAgent account=${trimmedAccount} groupJid=${trimmedGroup} slug=${trimmedSlug}`);
|
|
6058
6043
|
reloadManagerConfig(accountDir);
|
|
6059
6044
|
return { ok: true, message: `Per-group public agent set to "${trimmedSlug}" for group ${trimmedGroup}.` };
|
|
6060
6045
|
} catch (err) {
|
|
6061
6046
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6062
|
-
console.error(`${
|
|
6047
|
+
console.error(`${TAG17} setGroupPublicAgent failed: ${msg}`);
|
|
6063
6048
|
return { ok: false, error: msg };
|
|
6064
6049
|
}
|
|
6065
6050
|
}
|
|
@@ -6086,12 +6071,12 @@ function unsetGroupPublicAgent(accountDir, accountId, groupJid) {
|
|
|
6086
6071
|
}
|
|
6087
6072
|
config.whatsapp = parsed.data;
|
|
6088
6073
|
writeConfig(accountDir, config);
|
|
6089
|
-
console.error(`${
|
|
6074
|
+
console.error(`${TAG17} unsetGroupPublicAgent account=${trimmedAccount} groupJid=${trimmedGroup}`);
|
|
6090
6075
|
reloadManagerConfig(accountDir);
|
|
6091
6076
|
return { ok: true, message: `Per-group public agent override removed for group ${trimmedGroup}.` };
|
|
6092
6077
|
} catch (err) {
|
|
6093
6078
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6094
|
-
console.error(`${
|
|
6079
|
+
console.error(`${TAG17} unsetGroupPublicAgent failed: ${msg}`);
|
|
6095
6080
|
return { ok: false, error: msg };
|
|
6096
6081
|
}
|
|
6097
6082
|
}
|
|
@@ -6112,17 +6097,17 @@ function updateConfig(accountDir, fields) {
|
|
|
6112
6097
|
const parsed = WhatsAppConfigSchema.safeParse(wa);
|
|
6113
6098
|
if (!parsed.success) {
|
|
6114
6099
|
const msg = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
|
|
6115
|
-
console.error(`${
|
|
6100
|
+
console.error(`${TAG17} update validation failed: ${msg}`);
|
|
6116
6101
|
return { ok: false, error: `Validation failed: ${msg}` };
|
|
6117
6102
|
}
|
|
6118
6103
|
config.whatsapp = parsed.data;
|
|
6119
6104
|
writeConfig(accountDir, config);
|
|
6120
|
-
console.error(`${
|
|
6105
|
+
console.error(`${TAG17} updated fields=[${fieldNames.join(",")}]`);
|
|
6121
6106
|
reloadManagerConfig(accountDir);
|
|
6122
6107
|
return { ok: true, message: `Updated WhatsApp config: ${fieldNames.join(", ")}.` };
|
|
6123
6108
|
} catch (err) {
|
|
6124
6109
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6125
|
-
console.error(`${
|
|
6110
|
+
console.error(`${TAG17} updateConfig failed: ${msg}`);
|
|
6126
6111
|
return { ok: false, error: msg };
|
|
6127
6112
|
}
|
|
6128
6113
|
}
|
|
@@ -6140,7 +6125,7 @@ function getConfig(accountDir) {
|
|
|
6140
6125
|
}
|
|
6141
6126
|
|
|
6142
6127
|
// app/lib/whatsapp/login.ts
|
|
6143
|
-
var
|
|
6128
|
+
var TAG18 = "[whatsapp:login]";
|
|
6144
6129
|
function maskPhone(digits) {
|
|
6145
6130
|
if (digits.length <= 4) return "*".repeat(digits.length);
|
|
6146
6131
|
return digits.slice(0, 2) + "*".repeat(digits.length - 4) + digits.slice(-2);
|
|
@@ -6151,7 +6136,7 @@ function closeSocket(sock) {
|
|
|
6151
6136
|
try {
|
|
6152
6137
|
sock.ws?.close?.();
|
|
6153
6138
|
} catch (err) {
|
|
6154
|
-
console.warn(`${
|
|
6139
|
+
console.warn(`${TAG18} socket close error during cleanup: ${String(err)}`);
|
|
6155
6140
|
}
|
|
6156
6141
|
}
|
|
6157
6142
|
function resetActiveLogin(accountId) {
|
|
@@ -6178,18 +6163,18 @@ async function runPostPairing(login) {
|
|
|
6178
6163
|
const masked = selfPhone ? `${selfPhone.slice(0, 4)}***` : "null";
|
|
6179
6164
|
console.error(`[whatsapp-persist] wa-persist-on-connect account=${login.accountId} phone=${masked}`);
|
|
6180
6165
|
} else {
|
|
6181
|
-
console.error(`${
|
|
6166
|
+
console.error(`${TAG18} wa-persist-on-connect FAILED account=${login.accountId}: ${result.error}`);
|
|
6182
6167
|
}
|
|
6183
6168
|
} catch (err) {
|
|
6184
|
-
console.error(`${
|
|
6169
|
+
console.error(`${TAG18} wa-persist-on-connect error account=${login.accountId}: ${String(err)}`);
|
|
6185
6170
|
}
|
|
6186
6171
|
} else {
|
|
6187
|
-
console.error(`${
|
|
6172
|
+
console.error(`${TAG18} wa-persist-on-connect skipped \u2014 no accountDir account=${login.accountId}`);
|
|
6188
6173
|
}
|
|
6189
6174
|
try {
|
|
6190
6175
|
await registerLoginSocket(login.accountId, login.sock, login.authDir);
|
|
6191
6176
|
} catch (err) {
|
|
6192
|
-
console.error(`${
|
|
6177
|
+
console.error(`${TAG18} registerLoginSocket failed account=${login.accountId}: ${String(err)}`);
|
|
6193
6178
|
}
|
|
6194
6179
|
}
|
|
6195
6180
|
async function loginConnectionLoop(accountId, login) {
|
|
@@ -6201,7 +6186,7 @@ async function loginConnectionLoop(accountId, login) {
|
|
|
6201
6186
|
if (current?.id === login.id) {
|
|
6202
6187
|
await runPostPairing(current);
|
|
6203
6188
|
current.connected = true;
|
|
6204
|
-
console.error(`${
|
|
6189
|
+
console.error(`${TAG18} loginConnectionLoop: connected account=${accountId} attempt=${attempt} configPersisted=${current.configPersisted}`);
|
|
6205
6190
|
}
|
|
6206
6191
|
return;
|
|
6207
6192
|
} catch (err) {
|
|
@@ -6211,7 +6196,7 @@ async function loginConnectionLoop(accountId, login) {
|
|
|
6211
6196
|
if (!classification.shouldRetry || attempt >= LOGIN_MAX_RECONNECTS) {
|
|
6212
6197
|
if (attempt >= LOGIN_MAX_RECONNECTS) {
|
|
6213
6198
|
console.error(
|
|
6214
|
-
`${
|
|
6199
|
+
`${TAG18} login reconnect attempts exhausted (${attempt}/${LOGIN_MAX_RECONNECTS}) \u2014 surfacing error to agent`
|
|
6215
6200
|
);
|
|
6216
6201
|
current.error = `Login failed after ${attempt} reconnect attempts: ${formatError(err)}`;
|
|
6217
6202
|
} else {
|
|
@@ -6223,7 +6208,7 @@ async function loginConnectionLoop(accountId, login) {
|
|
|
6223
6208
|
attempt++;
|
|
6224
6209
|
const delay = LOGIN_RECONNECT_DELAYS[attempt - 1] ?? 8e3;
|
|
6225
6210
|
console.error(
|
|
6226
|
-
`${
|
|
6211
|
+
`${TAG18} status=${classification.statusCode ?? "unknown"} restart required \u2014 reconnecting with saved creds (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}) delay=${delay}ms`
|
|
6227
6212
|
);
|
|
6228
6213
|
closeSocket(current.sock);
|
|
6229
6214
|
await new Promise((r) => setTimeout(r, delay));
|
|
@@ -6234,7 +6219,7 @@ async function loginConnectionLoop(accountId, login) {
|
|
|
6234
6219
|
current.sock = newSock;
|
|
6235
6220
|
} catch (sockErr) {
|
|
6236
6221
|
console.error(
|
|
6237
|
-
`${
|
|
6222
|
+
`${TAG18} reconnect socket creation failed (attempt ${attempt}/${LOGIN_MAX_RECONNECTS}): ${String(sockErr)}`
|
|
6238
6223
|
);
|
|
6239
6224
|
current.error = `Reconnection failed: ${String(sockErr)}`;
|
|
6240
6225
|
return;
|
|
@@ -6248,7 +6233,7 @@ async function startLogin(opts) {
|
|
|
6248
6233
|
const hasAuth = await authExists(authDir);
|
|
6249
6234
|
const selfId = readSelfId(authDir);
|
|
6250
6235
|
console.error(
|
|
6251
|
-
`${
|
|
6236
|
+
`${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
6237
|
);
|
|
6253
6238
|
if (hasAuth && !force) {
|
|
6254
6239
|
const who = selfId.e164 ?? selfId.jid ?? "unknown";
|
|
@@ -6263,7 +6248,7 @@ async function startLogin(opts) {
|
|
|
6263
6248
|
}
|
|
6264
6249
|
const existing = activeLogins.get(accountId);
|
|
6265
6250
|
if (existing && isLoginFresh(existing) && existing.pairingCode && !force) {
|
|
6266
|
-
console.error(`${
|
|
6251
|
+
console.error(`${TAG18} startLogin account=${accountId} guard: returning existing pairing code (age=${Math.round((Date.now() - existing.startedAt) / 1e3)}s)`);
|
|
6267
6252
|
return {
|
|
6268
6253
|
pairingCode: existing.pairingCode,
|
|
6269
6254
|
phone: existing.phone,
|
|
@@ -6271,7 +6256,7 @@ async function startLogin(opts) {
|
|
|
6271
6256
|
};
|
|
6272
6257
|
}
|
|
6273
6258
|
if (existing) {
|
|
6274
|
-
console.error(`${
|
|
6259
|
+
console.error(`${TAG18} startLogin account=${accountId} ${force ? "force override" : "stale/no-code"}, resetting active login`);
|
|
6275
6260
|
}
|
|
6276
6261
|
resetActiveLogin(accountId);
|
|
6277
6262
|
await clearAuth(authDir);
|
|
@@ -6301,7 +6286,7 @@ async function startLogin(opts) {
|
|
|
6301
6286
|
const current = activeLogins.get(accountId);
|
|
6302
6287
|
if (current?.id !== login.id) return;
|
|
6303
6288
|
if (!current.pairingCode) current.pairingCode = code;
|
|
6304
|
-
console.error(`${
|
|
6289
|
+
console.error(`${TAG18} pairing-code-issued account=${accountId} phone=${maskPhone(digits)} codeLen=${code.length}`);
|
|
6305
6290
|
resolveCode?.(code);
|
|
6306
6291
|
}).catch((err) => {
|
|
6307
6292
|
clearTimeout(codeTimer);
|
|
@@ -6330,7 +6315,7 @@ async function startLogin(opts) {
|
|
|
6330
6315
|
const ttlTimer = setTimeout(() => {
|
|
6331
6316
|
const current = activeLogins.get(accountId);
|
|
6332
6317
|
if (current?.id === login.id && !current.connected) {
|
|
6333
|
-
console.error(`${
|
|
6318
|
+
console.error(`${TAG18} pairing-window-elapsed account=${accountId} (ttl sweep)`);
|
|
6334
6319
|
resetActiveLogin(accountId);
|
|
6335
6320
|
}
|
|
6336
6321
|
}, ACTIVE_LOGIN_TTL_MS);
|
|
@@ -6338,7 +6323,7 @@ async function startLogin(opts) {
|
|
|
6338
6323
|
ttlTimer.unref();
|
|
6339
6324
|
}
|
|
6340
6325
|
loginConnectionLoop(accountId, login).catch((err) => {
|
|
6341
|
-
console.error(`${
|
|
6326
|
+
console.error(`${TAG18} loginConnectionLoop unexpected error: ${String(err)}`);
|
|
6342
6327
|
const current = activeLogins.get(accountId);
|
|
6343
6328
|
if (current?.id === login.id) {
|
|
6344
6329
|
current.error = `Unexpected login error: ${String(err)}`;
|
|
@@ -6363,13 +6348,13 @@ async function waitForLogin(opts) {
|
|
|
6363
6348
|
const { accountId, timeoutMs = 6e4 } = opts;
|
|
6364
6349
|
const login = activeLogins.get(accountId);
|
|
6365
6350
|
console.error(
|
|
6366
|
-
`${
|
|
6351
|
+
`${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
6352
|
);
|
|
6368
6353
|
if (!login) {
|
|
6369
6354
|
return { connected: false, message: "No active WhatsApp login in progress.", configPersisted: false };
|
|
6370
6355
|
}
|
|
6371
6356
|
if (!isLoginFresh(login)) {
|
|
6372
|
-
console.error(`${
|
|
6357
|
+
console.error(`${TAG18} pairing-window-elapsed account=${accountId}`);
|
|
6373
6358
|
resetActiveLogin(accountId);
|
|
6374
6359
|
return { connected: false, message: "The pairing window expired. Ask me to generate a new code.", configPersisted: false };
|
|
6375
6360
|
}
|
|
@@ -6377,8 +6362,8 @@ async function waitForLogin(opts) {
|
|
|
6377
6362
|
while (Date.now() < deadline) {
|
|
6378
6363
|
if (login.connected) {
|
|
6379
6364
|
const selfId = readSelfId(login.authDir);
|
|
6380
|
-
console.error(`${
|
|
6381
|
-
console.error(`${
|
|
6365
|
+
console.error(`${TAG18} pairing-connected account=${accountId} phone=${selfId.e164 ?? "unknown"}`);
|
|
6366
|
+
console.error(`${TAG18} login complete for account=${accountId} phone=${selfId.e164 ?? "unknown"} configPersisted=${login.configPersisted}`);
|
|
6382
6367
|
const configPersisted = login.configPersisted;
|
|
6383
6368
|
activeLogins.delete(accountId);
|
|
6384
6369
|
return {
|
|
@@ -6396,7 +6381,7 @@ async function waitForLogin(opts) {
|
|
|
6396
6381
|
await new Promise((r) => setTimeout(r, 1e3));
|
|
6397
6382
|
}
|
|
6398
6383
|
const elapsed = Math.round((Date.now() - (deadline - timeoutMs)) / 1e3);
|
|
6399
|
-
console.error(`${
|
|
6384
|
+
console.error(`${TAG18} waitForLogin poll timeout account=${accountId} elapsed=${elapsed}s \u2014 login kept alive (pairing code still valid)`);
|
|
6400
6385
|
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
6386
|
}
|
|
6402
6387
|
|
|
@@ -6511,7 +6496,7 @@ function serializeWhatsAppSchema() {
|
|
|
6511
6496
|
// app/lib/whatsapp/status-reconcile.ts
|
|
6512
6497
|
import { readdirSync as readdirSync2 } from "fs";
|
|
6513
6498
|
import { join as join5 } from "path";
|
|
6514
|
-
var
|
|
6499
|
+
var TAG19 = "[whatsapp:reconcile]";
|
|
6515
6500
|
function listCredsAccountIds(credsRoot) {
|
|
6516
6501
|
try {
|
|
6517
6502
|
return readdirSync2(credsRoot, { withFileTypes: true }).filter((e) => e.isDirectory() && hasCredsSync(join5(credsRoot, e.name))).map((e) => e.name);
|
|
@@ -6533,14 +6518,14 @@ function reconcileCredsOnDisk(opts) {
|
|
|
6533
6518
|
const selfPhone = readSelfId(authDir).e164 ?? void 0;
|
|
6534
6519
|
const configured = accountDir ? isAccountConfigured(accountDir, accountId) : false;
|
|
6535
6520
|
console.error(
|
|
6536
|
-
`${
|
|
6521
|
+
`${TAG19} wa-link-unconfigured account=${accountId} creds=present config=${configured ? "present" : "absent"}`
|
|
6537
6522
|
);
|
|
6538
6523
|
if (!configured && accountDir) {
|
|
6539
6524
|
const result = persistAfterPairing(accountDir, accountId, selfPhone ?? null);
|
|
6540
6525
|
if (result.ok) {
|
|
6541
|
-
console.error(`${
|
|
6526
|
+
console.error(`${TAG19} self-healed account=${accountId}`);
|
|
6542
6527
|
} else {
|
|
6543
|
-
console.error(`${
|
|
6528
|
+
console.error(`${TAG19} self-heal FAILED account=${accountId}: ${result.error}`);
|
|
6544
6529
|
}
|
|
6545
6530
|
}
|
|
6546
6531
|
entries.push({ accountId, selfPhone, connected: false, linkedUnconfigured: !configured });
|
|
@@ -6549,7 +6534,7 @@ function reconcileCredsOnDisk(opts) {
|
|
|
6549
6534
|
}
|
|
6550
6535
|
|
|
6551
6536
|
// server/routes/whatsapp.ts
|
|
6552
|
-
var
|
|
6537
|
+
var TAG20 = "[whatsapp:api]";
|
|
6553
6538
|
var PLATFORM_ROOT4 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
6554
6539
|
var app3 = new Hono();
|
|
6555
6540
|
app3.get("/status", (c) => {
|
|
@@ -6561,10 +6546,10 @@ app3.get("/status", (c) => {
|
|
|
6561
6546
|
const reconciled = reconcileCredsOnDisk({ credsRoot, accountDir, liveAccountIds: liveIds });
|
|
6562
6547
|
const accounts = [...live, ...reconciled];
|
|
6563
6548
|
const summary = accounts.map((a) => `${a.accountId}:${a.connected ? "up" : a.linkedUnconfigured ? "linked-unconfigured" : "down"}`).join(", ");
|
|
6564
|
-
console.error(`${
|
|
6549
|
+
console.error(`${TAG20} status accounts=${accounts.length} [${summary}]`);
|
|
6565
6550
|
return c.json({ accounts });
|
|
6566
6551
|
} catch (err) {
|
|
6567
|
-
console.error(`${
|
|
6552
|
+
console.error(`${TAG20} status error: ${String(err)}`);
|
|
6568
6553
|
return c.json({ error: String(err) }, 500);
|
|
6569
6554
|
}
|
|
6570
6555
|
});
|
|
@@ -6580,10 +6565,10 @@ app3.post("/login/start", async (c) => {
|
|
|
6580
6565
|
const authDir = join6(MAXY_DIR, "credentials", "whatsapp", accountId);
|
|
6581
6566
|
const accountDir = resolveAccount()?.accountDir ?? null;
|
|
6582
6567
|
const result = await startLogin({ accountId, authDir, phone, accountDir, force });
|
|
6583
|
-
console.error(`${
|
|
6568
|
+
console.error(`${TAG20} login/start result account=${accountId} hasCode=${!!result.pairingCode}${result.selfPhone ? ` phone=${result.selfPhone}` : ""}`);
|
|
6584
6569
|
return c.json(result);
|
|
6585
6570
|
} catch (err) {
|
|
6586
|
-
console.error(`${
|
|
6571
|
+
console.error(`${TAG20} login/start error: ${String(err)}`);
|
|
6587
6572
|
return c.json({ error: String(err) }, 500);
|
|
6588
6573
|
}
|
|
6589
6574
|
});
|
|
@@ -6593,7 +6578,7 @@ app3.post("/login/wait", async (c) => {
|
|
|
6593
6578
|
const accountId = validateAccountId(body.accountId);
|
|
6594
6579
|
const timeoutMs = body.timeoutMs ?? 6e4;
|
|
6595
6580
|
const result = await waitForLogin({ accountId, timeoutMs });
|
|
6596
|
-
console.error(`${
|
|
6581
|
+
console.error(`${TAG20} login/wait result account=${accountId} connected=${result.connected}${result.selfPhone ? ` phone=${result.selfPhone}` : ""} configPersisted=${result.configPersisted}`);
|
|
6597
6582
|
return c.json({
|
|
6598
6583
|
connected: result.connected,
|
|
6599
6584
|
message: result.message,
|
|
@@ -6601,7 +6586,7 @@ app3.post("/login/wait", async (c) => {
|
|
|
6601
6586
|
configPersisted: result.configPersisted
|
|
6602
6587
|
});
|
|
6603
6588
|
} catch (err) {
|
|
6604
|
-
console.error(`${
|
|
6589
|
+
console.error(`${TAG20} login/wait error: ${String(err)}`);
|
|
6605
6590
|
return c.json({ error: String(err) }, 500);
|
|
6606
6591
|
}
|
|
6607
6592
|
});
|
|
@@ -6612,7 +6597,7 @@ app3.post("/disconnect", async (c) => {
|
|
|
6612
6597
|
await stopConnection(accountId);
|
|
6613
6598
|
return c.json({ disconnected: true, accountId });
|
|
6614
6599
|
} catch (err) {
|
|
6615
|
-
console.error(`${
|
|
6600
|
+
console.error(`${TAG20} disconnect error: ${String(err)}`);
|
|
6616
6601
|
return c.json({ error: String(err) }, 500);
|
|
6617
6602
|
}
|
|
6618
6603
|
});
|
|
@@ -6623,7 +6608,7 @@ app3.post("/reconnect", async (c) => {
|
|
|
6623
6608
|
await startConnection(accountId);
|
|
6624
6609
|
return c.json({ reconnecting: true, accountId });
|
|
6625
6610
|
} catch (err) {
|
|
6626
|
-
console.error(`${
|
|
6611
|
+
console.error(`${TAG20} reconnect error: ${String(err)}`);
|
|
6627
6612
|
return c.json({ error: String(err) }, 500);
|
|
6628
6613
|
}
|
|
6629
6614
|
});
|
|
@@ -6642,7 +6627,7 @@ app3.post("/send", async (c) => {
|
|
|
6642
6627
|
const result = await sendTextMessage(sock, to, text, { accountId });
|
|
6643
6628
|
return c.json(result);
|
|
6644
6629
|
} catch (err) {
|
|
6645
|
-
console.error(`${
|
|
6630
|
+
console.error(`${TAG20} send error: ${String(err)}`);
|
|
6646
6631
|
return c.json({ error: String(err) }, 500);
|
|
6647
6632
|
}
|
|
6648
6633
|
});
|
|
@@ -6663,7 +6648,7 @@ app3.post("/config", async (c) => {
|
|
|
6663
6648
|
return c.json({ ok: false, error: 'Missing required field "phone" (E.164 format, e.g. +441234567890).' }, 400);
|
|
6664
6649
|
}
|
|
6665
6650
|
const result = addAdminPhone(account.accountDir, phone);
|
|
6666
|
-
console.error(`${
|
|
6651
|
+
console.error(`${TAG20} config action=add-admin-phone phone=${phone} ok=${result.ok}`);
|
|
6667
6652
|
return c.json(result, result.ok ? 200 : 400);
|
|
6668
6653
|
}
|
|
6669
6654
|
case "remove-admin-phone": {
|
|
@@ -6671,12 +6656,12 @@ app3.post("/config", async (c) => {
|
|
|
6671
6656
|
return c.json({ ok: false, error: 'Missing required field "phone".' }, 400);
|
|
6672
6657
|
}
|
|
6673
6658
|
const result = removeAdminPhone(account.accountDir, phone);
|
|
6674
|
-
console.error(`${
|
|
6659
|
+
console.error(`${TAG20} config action=remove-admin-phone phone=${phone} ok=${result.ok}`);
|
|
6675
6660
|
return c.json(result, result.ok ? 200 : 400);
|
|
6676
6661
|
}
|
|
6677
6662
|
case "list-admin-phones": {
|
|
6678
6663
|
const phones = readAdminPhones(account.accountDir);
|
|
6679
|
-
console.error(`${
|
|
6664
|
+
console.error(`${TAG20} config action=list-admin-phones count=${phones.length}`);
|
|
6680
6665
|
return c.json({ ok: true, phones });
|
|
6681
6666
|
}
|
|
6682
6667
|
case "set-public-agent": {
|
|
@@ -6684,14 +6669,14 @@ app3.post("/config", async (c) => {
|
|
|
6684
6669
|
return c.json({ ok: false, error: 'Missing required field "slug" (the agent directory name, e.g. "my-agent").' }, 400);
|
|
6685
6670
|
}
|
|
6686
6671
|
const result = setPublicAgent(account.accountDir, slug);
|
|
6687
|
-
console.error(`${
|
|
6672
|
+
console.error(`${TAG20} config action=set-public-agent slug=${slug} ok=${result.ok}`);
|
|
6688
6673
|
return c.json(result, result.ok ? 200 : 400);
|
|
6689
6674
|
}
|
|
6690
6675
|
case "get-public-agent": {
|
|
6691
6676
|
const targetAccount = typeof accountId === "string" && accountId.trim() ? accountId.trim() : "default";
|
|
6692
6677
|
const targetGroup = typeof groupJid === "string" && groupJid.trim() ? groupJid.trim() : void 0;
|
|
6693
6678
|
const resolved = resolvePublicAgent(account.accountDir, { accountId: targetAccount, groupJid: targetGroup });
|
|
6694
|
-
console.error(`${
|
|
6679
|
+
console.error(`${TAG20} config action=get-public-agent accountId=${targetAccount} groupJid=${targetGroup ?? "none"} slug=${resolved?.slug ?? "none"} source=${resolved?.source ?? "none"}`);
|
|
6695
6680
|
return c.json({ ok: true, slug: resolved?.slug ?? null, source: resolved?.source ?? null });
|
|
6696
6681
|
}
|
|
6697
6682
|
case "set-group-public-agent": {
|
|
@@ -6703,7 +6688,7 @@ app3.post("/config", async (c) => {
|
|
|
6703
6688
|
}
|
|
6704
6689
|
const targetAccount = typeof accountId === "string" && accountId.trim() ? accountId.trim() : "default";
|
|
6705
6690
|
const result = setGroupPublicAgent(account.accountDir, targetAccount, groupJid, slug);
|
|
6706
|
-
console.error(`${
|
|
6691
|
+
console.error(`${TAG20} config action=set-group-public-agent accountId=${targetAccount} groupJid=${groupJid} slug=${slug} ok=${result.ok}`);
|
|
6707
6692
|
return c.json(result, result.ok ? 200 : 400);
|
|
6708
6693
|
}
|
|
6709
6694
|
case "unset-group-public-agent": {
|
|
@@ -6712,7 +6697,7 @@ app3.post("/config", async (c) => {
|
|
|
6712
6697
|
}
|
|
6713
6698
|
const targetAccount = typeof accountId === "string" && accountId.trim() ? accountId.trim() : "default";
|
|
6714
6699
|
const result = unsetGroupPublicAgent(account.accountDir, targetAccount, groupJid);
|
|
6715
|
-
console.error(`${
|
|
6700
|
+
console.error(`${TAG20} config action=unset-group-public-agent accountId=${targetAccount} groupJid=${groupJid} ok=${result.ok}`);
|
|
6716
6701
|
return c.json(result, result.ok ? 200 : 400);
|
|
6717
6702
|
}
|
|
6718
6703
|
case "list-public-agents": {
|
|
@@ -6729,26 +6714,26 @@ app3.post("/config", async (c) => {
|
|
|
6729
6714
|
const config = JSON.parse(readFileSync6(configPath2, "utf-8"));
|
|
6730
6715
|
agents.push({ slug: entry.name, displayName: config.displayName ?? entry.name });
|
|
6731
6716
|
} catch {
|
|
6732
|
-
console.error(`${
|
|
6717
|
+
console.error(`${TAG20} config action=list-public-agents error="failed to parse config.json for agent ${entry.name}" \u2014 skipping`);
|
|
6733
6718
|
}
|
|
6734
6719
|
}
|
|
6735
6720
|
} catch (err) {
|
|
6736
|
-
console.error(`${
|
|
6721
|
+
console.error(`${TAG20} config action=list-public-agents error="failed to scan agents directory: ${String(err)}"`);
|
|
6737
6722
|
}
|
|
6738
6723
|
}
|
|
6739
|
-
console.error(`${
|
|
6724
|
+
console.error(`${TAG20} config action=list-public-agents count=${agents.length}`);
|
|
6740
6725
|
return c.json({ ok: true, agents });
|
|
6741
6726
|
}
|
|
6742
6727
|
case "schema": {
|
|
6743
6728
|
const text = serializeWhatsAppSchema();
|
|
6744
|
-
console.error(`${
|
|
6729
|
+
console.error(`${TAG20} config action=schema`);
|
|
6745
6730
|
return c.json({ ok: true, text });
|
|
6746
6731
|
}
|
|
6747
6732
|
case "list-groups": {
|
|
6748
6733
|
const groupAccountId = accountId ?? "default";
|
|
6749
6734
|
const sock = getSocket(groupAccountId);
|
|
6750
6735
|
if (!sock) {
|
|
6751
|
-
console.error(`${
|
|
6736
|
+
console.error(`${TAG20} config action=list-groups error="not connected" accountId=${groupAccountId}`);
|
|
6752
6737
|
return c.json({ ok: false, error: `WhatsApp account "${groupAccountId}" is not connected. Connect first, then retry.` });
|
|
6753
6738
|
}
|
|
6754
6739
|
try {
|
|
@@ -6758,10 +6743,10 @@ app3.post("/config", async (c) => {
|
|
|
6758
6743
|
name: g.subject ?? g.id,
|
|
6759
6744
|
participantCount: Array.isArray(g.participants) ? g.participants.length : 0
|
|
6760
6745
|
}));
|
|
6761
|
-
console.error(`${
|
|
6746
|
+
console.error(`${TAG20} config action=list-groups count=${groups.length} accountId=${groupAccountId}`);
|
|
6762
6747
|
return c.json({ ok: true, groups });
|
|
6763
6748
|
} catch (err) {
|
|
6764
|
-
console.error(`${
|
|
6749
|
+
console.error(`${TAG20} config action=list-groups error="${String(err)}" accountId=${groupAccountId}`);
|
|
6765
6750
|
return c.json({ ok: false, error: `Failed to fetch groups: ${String(err)}` });
|
|
6766
6751
|
}
|
|
6767
6752
|
}
|
|
@@ -6771,12 +6756,12 @@ app3.post("/config", async (c) => {
|
|
|
6771
6756
|
}
|
|
6772
6757
|
const result = updateConfig(account.accountDir, fields);
|
|
6773
6758
|
const fieldNames = Object.keys(fields);
|
|
6774
|
-
console.error(`${
|
|
6759
|
+
console.error(`${TAG20} config action=update-config fields=[${fieldNames.join(",")}] ok=${result.ok}`);
|
|
6775
6760
|
return c.json(result, result.ok ? 200 : 400);
|
|
6776
6761
|
}
|
|
6777
6762
|
case "get-config": {
|
|
6778
6763
|
const waConfig = getConfig(account.accountDir);
|
|
6779
|
-
console.error(`${
|
|
6764
|
+
console.error(`${TAG20} config action=get-config`);
|
|
6780
6765
|
return c.json({ ok: true, config: waConfig });
|
|
6781
6766
|
}
|
|
6782
6767
|
default:
|
|
@@ -6786,7 +6771,7 @@ app3.post("/config", async (c) => {
|
|
|
6786
6771
|
);
|
|
6787
6772
|
}
|
|
6788
6773
|
} catch (err) {
|
|
6789
|
-
console.error(`${
|
|
6774
|
+
console.error(`${TAG20} config error: ${String(err)}`);
|
|
6790
6775
|
return c.json({ ok: false, error: String(err) }, 500);
|
|
6791
6776
|
}
|
|
6792
6777
|
});
|
|
@@ -6807,7 +6792,7 @@ app3.post("/send-document", async (c) => {
|
|
|
6807
6792
|
recordRouteDocumentOutbound(to, filePath);
|
|
6808
6793
|
return c.json({ success: true, messageId: result.messageId });
|
|
6809
6794
|
} catch (err) {
|
|
6810
|
-
console.error(`${
|
|
6795
|
+
console.error(`${TAG20} send-document error: ${String(err)}`);
|
|
6811
6796
|
return c.json({ error: String(err) }, 500);
|
|
6812
6797
|
}
|
|
6813
6798
|
});
|
|
@@ -6817,11 +6802,11 @@ app3.get("/activity", (c) => {
|
|
|
6817
6802
|
const result = getChannelActivity(accountId);
|
|
6818
6803
|
const total = result.accounts.reduce((sum, a) => sum + a.total, 0);
|
|
6819
6804
|
console.error(
|
|
6820
|
-
`${
|
|
6805
|
+
`${TAG20} activity accounts=${result.accounts.length} total=${total} recentEvents=${result.recentEvents.length}` + (accountId ? ` filter=${accountId}` : "")
|
|
6821
6806
|
);
|
|
6822
6807
|
return c.json(result);
|
|
6823
6808
|
} catch (err) {
|
|
6824
|
-
console.error(`${
|
|
6809
|
+
console.error(`${TAG20} activity error: ${String(err)}`);
|
|
6825
6810
|
return c.json({ error: String(err) }, 500);
|
|
6826
6811
|
}
|
|
6827
6812
|
});
|
|
@@ -6840,10 +6825,10 @@ app3.get("/conversations", (c) => {
|
|
|
6840
6825
|
};
|
|
6841
6826
|
});
|
|
6842
6827
|
conversations.sort((a, b) => (b.lastMessageTimestamp ?? 0) - (a.lastMessageTimestamp ?? 0));
|
|
6843
|
-
console.error(`${
|
|
6828
|
+
console.error(`${TAG20} conversations account=${accountId} count=${conversations.length}`);
|
|
6844
6829
|
return c.json({ conversations });
|
|
6845
6830
|
} catch (err) {
|
|
6846
|
-
console.error(`${
|
|
6831
|
+
console.error(`${TAG20} conversations error: ${String(err)}`);
|
|
6847
6832
|
return c.json({ error: String(err) }, 500);
|
|
6848
6833
|
}
|
|
6849
6834
|
});
|
|
@@ -6858,10 +6843,10 @@ app3.get("/messages", (c) => {
|
|
|
6858
6843
|
const limit = limitParam ? parseInt(limitParam, 10) : void 0;
|
|
6859
6844
|
const effectiveLimit = limit && !Number.isNaN(limit) && limit > 0 ? limit : void 0;
|
|
6860
6845
|
const messages = getMessages(accountId, jid, effectiveLimit);
|
|
6861
|
-
console.error(`${
|
|
6846
|
+
console.error(`${TAG20} messages account=${accountId} jid=${jid} limit=${effectiveLimit ?? "all"} returned=${messages.length}`);
|
|
6862
6847
|
return c.json({ messages });
|
|
6863
6848
|
} catch (err) {
|
|
6864
|
-
console.error(`${
|
|
6849
|
+
console.error(`${TAG20} messages error: ${String(err)}`);
|
|
6865
6850
|
return c.json({ error: String(err) }, 500);
|
|
6866
6851
|
}
|
|
6867
6852
|
});
|
|
@@ -6942,7 +6927,7 @@ app3.get("/conversation-graph-state", async (c) => {
|
|
|
6942
6927
|
}
|
|
6943
6928
|
} catch (err) {
|
|
6944
6929
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6945
|
-
console.error(`${
|
|
6930
|
+
console.error(`${TAG20} conversation-graph-state ERR cacheKey=${cacheKey} reason=${msg}`);
|
|
6946
6931
|
return c.json({ error: `Graph query failed: ${msg}`, cacheKey, cypher: cypher.trim() }, 500);
|
|
6947
6932
|
}
|
|
6948
6933
|
const ms = Date.now() - t0;
|
|
@@ -6955,7 +6940,7 @@ app3.get("/conversation-graph-state", async (c) => {
|
|
|
6955
6940
|
ms
|
|
6956
6941
|
});
|
|
6957
6942
|
} catch (err) {
|
|
6958
|
-
console.error(`${
|
|
6943
|
+
console.error(`${TAG20} conversation-graph-state error: ${String(err)}`);
|
|
6959
6944
|
return c.json({ error: String(err) }, 500);
|
|
6960
6945
|
}
|
|
6961
6946
|
});
|
|
@@ -6967,12 +6952,12 @@ app3.get("/group-info", async (c) => {
|
|
|
6967
6952
|
return c.json({ error: "Missing required parameter: jid" }, 400);
|
|
6968
6953
|
}
|
|
6969
6954
|
if (!isGroupJid(jid)) {
|
|
6970
|
-
console.error(`${
|
|
6955
|
+
console.error(`${TAG20} group-info error="not a group JID" jid=${jid} account=${accountId}`);
|
|
6971
6956
|
return c.json({ error: `"${jid}" is not a group JID. Group JIDs end with @g.us.` }, 400);
|
|
6972
6957
|
}
|
|
6973
6958
|
const sock = getSocket(accountId);
|
|
6974
6959
|
if (!sock) {
|
|
6975
|
-
console.error(`${
|
|
6960
|
+
console.error(`${TAG20} group-info error="not connected" account=${accountId}`);
|
|
6976
6961
|
return c.json({ error: `WhatsApp account "${accountId}" is not connected. Connect first, then retry.` }, 400);
|
|
6977
6962
|
}
|
|
6978
6963
|
const meta = await sock.groupMetadata(jid);
|
|
@@ -6985,10 +6970,10 @@ app3.get("/group-info", async (c) => {
|
|
|
6985
6970
|
participantCount: meta.participants.length,
|
|
6986
6971
|
participants: meta.participants.map((p) => ({ jid: p.id, admin: p.admin ?? null }))
|
|
6987
6972
|
};
|
|
6988
|
-
console.error(`${
|
|
6973
|
+
console.error(`${TAG20} group-info jid=${jid} subject="${meta.subject}" participants=${meta.participants.length} account=${accountId}`);
|
|
6989
6974
|
return c.json(result);
|
|
6990
6975
|
} catch (err) {
|
|
6991
|
-
console.error(`${
|
|
6976
|
+
console.error(`${TAG20} group-info error="${String(err)}" jid=${jid} account=${accountId}`);
|
|
6992
6977
|
return c.json({ error: `Failed to fetch group info: ${String(err)}` }, 500);
|
|
6993
6978
|
}
|
|
6994
6979
|
});
|
|
@@ -9095,7 +9080,7 @@ function resolveTunnelUrl() {
|
|
|
9095
9080
|
if (!state) return null;
|
|
9096
9081
|
return `https://${hostname2}.${state.domain}`;
|
|
9097
9082
|
}
|
|
9098
|
-
var
|
|
9083
|
+
var TAG21 = "[claude-session-manager:wrapper]";
|
|
9099
9084
|
async function refuseIfClaudeAuthDead(c, route, sessionId) {
|
|
9100
9085
|
const auth = await ensureAuth();
|
|
9101
9086
|
if (auth.status !== "dead" && auth.status !== "missing") return null;
|
|
@@ -9117,12 +9102,12 @@ async function performSpawnWithInitialMessage(args) {
|
|
|
9117
9102
|
const aboutOwner = await resolveOwnerProfileBlock(args.senderId, args.userId);
|
|
9118
9103
|
const ownerMs = Date.now() - ownerStart;
|
|
9119
9104
|
const aboutOwnerStatus = aboutOwner == null ? "absent" : "ok" in aboutOwner && aboutOwner.ok === false ? `unresolved:${aboutOwner.reason}` : "ok";
|
|
9120
|
-
console.log(`${
|
|
9105
|
+
console.log(`${TAG21} about-owner-resolved status=${aboutOwnerStatus} ms=${ownerMs}`);
|
|
9121
9106
|
const dormantPlugins = computeDormantPlugins(args.senderId);
|
|
9122
9107
|
const activePlugins = computeActivePlugins(args.senderId);
|
|
9123
9108
|
const specialistDomains = computeSpecialistDomains(args.senderId);
|
|
9124
9109
|
const tunnelUrl = resolveTunnelUrl();
|
|
9125
|
-
console.log(`${
|
|
9110
|
+
console.log(`${TAG21} tunnel-url-resolved value=${tunnelUrl ?? "null"}`);
|
|
9126
9111
|
const upstreamPayload = JSON.stringify({
|
|
9127
9112
|
senderId: args.senderId,
|
|
9128
9113
|
// Task 205 — pass userId through to the manager so it lands as
|
|
@@ -9149,24 +9134,24 @@ async function performSpawnWithInitialMessage(args) {
|
|
|
9149
9134
|
// unshapely values.
|
|
9150
9135
|
conversationNodeId: args.conversationNodeId
|
|
9151
9136
|
});
|
|
9152
|
-
console.log(`${
|
|
9137
|
+
console.log(`${TAG21} forward-spawn-start managerBase=${managerBase3()} bytes=${upstreamPayload.length} hidden=${args.hidden} specialist=${args.specialist ?? "none"}`);
|
|
9153
9138
|
const forwardStart = Date.now();
|
|
9154
9139
|
const upstream = await fetch(`${managerBase3()}/public-spawn`, {
|
|
9155
9140
|
method: "POST",
|
|
9156
9141
|
headers: { "content-type": "application/json" },
|
|
9157
9142
|
body: upstreamPayload
|
|
9158
9143
|
}).catch((err) => {
|
|
9159
|
-
console.error(`${
|
|
9144
|
+
console.error(`${TAG21} fetch-failed op=spawn message=${err instanceof Error ? err.message : String(err)} ms=${Date.now() - forwardStart}`);
|
|
9160
9145
|
return null;
|
|
9161
9146
|
});
|
|
9162
9147
|
if (!upstream) return {
|
|
9163
9148
|
response: new Response(JSON.stringify({ error: "manager-unreachable" }), { status: 503, headers: { "content-type": "application/json" } }),
|
|
9164
9149
|
claudeSessionId: null
|
|
9165
9150
|
};
|
|
9166
|
-
console.log(`${
|
|
9151
|
+
console.log(`${TAG21} forward-spawn-done status=${upstream.status} ms=${Date.now() - forwardStart}`);
|
|
9167
9152
|
if (args.initialMessage) {
|
|
9168
9153
|
const inputBytes = Buffer.byteLength(args.initialMessage, "utf8");
|
|
9169
|
-
console.log(`${
|
|
9154
|
+
console.log(`${TAG21} initial-message-inlined bytes=${inputBytes}`);
|
|
9170
9155
|
}
|
|
9171
9156
|
const bodyText = await upstream.text().catch(() => "");
|
|
9172
9157
|
let claudeSessionId = null;
|
|
@@ -9201,7 +9186,7 @@ app12.post("/", async (c) => {
|
|
|
9201
9186
|
if (refusal) return refusal;
|
|
9202
9187
|
const senderId = getAccountIdForSession(cacheKey) ?? "";
|
|
9203
9188
|
if (!senderId) {
|
|
9204
|
-
console.error(`${
|
|
9189
|
+
console.error(`${TAG21} reject reason=no-account-id cacheKey-prefix=${cacheKey.slice(0, 8)}`);
|
|
9205
9190
|
return c.json({ error: "admin-account-not-resolved" }, 500);
|
|
9206
9191
|
}
|
|
9207
9192
|
const userId = getUserIdForSession(cacheKey) ?? void 0;
|
|
@@ -9210,7 +9195,7 @@ app12.post("/", async (c) => {
|
|
|
9210
9195
|
const permissionMode = typeof body.permissionMode === "string" ? body.permissionMode : void 0;
|
|
9211
9196
|
const specialist = typeof body.specialist === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(body.specialist) ? body.specialist : void 0;
|
|
9212
9197
|
const model = typeof body.model === "string" && /^[A-Za-z0-9._-]{1,64}$/.test(body.model) ? body.model : void 0;
|
|
9213
|
-
console.log(`${
|
|
9198
|
+
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
9199
|
const conversationNodeId = cacheKey ? getSessionIdForSession(cacheKey) : void 0;
|
|
9215
9200
|
const { response, claudeSessionId } = await performSpawnWithInitialMessage({
|
|
9216
9201
|
senderId,
|
|
@@ -9229,13 +9214,13 @@ app12.post("/", async (c) => {
|
|
|
9229
9214
|
claudeSessionId,
|
|
9230
9215
|
senderId
|
|
9231
9216
|
);
|
|
9232
|
-
console.log(`${
|
|
9217
|
+
console.log(`${TAG21} route-done surface=cookie status=${response.status} route-ms=${Date.now() - routeStart}`);
|
|
9233
9218
|
return response;
|
|
9234
9219
|
});
|
|
9235
9220
|
var claude_sessions_default = app12;
|
|
9236
9221
|
|
|
9237
9222
|
// server/routes/admin/log-ingest.ts
|
|
9238
|
-
var
|
|
9223
|
+
var TAG22 = "[log-ingest]";
|
|
9239
9224
|
var TAG_PATTERN = /^[A-Za-z0-9_:-]{1,32}$/;
|
|
9240
9225
|
var LEVELS = /* @__PURE__ */ new Set(["debug", "info", "warn", "error"]);
|
|
9241
9226
|
var MAX_LINE_BYTES = 4096;
|
|
@@ -9246,7 +9231,7 @@ function isLoopbackAddr(addr) {
|
|
|
9246
9231
|
app13.post("/", async (c) => {
|
|
9247
9232
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
9248
9233
|
if (!isLoopbackAddr(remoteAddr)) {
|
|
9249
|
-
console.error(`${
|
|
9234
|
+
console.error(`${TAG22} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
9250
9235
|
return c.json({ error: "log-ingest-loopback-only" }, 403);
|
|
9251
9236
|
}
|
|
9252
9237
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -9255,7 +9240,7 @@ app13.post("/", async (c) => {
|
|
|
9255
9240
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
9256
9241
|
const offender = tokens.find((t) => !isLoopbackAddr(t));
|
|
9257
9242
|
if (offender !== void 0) {
|
|
9258
|
-
console.error(`${
|
|
9243
|
+
console.error(`${TAG22} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
9259
9244
|
return c.json({ error: "log-ingest-loopback-only" }, 403);
|
|
9260
9245
|
}
|
|
9261
9246
|
}
|
|
@@ -9297,18 +9282,18 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
|
9297
9282
|
]);
|
|
9298
9283
|
var app14 = new Hono();
|
|
9299
9284
|
app14.post("/", async (c) => {
|
|
9300
|
-
const
|
|
9285
|
+
const TAG31 = "[admin:events]";
|
|
9301
9286
|
let body;
|
|
9302
9287
|
try {
|
|
9303
9288
|
body = await c.req.json();
|
|
9304
9289
|
} catch (err) {
|
|
9305
9290
|
const detail = err instanceof Error ? err.message : String(err);
|
|
9306
|
-
console.error(`${
|
|
9291
|
+
console.error(`${TAG31} reject reason=body-not-json detail=${detail}`);
|
|
9307
9292
|
return c.json({ ok: false, detail: "Request body was not valid JSON" }, 400);
|
|
9308
9293
|
}
|
|
9309
9294
|
const event = typeof body.event === "string" ? body.event : "";
|
|
9310
9295
|
if (!ALLOWED_EVENTS.has(event)) {
|
|
9311
|
-
console.error(`${
|
|
9296
|
+
console.error(`${TAG31} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
|
|
9312
9297
|
return c.json({ ok: false, detail: `Event "${event}" is not allowed` }, 400);
|
|
9313
9298
|
}
|
|
9314
9299
|
const rawFields = body.fields && typeof body.fields === "object" ? body.fields : {};
|
|
@@ -13345,7 +13330,7 @@ var health_default2 = app27;
|
|
|
13345
13330
|
|
|
13346
13331
|
// server/routes/admin/linkedin-ingest.ts
|
|
13347
13332
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
13348
|
-
var
|
|
13333
|
+
var TAG23 = "[linkedin-ingest-route]";
|
|
13349
13334
|
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
13335
|
var ISO = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
13351
13336
|
var LINKEDIN_URL = /^https:\/\/www\.linkedin\.com\//;
|
|
@@ -13449,29 +13434,29 @@ app28.post("/", requireAdminSession, async (c) => {
|
|
|
13449
13434
|
try {
|
|
13450
13435
|
body = await c.req.json();
|
|
13451
13436
|
} catch {
|
|
13452
|
-
console.error(
|
|
13437
|
+
console.error(TAG23 + " rejected status=400 reason=schema:body-not-json");
|
|
13453
13438
|
return c.json({ ok: false, error: "schema", reason: "body-not-json" }, 400);
|
|
13454
13439
|
}
|
|
13455
13440
|
const v = validate(body);
|
|
13456
13441
|
if (!v.ok) {
|
|
13457
|
-
console.error(
|
|
13442
|
+
console.error(TAG23 + " rejected status=" + v.status + " reason=" + v.reason + " missing=" + v.missing.join(","));
|
|
13458
13443
|
return c.json({ ok: false, error: v.error, reason: v.reason, missing: v.missing }, v.status);
|
|
13459
13444
|
}
|
|
13460
13445
|
const envelope = v.envelope;
|
|
13461
13446
|
const cacheKey = c.var.cacheKey ?? "";
|
|
13462
13447
|
const senderId = getAccountIdForSession(cacheKey) ?? "";
|
|
13463
13448
|
if (!senderId) {
|
|
13464
|
-
console.error(
|
|
13449
|
+
console.error(TAG23 + " rejected status=500 reason=admin-account-not-resolved");
|
|
13465
13450
|
return c.json({ ok: false, error: "admin-account-not-resolved" }, 500);
|
|
13466
13451
|
}
|
|
13467
13452
|
const payloadBytes = JSON.stringify(envelope).length;
|
|
13468
13453
|
console.log(
|
|
13469
|
-
|
|
13454
|
+
TAG23 + " received kind=" + envelope.kind + " account=" + senderId.slice(0, 8) + " pageUrl=" + envelope.pageUrl + " dispatchId=" + envelope.dispatchId + " payloadBytes=" + payloadBytes
|
|
13470
13455
|
);
|
|
13471
13456
|
const initialMessage = buildInitialMessage(envelope);
|
|
13472
13457
|
const spawnStart = Date.now();
|
|
13473
13458
|
const sessionId = randomUUID9();
|
|
13474
|
-
console.log(
|
|
13459
|
+
console.log(TAG23 + " route target=rc-spawn dispatchId=" + envelope.dispatchId + " sessionId=" + sessionId.slice(0, 8));
|
|
13475
13460
|
const spawned = await managerRcSpawn({
|
|
13476
13461
|
sessionId,
|
|
13477
13462
|
initialMessage,
|
|
@@ -13480,12 +13465,12 @@ app28.post("/", requireAdminSession, async (c) => {
|
|
|
13480
13465
|
});
|
|
13481
13466
|
if ("error" in spawned) {
|
|
13482
13467
|
console.error(
|
|
13483
|
-
|
|
13468
|
+
TAG23 + " dispatch-failed dispatchId=" + envelope.dispatchId + " status=" + spawned.status + " ms=" + (Date.now() - spawnStart) + " message=" + spawned.error
|
|
13484
13469
|
);
|
|
13485
13470
|
return c.json({ ok: false, error: "dispatch-failed", upstreamStatus: spawned.status, detail: spawned.error }, 502);
|
|
13486
13471
|
}
|
|
13487
13472
|
console.log(
|
|
13488
|
-
|
|
13473
|
+
TAG23 + " dispatched dispatchId=" + envelope.dispatchId + " taskId=" + spawned.sessionId + " ms=" + (Date.now() - spawnStart)
|
|
13489
13474
|
);
|
|
13490
13475
|
return c.json({ ok: true, dispatchId: envelope.dispatchId, taskId: spawned.sessionId }, 202);
|
|
13491
13476
|
});
|
|
@@ -13493,7 +13478,7 @@ var linkedin_ingest_default = app28;
|
|
|
13493
13478
|
|
|
13494
13479
|
// server/routes/admin/post-turn-context.ts
|
|
13495
13480
|
import neo4j2 from "neo4j-driver";
|
|
13496
|
-
var
|
|
13481
|
+
var TAG24 = "[post-turn-context]";
|
|
13497
13482
|
var STRIPPED_PROPERTIES2 = /* @__PURE__ */ new Set([
|
|
13498
13483
|
"embedding",
|
|
13499
13484
|
"passwordHash",
|
|
@@ -13535,7 +13520,7 @@ var app29 = new Hono();
|
|
|
13535
13520
|
app29.get("/", async (c) => {
|
|
13536
13521
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
13537
13522
|
if (!isLoopbackAddr2(remoteAddr)) {
|
|
13538
|
-
console.error(`${
|
|
13523
|
+
console.error(`${TAG24} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
13539
13524
|
return c.json({ error: "post-turn-context-loopback-only" }, 403);
|
|
13540
13525
|
}
|
|
13541
13526
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -13544,7 +13529,7 @@ app29.get("/", async (c) => {
|
|
|
13544
13529
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
13545
13530
|
const offender = tokens.find((t) => !isLoopbackAddr2(t));
|
|
13546
13531
|
if (offender !== void 0) {
|
|
13547
|
-
console.error(`${
|
|
13532
|
+
console.error(`${TAG24} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
13548
13533
|
return c.json({ error: "post-turn-context-loopback-only" }, 403);
|
|
13549
13534
|
}
|
|
13550
13535
|
}
|
|
@@ -13576,7 +13561,7 @@ app29.get("/", async (c) => {
|
|
|
13576
13561
|
writes.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
|
|
13577
13562
|
const total = Date.now() - started;
|
|
13578
13563
|
console.log(
|
|
13579
|
-
`${
|
|
13564
|
+
`${TAG24} sessionId=${sessionId} accountId=${accountId} writes=${writes.length} ms=${total}`
|
|
13580
13565
|
);
|
|
13581
13566
|
return c.json({
|
|
13582
13567
|
writes: writes.map(({ elementId, labels, properties }) => ({ elementId, labels, properties }))
|
|
@@ -13585,7 +13570,7 @@ app29.get("/", async (c) => {
|
|
|
13585
13570
|
const elapsed = Date.now() - started;
|
|
13586
13571
|
const message = err instanceof Error ? err.message : String(err);
|
|
13587
13572
|
console.error(
|
|
13588
|
-
`${
|
|
13573
|
+
`${TAG24} neo4j-unreachable sessionId=${sessionId} ms=${elapsed} err="${message}"`
|
|
13589
13574
|
);
|
|
13590
13575
|
return c.json({ error: `post-turn-context unavailable: ${message}` }, 503);
|
|
13591
13576
|
} finally {
|
|
@@ -13596,7 +13581,7 @@ var post_turn_context_default = app29;
|
|
|
13596
13581
|
|
|
13597
13582
|
// server/routes/admin/public-session-context.ts
|
|
13598
13583
|
import neo4j3 from "neo4j-driver";
|
|
13599
|
-
var
|
|
13584
|
+
var TAG25 = "[public-session-context]";
|
|
13600
13585
|
var STRIPPED_PROPERTIES3 = /* @__PURE__ */ new Set([
|
|
13601
13586
|
"embedding",
|
|
13602
13587
|
"passwordHash",
|
|
@@ -13638,7 +13623,7 @@ var app30 = new Hono();
|
|
|
13638
13623
|
app30.get("/", async (c) => {
|
|
13639
13624
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
13640
13625
|
if (!isLoopbackAddr3(remoteAddr)) {
|
|
13641
|
-
console.error(`${
|
|
13626
|
+
console.error(`${TAG25} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
13642
13627
|
return c.json({ error: "public-session-context-loopback-only" }, 403);
|
|
13643
13628
|
}
|
|
13644
13629
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -13647,7 +13632,7 @@ app30.get("/", async (c) => {
|
|
|
13647
13632
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
13648
13633
|
const offender = tokens.find((t) => !isLoopbackAddr3(t));
|
|
13649
13634
|
if (offender !== void 0) {
|
|
13650
|
-
console.error(`${
|
|
13635
|
+
console.error(`${TAG25} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
13651
13636
|
return c.json({ error: "public-session-context-loopback-only" }, 403);
|
|
13652
13637
|
}
|
|
13653
13638
|
}
|
|
@@ -13678,7 +13663,7 @@ app30.get("/", async (c) => {
|
|
|
13678
13663
|
writes.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
|
|
13679
13664
|
const total = Date.now() - started;
|
|
13680
13665
|
console.log(
|
|
13681
|
-
`${
|
|
13666
|
+
`${TAG25} sliceToken=${sliceToken.slice(0, 8)} writes=${writes.length} ms=${total}`
|
|
13682
13667
|
);
|
|
13683
13668
|
return c.json({
|
|
13684
13669
|
writes: writes.map(({ elementId, labels, properties }) => ({ elementId, labels, properties }))
|
|
@@ -13687,7 +13672,7 @@ app30.get("/", async (c) => {
|
|
|
13687
13672
|
const elapsed = Date.now() - started;
|
|
13688
13673
|
const message = err instanceof Error ? err.message : String(err);
|
|
13689
13674
|
console.error(
|
|
13690
|
-
`${
|
|
13675
|
+
`${TAG25} neo4j-unreachable sliceToken=${sliceToken.slice(0, 8)} ms=${elapsed} err="${message}"`
|
|
13691
13676
|
);
|
|
13692
13677
|
return c.json({ error: `public-session-context unavailable: ${message}` }, 503);
|
|
13693
13678
|
} finally {
|
|
@@ -13697,7 +13682,7 @@ app30.get("/", async (c) => {
|
|
|
13697
13682
|
var public_session_context_default = app30;
|
|
13698
13683
|
|
|
13699
13684
|
// server/routes/admin/public-session-exit.ts
|
|
13700
|
-
var
|
|
13685
|
+
var TAG26 = "[public-session-exit-route]";
|
|
13701
13686
|
function isLoopbackAddr4(addr) {
|
|
13702
13687
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
13703
13688
|
}
|
|
@@ -13705,7 +13690,7 @@ var app31 = new Hono();
|
|
|
13705
13690
|
app31.post("/", async (c) => {
|
|
13706
13691
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
13707
13692
|
if (!isLoopbackAddr4(remoteAddr)) {
|
|
13708
|
-
console.error(`${
|
|
13693
|
+
console.error(`${TAG26} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
13709
13694
|
return c.json({ error: "public-session-exit-loopback-only" }, 403);
|
|
13710
13695
|
}
|
|
13711
13696
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -13714,7 +13699,7 @@ app31.post("/", async (c) => {
|
|
|
13714
13699
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
13715
13700
|
const offender = tokens.find((t) => !isLoopbackAddr4(t));
|
|
13716
13701
|
if (offender !== void 0) {
|
|
13717
|
-
console.error(`${
|
|
13702
|
+
console.error(`${TAG26} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
13718
13703
|
return c.json({ error: "public-session-exit-loopback-only" }, 403);
|
|
13719
13704
|
}
|
|
13720
13705
|
}
|
|
@@ -13732,7 +13717,7 @@ app31.post("/", async (c) => {
|
|
|
13732
13717
|
var public_session_exit_default = app31;
|
|
13733
13718
|
|
|
13734
13719
|
// server/routes/admin/access-session-evict.ts
|
|
13735
|
-
var
|
|
13720
|
+
var TAG27 = "[access-session-evict]";
|
|
13736
13721
|
function isLoopbackAddr5(addr) {
|
|
13737
13722
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
13738
13723
|
}
|
|
@@ -13740,7 +13725,7 @@ var app32 = new Hono();
|
|
|
13740
13725
|
app32.post("/", async (c) => {
|
|
13741
13726
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
13742
13727
|
if (!isLoopbackAddr5(remoteAddr)) {
|
|
13743
|
-
console.error(`${
|
|
13728
|
+
console.error(`${TAG27} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
13744
13729
|
return c.json({ error: "access-session-evict-loopback-only" }, 403);
|
|
13745
13730
|
}
|
|
13746
13731
|
const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
|
|
@@ -13749,7 +13734,7 @@ app32.post("/", async (c) => {
|
|
|
13749
13734
|
const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
|
|
13750
13735
|
const offender = tokens.find((t) => !isLoopbackAddr5(t));
|
|
13751
13736
|
if (offender !== void 0) {
|
|
13752
|
-
console.error(`${
|
|
13737
|
+
console.error(`${TAG27} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
|
|
13753
13738
|
return c.json({ error: "access-session-evict-loopback-only" }, 403);
|
|
13754
13739
|
}
|
|
13755
13740
|
}
|
|
@@ -13762,7 +13747,7 @@ app32.post("/", async (c) => {
|
|
|
13762
13747
|
const grantId = typeof body.grantId === "string" ? body.grantId.trim() : "";
|
|
13763
13748
|
if (!grantId) return c.json({ error: "grantId required" }, 400);
|
|
13764
13749
|
const dropped = evictAccessSessionsByGrant(grantId);
|
|
13765
|
-
console.log(`${
|
|
13750
|
+
console.log(`${TAG27} grantId=${grantId} dropped=${dropped}`);
|
|
13766
13751
|
return c.json({ ok: true, dropped });
|
|
13767
13752
|
});
|
|
13768
13753
|
var access_session_evict_default = app32;
|
|
@@ -13770,7 +13755,7 @@ var access_session_evict_default = app32;
|
|
|
13770
13755
|
// server/routes/admin/identity.ts
|
|
13771
13756
|
var import_dist4 = __toESM(require_dist3(), 1);
|
|
13772
13757
|
var app33 = new Hono();
|
|
13773
|
-
var
|
|
13758
|
+
var TAG28 = "[admin-identity]";
|
|
13774
13759
|
function managerBase5() {
|
|
13775
13760
|
const port2 = (0, import_dist4.requirePortEnv)("CLAUDE_SESSION_MANAGER_PORT", { tag: "admin-identity" });
|
|
13776
13761
|
return `http://127.0.0.1:${port2}`;
|
|
@@ -13801,20 +13786,20 @@ app33.post("/validate", async (c) => {
|
|
|
13801
13786
|
const verdict = validatePin(pin, USERS_FILE);
|
|
13802
13787
|
if (verdict.kind !== "match") {
|
|
13803
13788
|
if (verdict.kind === "miss") fireStop();
|
|
13804
|
-
console.log(`${
|
|
13789
|
+
console.log(`${TAG28} op=endpoint-validate result=${verdict.kind}${sessionId ? ` sessionId=${sessionId.slice(0, 8)}` : ""}`);
|
|
13805
13790
|
return c.json({ kind: verdict.kind });
|
|
13806
13791
|
}
|
|
13807
13792
|
const { userId } = verdict;
|
|
13808
13793
|
const accounts = resolveUserAccounts(userId);
|
|
13809
13794
|
if (accounts.length === 0) {
|
|
13810
13795
|
fireStop();
|
|
13811
|
-
console.log(`${
|
|
13796
|
+
console.log(`${TAG28} op=endpoint-validate result=no-account userId=${userId.slice(0, 8)}`);
|
|
13812
13797
|
return c.json({ kind: "miss" });
|
|
13813
13798
|
}
|
|
13814
13799
|
const accountId = accounts[0].accountId;
|
|
13815
13800
|
const { userName } = await resolveUserIdentity(accountId, userId);
|
|
13816
13801
|
const aboutOwner = await resolveOwnerProfileBlock(accountId, userId);
|
|
13817
|
-
console.log(`${
|
|
13802
|
+
console.log(`${TAG28} op=endpoint-validate result=match userId=${userId.slice(0, 8)} aboutOwner=${aboutOwner.ok ? "ok" : `unresolved:${aboutOwner.reason}`}`);
|
|
13818
13803
|
return c.json({ kind: "match", userId, userName, aboutOwner });
|
|
13819
13804
|
});
|
|
13820
13805
|
var identity_default = app33;
|
|
@@ -14093,7 +14078,7 @@ async function generateNewMagicToken(grantId) {
|
|
|
14093
14078
|
}
|
|
14094
14079
|
|
|
14095
14080
|
// server/routes/access/verify-token.ts
|
|
14096
|
-
var
|
|
14081
|
+
var TAG29 = "[access-verify]";
|
|
14097
14082
|
var MINT_TAG = "[access-session-mint]";
|
|
14098
14083
|
var COOKIE_NAME = "__access_session";
|
|
14099
14084
|
var app36 = new Hono();
|
|
@@ -14112,39 +14097,39 @@ app36.post("/", async (c) => {
|
|
|
14112
14097
|
}
|
|
14113
14098
|
const rateMsg = checkAccessRateLimit(ip, agentSlug);
|
|
14114
14099
|
if (rateMsg) {
|
|
14115
|
-
console.error(`${
|
|
14100
|
+
console.error(`${TAG29} grantId=- agentSlug=${agentSlug} result=rate-limited ip=${ip}`);
|
|
14116
14101
|
return c.json({ error: rateMsg }, 429);
|
|
14117
14102
|
}
|
|
14118
14103
|
const grant = await findGrantByMagicToken(token);
|
|
14119
14104
|
if (!grant) {
|
|
14120
14105
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
14121
|
-
console.error(`${
|
|
14106
|
+
console.error(`${TAG29} grantId=- agentSlug=${agentSlug} result=notfound ip=${ip}`);
|
|
14122
14107
|
return c.json({ error: "invalid-or-expired-link" }, 401);
|
|
14123
14108
|
}
|
|
14124
14109
|
if (grant.agentSlug !== agentSlug) {
|
|
14125
14110
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
14126
14111
|
console.error(
|
|
14127
|
-
`${
|
|
14112
|
+
`${TAG29} grantId=${grant.grantId} agentSlug=${agentSlug} result=agent-mismatch grantAgent=${grant.agentSlug} ip=${ip}`
|
|
14128
14113
|
);
|
|
14129
14114
|
return c.json({ error: "invalid-or-expired-link" }, 401);
|
|
14130
14115
|
}
|
|
14131
14116
|
if (grant.status === "expired" || grant.status === "revoked") {
|
|
14132
14117
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
14133
14118
|
console.error(
|
|
14134
|
-
`${
|
|
14119
|
+
`${TAG29} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired status=${grant.status} ip=${ip}`
|
|
14135
14120
|
);
|
|
14136
14121
|
return c.json({ error: "access-no-longer-valid" }, 401);
|
|
14137
14122
|
}
|
|
14138
14123
|
if (grant.expiresAt !== null && grant.expiresAt < Date.now()) {
|
|
14139
14124
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
14140
14125
|
console.error(
|
|
14141
|
-
`${
|
|
14126
|
+
`${TAG29} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired reason=expiresAt-past ip=${ip}`
|
|
14142
14127
|
);
|
|
14143
14128
|
return c.json({ error: "access-no-longer-valid" }, 401);
|
|
14144
14129
|
}
|
|
14145
14130
|
if (!grant.sliceToken) {
|
|
14146
14131
|
console.error(
|
|
14147
|
-
`${
|
|
14132
|
+
`${TAG29} grantId=${grant.grantId} agentSlug=${agentSlug} result=no-slice-token reason=schema-violation`
|
|
14148
14133
|
);
|
|
14149
14134
|
return c.json({ error: "grant-misconfigured" }, 500);
|
|
14150
14135
|
}
|
|
@@ -14160,12 +14145,12 @@ app36.post("/", async (c) => {
|
|
|
14160
14145
|
await consumeMagicTokenAndActivate(grant.grantId);
|
|
14161
14146
|
} catch (err) {
|
|
14162
14147
|
console.error(
|
|
14163
|
-
`${
|
|
14148
|
+
`${TAG29} grantId=${grant.grantId} agentSlug=${agentSlug} result=consume-failed err="${err instanceof Error ? err.message : String(err)}"`
|
|
14164
14149
|
);
|
|
14165
14150
|
return c.json({ error: "verification-failed" }, 500);
|
|
14166
14151
|
}
|
|
14167
14152
|
clearAccessRateLimit(ip, agentSlug);
|
|
14168
|
-
console.log(`${
|
|
14153
|
+
console.log(`${TAG29} grantId=${grant.grantId} agentSlug=${agentSlug} result=ok ip=${ip}`);
|
|
14169
14154
|
console.log(
|
|
14170
14155
|
`${MINT_TAG} grantId=${grant.grantId} sliceToken=${grant.sliceToken.slice(0, 8)} agentSlug=${agentSlug} personId=${grant.personId ?? "none"}`
|
|
14171
14156
|
);
|
|
@@ -14241,7 +14226,7 @@ async function sendMagicLinkEmail(payload) {
|
|
|
14241
14226
|
}
|
|
14242
14227
|
|
|
14243
14228
|
// server/routes/access/request-magic-link.ts
|
|
14244
|
-
var
|
|
14229
|
+
var TAG30 = "[access-request-link]";
|
|
14245
14230
|
var app37 = new Hono();
|
|
14246
14231
|
var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
|
|
14247
14232
|
app37.post("/", async (c) => {
|
|
@@ -14258,18 +14243,18 @@ app37.post("/", async (c) => {
|
|
|
14258
14243
|
}
|
|
14259
14244
|
const rateMsg = checkRequestLinkRateLimit(contactValue);
|
|
14260
14245
|
if (rateMsg) {
|
|
14261
|
-
console.error(`${
|
|
14246
|
+
console.error(`${TAG30} contactValue=${maskContact(contactValue)} result=rate-limited`);
|
|
14262
14247
|
return c.json({ error: rateMsg }, 429);
|
|
14263
14248
|
}
|
|
14264
14249
|
recordRequestLinkAttempt(contactValue);
|
|
14265
14250
|
const accountId = process.env.ACCOUNT_ID ?? "";
|
|
14266
14251
|
if (!accountId) {
|
|
14267
|
-
console.error(`${
|
|
14252
|
+
console.error(`${TAG30} contactValue=${maskContact(contactValue)} result=no-account-id`);
|
|
14268
14253
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
14269
14254
|
}
|
|
14270
14255
|
const grant = await findActiveGrantByContact(contactValue, agentSlug, accountId);
|
|
14271
14256
|
if (!grant) {
|
|
14272
|
-
console.log(`${
|
|
14257
|
+
console.log(`${TAG30} contactValue=${maskContact(contactValue)} result=notfound`);
|
|
14273
14258
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
14274
14259
|
}
|
|
14275
14260
|
let token;
|
|
@@ -14277,7 +14262,7 @@ app37.post("/", async (c) => {
|
|
|
14277
14262
|
token = await generateNewMagicToken(grant.grantId);
|
|
14278
14263
|
} catch (err) {
|
|
14279
14264
|
console.error(
|
|
14280
|
-
`${
|
|
14265
|
+
`${TAG30} contactValue=${maskContact(contactValue)} result=mint-failed err="${err instanceof Error ? err.message : String(err)}"`
|
|
14281
14266
|
);
|
|
14282
14267
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
14283
14268
|
}
|
|
@@ -14309,12 +14294,12 @@ app37.post("/", async (c) => {
|
|
|
14309
14294
|
});
|
|
14310
14295
|
if (!sendResult.ok) {
|
|
14311
14296
|
console.error(
|
|
14312
|
-
`${
|
|
14297
|
+
`${TAG30} contactValue=${maskContact(contactValue)} result=send-failed err="${sendResult.error}"`
|
|
14313
14298
|
);
|
|
14314
14299
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
14315
14300
|
}
|
|
14316
14301
|
console.log(
|
|
14317
|
-
`${
|
|
14302
|
+
`${TAG30} contactValue=${maskContact(contactValue)} result=ok messageId=${sendResult.messageId}`
|
|
14318
14303
|
);
|
|
14319
14304
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
14320
14305
|
});
|
|
@@ -15521,51 +15506,6 @@ async function startFileWatcher(opts = {}) {
|
|
|
15521
15506
|
}
|
|
15522
15507
|
|
|
15523
15508
|
// 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
15509
|
function startReaper2() {
|
|
15570
15510
|
startReaper();
|
|
15571
15511
|
}
|
|
@@ -17014,60 +16954,37 @@ init({
|
|
|
17014
16954
|
platformRoot: resolve26(process.env.MAXY_PLATFORM_ROOT ?? join18(__dirname, "..")),
|
|
17015
16955
|
accountConfig: bootAccountConfig,
|
|
17016
16956
|
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
|
-
}
|
|
16957
|
+
if (msg.isOwnerMirror) {
|
|
16958
|
+
console.error(`[whatsapp:route] skipped reason=owner-mirror senderId=${msg.senderPhone}`);
|
|
17032
16959
|
return;
|
|
17033
16960
|
}
|
|
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
|
-
}
|
|
16961
|
+
if (msg.agentType !== "admin") {
|
|
16962
|
+
console.error(`[whatsapp:route] dropped reason=non-admin-sender senderId=${msg.senderPhone} agentType=${msg.agentType}`);
|
|
17064
16963
|
return;
|
|
17065
16964
|
}
|
|
17066
|
-
|
|
16965
|
+
if (!msg.text) {
|
|
16966
|
+
console.error(`[whatsapp:route] dropped reason=no-text-on-native-channel senderId=${msg.senderPhone} media=${msg.mediaType ?? "none"}`);
|
|
16967
|
+
return;
|
|
16968
|
+
}
|
|
16969
|
+
try {
|
|
16970
|
+
void msg.composing().catch(() => {
|
|
16971
|
+
});
|
|
16972
|
+
await waGateway.handleInbound({
|
|
16973
|
+
accountId: msg.accountId,
|
|
16974
|
+
senderId: msg.senderPhone,
|
|
16975
|
+
text: msg.text,
|
|
16976
|
+
reply: msg.reply
|
|
16977
|
+
});
|
|
16978
|
+
} catch (err) {
|
|
16979
|
+
console.error(
|
|
16980
|
+
`[whatsapp-native] reject senderId=${msg.senderPhone} message=${err instanceof Error ? err.message : String(err)}`
|
|
16981
|
+
);
|
|
16982
|
+
}
|
|
17067
16983
|
}
|
|
17068
16984
|
}).catch((err) => {
|
|
17069
16985
|
console.error(`[whatsapp] init failed: ${String(err)}`);
|
|
17070
16986
|
});
|
|
16987
|
+
startReaper2();
|
|
17071
16988
|
var shuttingDown = false;
|
|
17072
16989
|
process.on("SIGTERM", async () => {
|
|
17073
16990
|
if (shuttingDown) {
|