@rubytech/create-realagent-code 0.1.613 → 0.1.614
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/lib/agent-dispatch-rule/dist/index.d.ts +34 -0
- package/payload/platform/lib/agent-dispatch-rule/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/agent-dispatch-rule/dist/index.js +39 -0
- package/payload/platform/lib/agent-dispatch-rule/dist/index.js.map +1 -1
- package/payload/platform/lib/agent-dispatch-rule/src/__tests__/carrier-verdict.test.ts +92 -0
- package/payload/platform/lib/agent-dispatch-rule/src/index.ts +59 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +46 -1
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +6 -0
- package/payload/platform/plugins/docs/references/telegram-guide.md +45 -0
- package/payload/platform/plugins/scheduling/mcp/dist/index.js +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/agent-dispatch-carrier.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/agent-dispatch-carrier.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/agent-dispatch-carrier.test.js +72 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/agent-dispatch-carrier.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-delivery-reconcile.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-delivery-reconcile.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-delivery-reconcile.test.js +327 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-delivery-reconcile.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-delivery.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-delivery.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-delivery.test.js +130 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-delivery.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-run.test.js +27 -58
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-run.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/agent-dispatch.d.ts +8 -3
- package/payload/platform/plugins/scheduling/mcp/dist/lib/agent-dispatch.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/agent-dispatch.js +37 -3
- package/payload/platform/plugins/scheduling/mcp/dist/lib/agent-dispatch.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-delivery.d.ts +67 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-delivery.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-delivery.js +133 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-delivery.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.d.ts +67 -12
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.js +226 -72
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js +66 -4
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/reconcile-run-controls.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/reconcile-run-controls.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/reconcile-run-controls.test.js +45 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/reconcile-run-controls.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts +3 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js +32 -7
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +12 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js +15 -2
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts +14 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js +4 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.d.ts +3 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.js +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js +14 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js.map +1 -1
- package/payload/server/public/operator.html +1 -1
- package/payload/server/server.js +663 -620
package/payload/server/server.js
CHANGED
|
@@ -3220,10 +3220,10 @@ var require_dist10 = __commonJS({
|
|
|
3220
3220
|
});
|
|
3221
3221
|
|
|
3222
3222
|
// server/index.ts
|
|
3223
|
-
import { readFileSync as
|
|
3223
|
+
import { readFileSync as readFileSync64, existsSync as existsSync63, watchFile, readdirSync as readdirSync38, statSync as statSync34 } from "fs";
|
|
3224
3224
|
import { spawn as spawn3 } from "child_process";
|
|
3225
3225
|
import { createHash as createHash8 } from "crypto";
|
|
3226
|
-
import { resolve as resolve55, join as
|
|
3226
|
+
import { resolve as resolve55, join as join78, basename as basename19 } from "path";
|
|
3227
3227
|
import { homedir as homedir5 } from "os";
|
|
3228
3228
|
|
|
3229
3229
|
// server/lib/route-cache-watchers.ts
|
|
@@ -7196,17 +7196,17 @@ async function computeSessionList(scopeAccountId) {
|
|
|
7196
7196
|
if (adminUserId && role === ADMIN_ROLE && sidecarChannel === WEBCHAT_CHANNEL) {
|
|
7197
7197
|
adminUserIdBySession.set(sessionId, adminUserId);
|
|
7198
7198
|
}
|
|
7199
|
-
const
|
|
7200
|
-
if (
|
|
7199
|
+
const tail2 = await lastAssistantModelFromTail(path, size);
|
|
7200
|
+
if (tail2.failure) {
|
|
7201
7201
|
tailReadFails += 1;
|
|
7202
7202
|
console.error(
|
|
7203
|
-
`[admin-sessions-list] op=tail-read-failed sessionId=${sessionId.slice(0, 8)} reason=${
|
|
7203
|
+
`[admin-sessions-list] op=tail-read-failed sessionId=${sessionId.slice(0, 8)} reason=${tail2.failure}`
|
|
7204
7204
|
);
|
|
7205
7205
|
} else {
|
|
7206
|
-
if (
|
|
7207
|
-
if (
|
|
7206
|
+
if (tail2.bytesRead > 0) tailReads += 1;
|
|
7207
|
+
if (tail2.model === null) tailModelMiss += 1;
|
|
7208
7208
|
}
|
|
7209
|
-
tailBytes +=
|
|
7209
|
+
tailBytes += tail2.bytesRead;
|
|
7210
7210
|
rows.push({
|
|
7211
7211
|
sessionId,
|
|
7212
7212
|
title: resolved.title,
|
|
@@ -7225,7 +7225,7 @@ async function computeSessionList(scopeAccountId) {
|
|
|
7225
7225
|
// diverge from the sidecar (e.g. an ai-titled channel row).
|
|
7226
7226
|
channel: sidecarChannel,
|
|
7227
7227
|
personName: null,
|
|
7228
|
-
model:
|
|
7228
|
+
model: tail2.model,
|
|
7229
7229
|
accountId: rowAccountId,
|
|
7230
7230
|
senderId,
|
|
7231
7231
|
whatsappName: null
|
|
@@ -7445,33 +7445,53 @@ function createScheduleInjectRoutes(deps) {
|
|
|
7445
7445
|
console.error(`${TAG6} op=inject-spawn eventId=${eventId} sessionId=${sessionId2} result=ok status=-`);
|
|
7446
7446
|
return c.json({ ok: true, sessionKey: sessionId2, ...transcriptBoundary(sessionId2) }, 200);
|
|
7447
7447
|
}
|
|
7448
|
-
const
|
|
7449
|
-
if (resolution.kind === "none") {
|
|
7450
|
-
console.error(`${TAG6} op=schedule-telegram-reject eventId=${eventId} destination=${destination} reason=unresolved-effective-account`);
|
|
7451
|
-
return c.json({ ok: false, error: "unresolved-effective-account" }, 403);
|
|
7452
|
-
}
|
|
7448
|
+
const namedBotId = typeof body.botId === "string" && body.botId.length > 0 ? body.botId : null;
|
|
7453
7449
|
let claimant;
|
|
7454
|
-
|
|
7455
|
-
|
|
7456
|
-
|
|
7457
|
-
|
|
7458
|
-
|
|
7450
|
+
let carrierSource;
|
|
7451
|
+
let claimantCount = 0;
|
|
7452
|
+
if (namedBotId !== null && eventAccountId !== null) {
|
|
7453
|
+
carrierSource = "named";
|
|
7454
|
+
const carrier = deps.carrierFor(eventAccountId, namedBotId, destination);
|
|
7455
|
+
if ("error" in carrier) {
|
|
7459
7456
|
console.error(
|
|
7460
|
-
`${TAG6} op=
|
|
7457
|
+
`${TAG6} op=carrier-unavailable eventId=${eventId} botId=${namedBotId} reason=${carrier.error}`
|
|
7461
7458
|
);
|
|
7462
|
-
return c.json({ ok: false, error: "
|
|
7459
|
+
return c.json({ ok: false, error: "carrier-unavailable" }, 403);
|
|
7463
7460
|
}
|
|
7464
|
-
|
|
7461
|
+
claimant = carrier;
|
|
7462
|
+
} else {
|
|
7463
|
+
carrierSource = "resolved";
|
|
7464
|
+
const resolution = deps.telegramAccountForDestination(destination);
|
|
7465
|
+
if (resolution.kind === "none") {
|
|
7466
|
+
console.error(`${TAG6} op=schedule-telegram-reject eventId=${eventId} destination=${destination} reason=unresolved-effective-account`);
|
|
7467
|
+
return c.json({ ok: false, error: "unresolved-effective-account" }, 403);
|
|
7468
|
+
}
|
|
7469
|
+
claimantCount = resolution.kind === "ambiguous" ? resolution.claimants.length : 1;
|
|
7470
|
+
if (resolution.kind === "one") {
|
|
7471
|
+
claimant = resolution;
|
|
7472
|
+
} else {
|
|
7473
|
+
const mine = resolution.claimants.filter((c2) => c2.accountId === eventAccountId);
|
|
7474
|
+
if (mine.length === 0) {
|
|
7475
|
+
console.error(
|
|
7476
|
+
`${TAG6} op=event-account-scope-mismatch eventId=${eventId} eventAccount=${eventAccountId ?? "-"} effectiveAccount=none claimants=${resolution.claimants.length} destination=${destination} dispatched=no`
|
|
7477
|
+
);
|
|
7478
|
+
return c.json({ ok: false, error: "event-account-scope-mismatch" }, 403);
|
|
7479
|
+
}
|
|
7480
|
+
if (mine.length > 1) {
|
|
7481
|
+
console.error(
|
|
7482
|
+
`${TAG6} op=telegram-destination-ambiguous eventId=${eventId} destination=${destination} accounts=${mine.length} scope=within-account dispatched=no`
|
|
7483
|
+
);
|
|
7484
|
+
return c.json({ ok: false, error: "telegram-destination-ambiguous" }, 403);
|
|
7485
|
+
}
|
|
7486
|
+
claimant = mine[0];
|
|
7465
7487
|
console.error(
|
|
7466
|
-
`${TAG6} op=telegram-destination-
|
|
7488
|
+
`${TAG6} op=telegram-destination-narrowed eventId=${eventId} destination=${destination} claimants=${resolution.claimants.length} account=${claimant.accountId} botId=${claimant.botId}`
|
|
7467
7489
|
);
|
|
7468
|
-
return c.json({ ok: false, error: "telegram-destination-ambiguous" }, 403);
|
|
7469
7490
|
}
|
|
7470
|
-
claimant = mine[0];
|
|
7471
|
-
console.error(
|
|
7472
|
-
`${TAG6} op=telegram-destination-narrowed eventId=${eventId} destination=${destination} claimants=${resolution.claimants.length} account=${claimant.accountId} botId=${claimant.botId}`
|
|
7473
|
-
);
|
|
7474
7491
|
}
|
|
7492
|
+
console.error(
|
|
7493
|
+
`${TAG6} op=carrier eventId=${eventId} botId=${claimant.botId} source=${carrierSource} claimants=${claimantCount}`
|
|
7494
|
+
);
|
|
7475
7495
|
const { accountId: effectiveAccount, botId, botToken } = claimant;
|
|
7476
7496
|
console.error(`${TAG6} op=effective-account eventId=${eventId} effectiveAccount=${effectiveAccount} botId=${botId}`);
|
|
7477
7497
|
if (eventAccountId === null || eventAccountId !== effectiveAccount) {
|
|
@@ -8270,8 +8290,8 @@ function auditGroupOutbound() {
|
|
|
8270
8290
|
}
|
|
8271
8291
|
function auditGroupOutboundNote() {
|
|
8272
8292
|
const a = auditGroupOutbound();
|
|
8273
|
-
const
|
|
8274
|
-
const note = `convos=${a.convos} outbound=${a.outbound} operator=${a.operator} agent=${a.agent} unstamped=${a.unstamped}${
|
|
8293
|
+
const tail2 = a.agent > 0 ? ` offenders=${a.offenders.join(",")}` : "";
|
|
8294
|
+
const note = `convos=${a.convos} outbound=${a.outbound} operator=${a.operator} agent=${a.agent} unstamped=${a.unstamped}${tail2}`;
|
|
8275
8295
|
console.log(`${TAG13} op=group-outbound-audit ${note}`);
|
|
8276
8296
|
return note;
|
|
8277
8297
|
}
|
|
@@ -9302,10 +9322,10 @@ function resolveKey(accountId, ctx) {
|
|
|
9302
9322
|
function setAccountPolicy(accountDir, accountId, policy, ctx) {
|
|
9303
9323
|
const id = accountId.trim();
|
|
9304
9324
|
if (!id) return { ok: false, reason: "missing-account-id", error: "Missing account id." };
|
|
9305
|
-
const
|
|
9325
|
+
const fields2 = ["dmPolicy", "adminPhones", "allowFrom"].filter(
|
|
9306
9326
|
(f) => policy[f] !== void 0
|
|
9307
9327
|
);
|
|
9308
|
-
if (
|
|
9328
|
+
if (fields2.length === 0) {
|
|
9309
9329
|
return {
|
|
9310
9330
|
ok: false,
|
|
9311
9331
|
reason: "empty-policy",
|
|
@@ -9327,7 +9347,7 @@ function setAccountPolicy(accountDir, accountId, policy, ctx) {
|
|
|
9327
9347
|
const accounts = wa.accounts;
|
|
9328
9348
|
if (!accounts[key2] || typeof accounts[key2] !== "object") accounts[key2] = { name: "Main" };
|
|
9329
9349
|
const slice = accounts[key2];
|
|
9330
|
-
for (const field2 of
|
|
9350
|
+
for (const field2 of fields2) slice[field2] = policy[field2];
|
|
9331
9351
|
const parsed = WhatsAppConfigSchema.safeParse(wa);
|
|
9332
9352
|
if (!parsed.success) {
|
|
9333
9353
|
const msg = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
|
|
@@ -9337,7 +9357,7 @@ function setAccountPolicy(accountDir, accountId, policy, ctx) {
|
|
|
9337
9357
|
config.whatsapp = parsed.data;
|
|
9338
9358
|
writeConfig(accountDir, config);
|
|
9339
9359
|
console.error(
|
|
9340
|
-
`${TAG15} op=set-account-policy account=${id} key=${key2} keyKind=${verdict.kind} fields=[${
|
|
9360
|
+
`${TAG15} op=set-account-policy account=${id} key=${key2} keyKind=${verdict.kind} fields=[${fields2.join(",")}] ok=true`
|
|
9341
9361
|
);
|
|
9342
9362
|
reloadManagerConfig(accountDir);
|
|
9343
9363
|
return { ok: true, key: key2 };
|
|
@@ -9599,8 +9619,8 @@ function resolvePublicAgentEnabled(accountDir, opts) {
|
|
|
9599
9619
|
return { enabled: false, source: "default" };
|
|
9600
9620
|
}
|
|
9601
9621
|
}
|
|
9602
|
-
function updateConfig(accountDir,
|
|
9603
|
-
const fieldNames = Object.keys(
|
|
9622
|
+
function updateConfig(accountDir, fields2) {
|
|
9623
|
+
const fieldNames = Object.keys(fields2);
|
|
9604
9624
|
if (fieldNames.length === 0) {
|
|
9605
9625
|
return { ok: false, error: "No fields provided to update." };
|
|
9606
9626
|
}
|
|
@@ -9610,7 +9630,7 @@ function updateConfig(accountDir, fields) {
|
|
|
9610
9630
|
config.whatsapp = {};
|
|
9611
9631
|
}
|
|
9612
9632
|
const wa = config.whatsapp;
|
|
9613
|
-
for (const [key2, value] of Object.entries(
|
|
9633
|
+
for (const [key2, value] of Object.entries(fields2)) {
|
|
9614
9634
|
wa[key2] = value;
|
|
9615
9635
|
}
|
|
9616
9636
|
const parsed = WhatsAppConfigSchema.safeParse(wa);
|
|
@@ -10320,12 +10340,12 @@ function unwrapToShape(schema) {
|
|
|
10320
10340
|
}
|
|
10321
10341
|
function extractFields(schema) {
|
|
10322
10342
|
const shape = unwrapToShape(schema);
|
|
10323
|
-
const
|
|
10343
|
+
const fields2 = [];
|
|
10324
10344
|
for (const [name, fieldSchema] of Object.entries(shape)) {
|
|
10325
10345
|
const def = fieldSchema?._def;
|
|
10326
10346
|
const resolved = resolveZodType(def);
|
|
10327
10347
|
const description = extractDescription(fieldSchema, def);
|
|
10328
|
-
|
|
10348
|
+
fields2.push({
|
|
10329
10349
|
name,
|
|
10330
10350
|
type: resolved.type,
|
|
10331
10351
|
required: resolved.required,
|
|
@@ -10333,14 +10353,14 @@ function extractFields(schema) {
|
|
|
10333
10353
|
...description !== void 0 ? { description } : {}
|
|
10334
10354
|
});
|
|
10335
10355
|
}
|
|
10336
|
-
return
|
|
10356
|
+
return fields2;
|
|
10337
10357
|
}
|
|
10338
10358
|
function escapeTableCell(text) {
|
|
10339
10359
|
return text.replace(/\|/g, "\\|");
|
|
10340
10360
|
}
|
|
10341
|
-
function formatFieldTable(title,
|
|
10361
|
+
function formatFieldTable(title, fields2) {
|
|
10342
10362
|
const lines = [`## ${title}`, "", "| Field | Type | Required | Default | Description |", "|-------|------|----------|---------|-------------|"];
|
|
10343
|
-
for (const f of
|
|
10363
|
+
for (const f of fields2) {
|
|
10344
10364
|
const desc = f.description ? escapeTableCell(f.description) : "\u2014";
|
|
10345
10365
|
lines.push(`| ${f.name} | ${f.type} | ${f.required ? "yes" : "no"} | ${f.default ?? "\u2014"} | ${desc} |`);
|
|
10346
10366
|
}
|
|
@@ -10497,12 +10517,12 @@ function houseSocketScopeDenial(c, op) {
|
|
|
10497
10517
|
}
|
|
10498
10518
|
function selfOrHouseScopeDenial(c, targetAccountId, op, targetSource = "explicit") {
|
|
10499
10519
|
const { decision, callerAccountId, houseAdminScope } = evaluateCallerScope(c, targetAccountId);
|
|
10500
|
-
const
|
|
10520
|
+
const tail2 = `target=${targetAccountId} targetSource=${targetSource} caller=${callerAccountId ?? "none"} houseAdmin=${houseAdminScope ? "y" : "n"}`;
|
|
10501
10521
|
if (decision.authorized) {
|
|
10502
|
-
console.error(`${TAG20} op=authz-ok route=${op} ${
|
|
10522
|
+
console.error(`${TAG20} op=authz-ok route=${op} ${tail2}`);
|
|
10503
10523
|
return null;
|
|
10504
10524
|
}
|
|
10505
|
-
console.error(`${TAG20} op=authz-deny route=${op} ${
|
|
10525
|
+
console.error(`${TAG20} op=authz-deny route=${op} ${tail2}`);
|
|
10506
10526
|
return c.json({ ok: false, error: "Not authorized. This session may only pair or manage its own account." }, 403);
|
|
10507
10527
|
}
|
|
10508
10528
|
function bindingScopeDenial(c, targetAccountId, op) {
|
|
@@ -10776,7 +10796,7 @@ app3.post("/reconnect", async (c) => {
|
|
|
10776
10796
|
app3.post("/config", async (c) => {
|
|
10777
10797
|
try {
|
|
10778
10798
|
const body = await c.req.json().catch(() => ({}));
|
|
10779
|
-
const { action, phone, slug, fields, accountId, managesAccount, mode, policy, party, account: partyAccount, enabled } = body;
|
|
10799
|
+
const { action, phone, slug, fields: fields2, accountId, managesAccount, mode, policy, party, account: partyAccount, enabled } = body;
|
|
10780
10800
|
if (!action || typeof action !== "string") {
|
|
10781
10801
|
return c.json({ ok: false, error: 'Missing required field "action".' }, 400);
|
|
10782
10802
|
}
|
|
@@ -11040,11 +11060,11 @@ app3.post("/config", async (c) => {
|
|
|
11040
11060
|
}
|
|
11041
11061
|
}
|
|
11042
11062
|
case "update-config": {
|
|
11043
|
-
if (!
|
|
11063
|
+
if (!fields2 || typeof fields2 !== "object" || Array.isArray(fields2)) {
|
|
11044
11064
|
return c.json({ ok: false, error: 'Missing required field "fields" (object with config field names and values).' }, 400);
|
|
11045
11065
|
}
|
|
11046
|
-
const result = updateConfig(account.accountDir,
|
|
11047
|
-
const fieldNames = Object.keys(
|
|
11066
|
+
const result = updateConfig(account.accountDir, fields2);
|
|
11067
|
+
const fieldNames = Object.keys(fields2);
|
|
11048
11068
|
console.error(`${TAG20} config action=update-config fields=[${fieldNames.join(",")}] ok=${result.ok}`);
|
|
11049
11069
|
return c.json(result, result.ok ? 200 : 400);
|
|
11050
11070
|
}
|
|
@@ -14194,13 +14214,13 @@ async function pullVisitStatusForAccount(opts) {
|
|
|
14194
14214
|
log2(
|
|
14195
14215
|
`${TAG24} op=merged account=${accountId} id=${row.id} labour=${row.dayHundredths > 0} forWorker=${row.forOwnerId !== ""}`
|
|
14196
14216
|
);
|
|
14197
|
-
const
|
|
14198
|
-
if (row.workDate !== "")
|
|
14199
|
-
if (row.workNote !== "")
|
|
14200
|
-
if (row.assignedOwnerId !== "")
|
|
14201
|
-
if (row.startDate !== "")
|
|
14202
|
-
if (row.forOwnerId !== "")
|
|
14203
|
-
for (const field2 of
|
|
14217
|
+
const fields2 = ["status"];
|
|
14218
|
+
if (row.workDate !== "") fields2.push("workDate");
|
|
14219
|
+
if (row.workNote !== "") fields2.push("workNote");
|
|
14220
|
+
if (row.assignedOwnerId !== "") fields2.push("assignedOwnerId");
|
|
14221
|
+
if (row.startDate !== "") fields2.push("startDate");
|
|
14222
|
+
if (row.forOwnerId !== "") fields2.push("forOwnerId");
|
|
14223
|
+
for (const field2 of fields2) {
|
|
14204
14224
|
log2(`${TAG24} op=applied visitId=${row.visitId} field=${field2}`);
|
|
14205
14225
|
}
|
|
14206
14226
|
} catch (err) {
|
|
@@ -16298,10 +16318,97 @@ function runTelegramStoreCensus() {
|
|
|
16298
16318
|
return c;
|
|
16299
16319
|
}
|
|
16300
16320
|
|
|
16321
|
+
// app/lib/telegram/card-row-census.ts
|
|
16322
|
+
import { closeSync as closeSync6, openSync as openSync6, readdirSync as readdirSync15, readFileSync as readFileSync24, readSync as readSync6, statSync as statSync15 } from "fs";
|
|
16323
|
+
import { join as join30 } from "path";
|
|
16324
|
+
var CARD_ROW_CENSUS_TAG = "[telegram-card-row-census]";
|
|
16325
|
+
var CARD_ROW_WINDOW_MS = 60 * 60 * 1e3;
|
|
16326
|
+
var MAX_BYTES_PER_FILE = 4e6;
|
|
16327
|
+
function tail(path, size) {
|
|
16328
|
+
if (size <= MAX_BYTES_PER_FILE) return readFileSync24(path, "utf-8");
|
|
16329
|
+
const buf = Buffer.alloc(MAX_BYTES_PER_FILE);
|
|
16330
|
+
const fd = openSync6(path, "r");
|
|
16331
|
+
try {
|
|
16332
|
+
const read = readSync6(fd, buf, 0, MAX_BYTES_PER_FILE, size - MAX_BYTES_PER_FILE);
|
|
16333
|
+
const text = buf.subarray(0, read).toString("utf-8");
|
|
16334
|
+
const nl = text.indexOf("\n");
|
|
16335
|
+
return nl === -1 ? "" : text.slice(nl + 1);
|
|
16336
|
+
} finally {
|
|
16337
|
+
closeSync6(fd);
|
|
16338
|
+
}
|
|
16339
|
+
}
|
|
16340
|
+
function fields(line) {
|
|
16341
|
+
const out = {};
|
|
16342
|
+
for (const part of line.split(" ")) {
|
|
16343
|
+
const i = part.indexOf("=");
|
|
16344
|
+
if (i > 0) out[part.slice(0, i)] = part.slice(i + 1);
|
|
16345
|
+
}
|
|
16346
|
+
return out;
|
|
16347
|
+
}
|
|
16348
|
+
function parseCardSends(lines) {
|
|
16349
|
+
const out = [];
|
|
16350
|
+
for (const line of lines) {
|
|
16351
|
+
if (!line.startsWith("[telegram-tools] op=card-sent ")) continue;
|
|
16352
|
+
const f = fields(line);
|
|
16353
|
+
if (f.outcome !== "sent") continue;
|
|
16354
|
+
if (!f.accountId || !f.key || !f.messageId) continue;
|
|
16355
|
+
const atMs = Date.parse(f.at ?? "");
|
|
16356
|
+
if (!Number.isFinite(atMs)) continue;
|
|
16357
|
+
out.push({ accountId: f.accountId, channelKey: f.key, messageId: f.messageId, atMs });
|
|
16358
|
+
}
|
|
16359
|
+
return out;
|
|
16360
|
+
}
|
|
16361
|
+
function rowExists(send) {
|
|
16362
|
+
const rowId = `telegram:${send.accountId}:${send.channelKey}:card:${send.messageId}`;
|
|
16363
|
+
for (const row of readRows(send.accountId, send.channelKey)) {
|
|
16364
|
+
if (isUpdateRecord(row)) continue;
|
|
16365
|
+
if (row.messageId === rowId) return true;
|
|
16366
|
+
}
|
|
16367
|
+
return false;
|
|
16368
|
+
}
|
|
16369
|
+
function collectCardRowCensus(input) {
|
|
16370
|
+
const floor = input.nowMs - CARD_ROW_WINDOW_MS;
|
|
16371
|
+
const sends = /* @__PURE__ */ new Map();
|
|
16372
|
+
try {
|
|
16373
|
+
if (input.logDir) {
|
|
16374
|
+
for (const name of readdirSync15(input.logDir)) {
|
|
16375
|
+
if (!name.startsWith("mcp-") || !name.endsWith(".log")) continue;
|
|
16376
|
+
const path = join30(input.logDir, name);
|
|
16377
|
+
let text;
|
|
16378
|
+
try {
|
|
16379
|
+
text = tail(path, statSync15(path).size);
|
|
16380
|
+
} catch {
|
|
16381
|
+
continue;
|
|
16382
|
+
}
|
|
16383
|
+
for (const send of parseCardSends(text.split("\n"))) {
|
|
16384
|
+
if (send.atMs < floor || send.atMs > input.nowMs) continue;
|
|
16385
|
+
sends.set(`${send.accountId}:${send.channelKey}:${send.messageId}`, send);
|
|
16386
|
+
}
|
|
16387
|
+
}
|
|
16388
|
+
}
|
|
16389
|
+
} catch {
|
|
16390
|
+
}
|
|
16391
|
+
let rows = 0;
|
|
16392
|
+
const missingIds = [];
|
|
16393
|
+
for (const send of sends.values()) {
|
|
16394
|
+
if (rowExists(send)) rows += 1;
|
|
16395
|
+
else missingIds.push(send.messageId);
|
|
16396
|
+
}
|
|
16397
|
+
return { sent: sends.size, rows, missing: missingIds.length, missingIds };
|
|
16398
|
+
}
|
|
16399
|
+
function cardRowCensusLine(input) {
|
|
16400
|
+
const c = collectCardRowCensus(input);
|
|
16401
|
+
const head = `${CARD_ROW_CENSUS_TAG} sent=${c.sent} rows=${c.rows} missing=${c.missing} window=60m`;
|
|
16402
|
+
return c.missing > 0 ? `${head} missing-ids=[${c.missingIds.join(",")}]` : head;
|
|
16403
|
+
}
|
|
16404
|
+
function runTelegramCardRowCensus(logDir, nowMs = Date.now()) {
|
|
16405
|
+
console.error(cardRowCensusLine({ logDir, nowMs }));
|
|
16406
|
+
}
|
|
16407
|
+
|
|
16301
16408
|
// app/lib/telegram/reach-census.ts
|
|
16302
16409
|
var import_dist4 = __toESM(require_dist2(), 1);
|
|
16303
16410
|
import { existsSync as existsSync21 } from "fs";
|
|
16304
|
-
import { join as
|
|
16411
|
+
import { join as join31 } from "path";
|
|
16305
16412
|
function collectTelegramReachCensus(accounts) {
|
|
16306
16413
|
const out = {
|
|
16307
16414
|
accounts: accounts.length,
|
|
@@ -16311,7 +16418,7 @@ function collectTelegramReachCensus(accounts) {
|
|
|
16311
16418
|
};
|
|
16312
16419
|
for (const account of accounts) {
|
|
16313
16420
|
const reach = (0, import_dist4.collectTelegramReach)({
|
|
16314
|
-
storeDir:
|
|
16421
|
+
storeDir: join31(STORE_ROOT2(), account.accountId),
|
|
16315
16422
|
bots: account.bots
|
|
16316
16423
|
});
|
|
16317
16424
|
for (const bot of reach.bots) {
|
|
@@ -16365,7 +16472,7 @@ function runTelegramCheckoutCensus(bots, now) {
|
|
|
16365
16472
|
}
|
|
16366
16473
|
|
|
16367
16474
|
// app/lib/telegram/media-census.ts
|
|
16368
|
-
import { join as
|
|
16475
|
+
import { join as join32, resolve as resolve20 } from "path";
|
|
16369
16476
|
function idsByTarget(rows) {
|
|
16370
16477
|
const out = /* @__PURE__ */ new Map();
|
|
16371
16478
|
for (const row of rows) {
|
|
@@ -16446,8 +16553,8 @@ function readWaOperatorTurns() {
|
|
|
16446
16553
|
}
|
|
16447
16554
|
|
|
16448
16555
|
// server/routes/session-reader.ts
|
|
16449
|
-
import { readFileSync as
|
|
16450
|
-
import { isAbsolute as isAbsolute2, join as
|
|
16556
|
+
import { readFileSync as readFileSync25, watch as watch4, statSync as statSync16, existsSync as existsSync22, readdirSync as readdirSync16, realpathSync as realpathSync5 } from "fs";
|
|
16557
|
+
import { isAbsolute as isAbsolute2, join as join33, relative as relative3, resolve as resolve21, sep as sep5 } from "path";
|
|
16451
16558
|
|
|
16452
16559
|
// server/routes/admin/manager-client.ts
|
|
16453
16560
|
var SESSION_ID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -16552,7 +16659,7 @@ function openTaskKey(turns) {
|
|
|
16552
16659
|
}
|
|
16553
16660
|
function readSubagentMeta(dir, hex) {
|
|
16554
16661
|
try {
|
|
16555
|
-
const m = JSON.parse(
|
|
16662
|
+
const m = JSON.parse(readFileSync25(join33(dir, `agent-${hex}.meta.json`), "utf8"));
|
|
16556
16663
|
if (typeof m.agentType === "string" && typeof m.description === "string" && typeof m.toolUseId === "string") {
|
|
16557
16664
|
return { agentType: m.agentType, description: m.description, toolUseId: m.toolUseId };
|
|
16558
16665
|
}
|
|
@@ -16575,7 +16682,7 @@ function runActivityTick(c) {
|
|
|
16575
16682
|
c.parentGrewThisTick = false;
|
|
16576
16683
|
let names = [];
|
|
16577
16684
|
try {
|
|
16578
|
-
names =
|
|
16685
|
+
names = readdirSync16(c.subagentsDir).filter((n) => AGENT_JSONL_RE.test(n));
|
|
16579
16686
|
} catch {
|
|
16580
16687
|
}
|
|
16581
16688
|
const entries2 = [];
|
|
@@ -16584,7 +16691,7 @@ function runActivityTick(c) {
|
|
|
16584
16691
|
let size = 0;
|
|
16585
16692
|
let mtimeMs = 0;
|
|
16586
16693
|
try {
|
|
16587
|
-
const st =
|
|
16694
|
+
const st = statSync16(join33(c.subagentsDir, name));
|
|
16588
16695
|
size = st.size;
|
|
16589
16696
|
mtimeMs = st.mtimeMs;
|
|
16590
16697
|
} catch {
|
|
@@ -16629,11 +16736,11 @@ app7.get("/stream", requireAdminSession, (c) => {
|
|
|
16629
16736
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
16630
16737
|
const projectDir = c.req.query("projectDir") ?? "";
|
|
16631
16738
|
const cfg = claudeConfigDir();
|
|
16632
|
-
const projectsRoot = cfg ? resolve21(
|
|
16739
|
+
const projectsRoot = cfg ? resolve21(join33(cfg, "projects")) : null;
|
|
16633
16740
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
|
|
16634
16741
|
return c.json({ error: "bad session reference" }, 400);
|
|
16635
16742
|
}
|
|
16636
|
-
const jsonlPath = resolve21(
|
|
16743
|
+
const jsonlPath = resolve21(join33(projectDir, `${sessionId}.jsonl`));
|
|
16637
16744
|
if (!jsonlPath.startsWith(projectsRoot + sep5)) {
|
|
16638
16745
|
return c.json({ error: "bad session reference" }, 400);
|
|
16639
16746
|
}
|
|
@@ -16653,7 +16760,7 @@ data: ${JSON.stringify(turn)}
|
|
|
16653
16760
|
start(controller) {
|
|
16654
16761
|
const fileEnd0 = (() => {
|
|
16655
16762
|
try {
|
|
16656
|
-
return
|
|
16763
|
+
return statSync16(jsonlPath).size;
|
|
16657
16764
|
} catch {
|
|
16658
16765
|
return 0;
|
|
16659
16766
|
}
|
|
@@ -16661,7 +16768,7 @@ data: ${JSON.stringify(turn)}
|
|
|
16661
16768
|
let offset = resumeOffset(lastEventId, fileEnd0);
|
|
16662
16769
|
console.log(`[wa-stream] op=open conn=${connId} sessionId=${sessionId} channel=reader resume=${offset}`);
|
|
16663
16770
|
const sessionKey = c.req.query("session_key") ?? "";
|
|
16664
|
-
const subagentsDir = resolve21(
|
|
16771
|
+
const subagentsDir = resolve21(join33(projectDir, sessionId, "subagents"));
|
|
16665
16772
|
console.log(
|
|
16666
16773
|
`[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${existsSync22(subagentsDir)}`
|
|
16667
16774
|
);
|
|
@@ -16814,11 +16921,11 @@ app7.get("/backfill", requireAdminSession, (c) => {
|
|
|
16814
16921
|
const beforeRaw = c.req.query("before") ?? "";
|
|
16815
16922
|
const before = Number(beforeRaw);
|
|
16816
16923
|
const cfg = claudeConfigDir();
|
|
16817
|
-
const projectsRoot = cfg ? resolve21(
|
|
16924
|
+
const projectsRoot = cfg ? resolve21(join33(cfg, "projects")) : null;
|
|
16818
16925
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId) || beforeRaw === "" || !Number.isFinite(before) || before < 0) {
|
|
16819
16926
|
return c.json({ error: "bad session reference" }, 400);
|
|
16820
16927
|
}
|
|
16821
|
-
const jsonlPath = resolve21(
|
|
16928
|
+
const jsonlPath = resolve21(join33(projectDir, `${sessionId}.jsonl`));
|
|
16822
16929
|
if (!jsonlPath.startsWith(projectsRoot + sep5)) {
|
|
16823
16930
|
return c.json({ error: "bad session reference" }, 400);
|
|
16824
16931
|
}
|
|
@@ -16830,7 +16937,7 @@ app7.get("/backfill", requireAdminSession, (c) => {
|
|
|
16830
16937
|
const scratchpadRoot = sessionScratchpadRoot(projectDir, sessionId);
|
|
16831
16938
|
const fileEnd = (() => {
|
|
16832
16939
|
try {
|
|
16833
|
-
return
|
|
16940
|
+
return statSync16(jsonlPath).size;
|
|
16834
16941
|
} catch {
|
|
16835
16942
|
return 0;
|
|
16836
16943
|
}
|
|
@@ -16873,7 +16980,7 @@ app7.get("/directives", requireAdminSession, (c) => {
|
|
|
16873
16980
|
if (!dir || !existsSync22(dir)) return c.json({ entries: [] });
|
|
16874
16981
|
let names;
|
|
16875
16982
|
try {
|
|
16876
|
-
names =
|
|
16983
|
+
names = readdirSync16(dir).filter((n) => DIRECTIVE_NAME_RE.test(n));
|
|
16877
16984
|
} catch {
|
|
16878
16985
|
return c.json({ entries: [] });
|
|
16879
16986
|
}
|
|
@@ -16883,7 +16990,7 @@ app7.get("/directives", requireAdminSession, (c) => {
|
|
|
16883
16990
|
const pid = Number(pidPart);
|
|
16884
16991
|
let len = 0;
|
|
16885
16992
|
try {
|
|
16886
|
-
len =
|
|
16993
|
+
len = statSync16(join33(dir, name)).size;
|
|
16887
16994
|
} catch {
|
|
16888
16995
|
}
|
|
16889
16996
|
return { name, secs, pid, ts: Number.isFinite(secs) ? new Date(secs * 1e3).toISOString() : null, len };
|
|
@@ -16898,11 +17005,11 @@ app7.get("/directive", requireAdminSession, (c) => {
|
|
|
16898
17005
|
}
|
|
16899
17006
|
const dir = directiveStoreDir(sessionId);
|
|
16900
17007
|
if (!dir) return c.json({ error: "no account" }, 404);
|
|
16901
|
-
const path = resolve21(
|
|
17008
|
+
const path = resolve21(join33(dir, name));
|
|
16902
17009
|
if (!path.startsWith(dir + sep5)) return c.json({ error: "bad reference" }, 400);
|
|
16903
17010
|
let body;
|
|
16904
17011
|
try {
|
|
16905
|
-
body =
|
|
17012
|
+
body = readFileSync25(path, "utf8");
|
|
16906
17013
|
} catch {
|
|
16907
17014
|
return c.json({ error: "not found" }, 404);
|
|
16908
17015
|
}
|
|
@@ -16911,8 +17018,8 @@ app7.get("/directive", requireAdminSession, (c) => {
|
|
|
16911
17018
|
var session_reader_default = app7;
|
|
16912
17019
|
|
|
16913
17020
|
// server/routes/operator-conversations.ts
|
|
16914
|
-
import { readFileSync as
|
|
16915
|
-
import { basename as basename9, dirname as dirname9, join as
|
|
17021
|
+
import { readFileSync as readFileSync26 } from "fs";
|
|
17022
|
+
import { basename as basename9, dirname as dirname9, join as join34 } from "path";
|
|
16916
17023
|
|
|
16917
17024
|
// app/lib/reader/operator-conversations.ts
|
|
16918
17025
|
function operatorConvName(row) {
|
|
@@ -17000,7 +17107,7 @@ app8.get("/conversations", requireAdminSession, async (c) => {
|
|
|
17000
17107
|
}
|
|
17001
17108
|
const cfg = claudeConfigDir();
|
|
17002
17109
|
if (!cfg) return c.json({ conversations: [] });
|
|
17003
|
-
const projectsRoot =
|
|
17110
|
+
const projectsRoot = join34(cfg, "projects");
|
|
17004
17111
|
const userTitles = loadUserTitles(ACCOUNTS_DIR ?? null);
|
|
17005
17112
|
const rows = [];
|
|
17006
17113
|
let sessionRowsExcludedUntagged = 0;
|
|
@@ -17018,7 +17125,7 @@ app8.get("/conversations", requireAdminSession, async (c) => {
|
|
|
17018
17125
|
enumeratedCount += 1;
|
|
17019
17126
|
const sessionId = basename9(path).replace(/\.jsonl$/, "");
|
|
17020
17127
|
const projectDir = dirname9(path);
|
|
17021
|
-
const meta = readSidecarMeta(
|
|
17128
|
+
const meta = readSidecarMeta(join34(projectDir, `${sessionId}.meta.json`));
|
|
17022
17129
|
if (!isReaderChannelSession(meta.role, meta.channel)) continue;
|
|
17023
17130
|
if (multiAccount) {
|
|
17024
17131
|
if (meta.accountId === null) {
|
|
@@ -17030,7 +17137,7 @@ app8.get("/conversations", requireAdminSession, async (c) => {
|
|
|
17030
17137
|
let body = "";
|
|
17031
17138
|
let bodyRead = false;
|
|
17032
17139
|
try {
|
|
17033
|
-
body =
|
|
17140
|
+
body = readFileSync26(path, "utf8");
|
|
17034
17141
|
bodyRead = true;
|
|
17035
17142
|
bodyReadCount += 1;
|
|
17036
17143
|
} catch (err) {
|
|
@@ -17206,7 +17313,7 @@ app8.get("/conversations-all", requireAdminSession, async (c) => {
|
|
|
17206
17313
|
const { value, state } = await getOrCompute("conversations-all", houseId, async () => {
|
|
17207
17314
|
const cfg = claudeConfigDir();
|
|
17208
17315
|
if (!cfg) return { conversations: [] };
|
|
17209
|
-
const projectsRoot =
|
|
17316
|
+
const projectsRoot = join34(cfg, "projects");
|
|
17210
17317
|
const userTitles = loadUserTitles(ACCOUNTS_DIR ?? null);
|
|
17211
17318
|
const validAccounts = listValidAccounts();
|
|
17212
17319
|
const validIds = new Set(validAccounts.map((a) => a.accountId));
|
|
@@ -17226,7 +17333,7 @@ app8.get("/conversations-all", requireAdminSession, async (c) => {
|
|
|
17226
17333
|
enumeratedCount += 1;
|
|
17227
17334
|
const sessionId = basename9(path).replace(/\.jsonl$/, "");
|
|
17228
17335
|
const projectDir = dirname9(path);
|
|
17229
|
-
const meta = readSidecarMeta(
|
|
17336
|
+
const meta = readSidecarMeta(join34(projectDir, `${sessionId}.meta.json`));
|
|
17230
17337
|
if (!isReaderChannelSession(meta.role, meta.channel)) continue;
|
|
17231
17338
|
if (meta.accountId === null) {
|
|
17232
17339
|
untaggedCount += 1;
|
|
@@ -17237,7 +17344,7 @@ app8.get("/conversations-all", requireAdminSession, async (c) => {
|
|
|
17237
17344
|
let body = "";
|
|
17238
17345
|
let bodyRead = false;
|
|
17239
17346
|
try {
|
|
17240
|
-
body =
|
|
17347
|
+
body = readFileSync26(path, "utf8");
|
|
17241
17348
|
bodyRead = true;
|
|
17242
17349
|
bodyReadCount += 1;
|
|
17243
17350
|
} catch (err) {
|
|
@@ -17362,8 +17469,8 @@ app8.get("/conversations-all", requireAdminSession, async (c) => {
|
|
|
17362
17469
|
var operator_conversations_default = app8;
|
|
17363
17470
|
|
|
17364
17471
|
// server/routes/public-reader.ts
|
|
17365
|
-
import { statSync as
|
|
17366
|
-
import { basename as basename10, dirname as dirname10, join as
|
|
17472
|
+
import { statSync as statSync18, watch as watch6, readFileSync as readFileSync27, readdirSync as readdirSync18 } from "fs";
|
|
17473
|
+
import { basename as basename10, dirname as dirname10, join as join35, resolve as resolve23, sep as sep7 } from "path";
|
|
17367
17474
|
|
|
17368
17475
|
// app/lib/reader/delivered-kinds.ts
|
|
17369
17476
|
var PUBLIC_DELIVERED_KINDS = /* @__PURE__ */ new Set([
|
|
@@ -17452,10 +17559,10 @@ function enumeratePublicRows() {
|
|
|
17452
17559
|
const cfg = claudeConfigDir();
|
|
17453
17560
|
if (!cfg) return [];
|
|
17454
17561
|
const rows = [];
|
|
17455
|
-
for (const { path } of enumerateJsonls(
|
|
17562
|
+
for (const { path } of enumerateJsonls(join35(cfg, "projects"))) {
|
|
17456
17563
|
const sessionId = basename10(path).replace(/\.jsonl$/, "");
|
|
17457
17564
|
const projectDir = dirname10(path);
|
|
17458
|
-
const meta = readSidecarMeta(
|
|
17565
|
+
const meta = readSidecarMeta(join35(projectDir, `${sessionId}.meta.json`));
|
|
17459
17566
|
rows.push({
|
|
17460
17567
|
sessionId,
|
|
17461
17568
|
projectDir,
|
|
@@ -17522,15 +17629,15 @@ app9.get("/backfill", (c) => {
|
|
|
17522
17629
|
const beforeRaw = c.req.query("before") ?? "";
|
|
17523
17630
|
const before = Number(beforeRaw);
|
|
17524
17631
|
const cfg = claudeConfigDir();
|
|
17525
|
-
const projectsRoot = cfg ? resolve23(
|
|
17632
|
+
const projectsRoot = cfg ? resolve23(join35(cfg, "projects")) : null;
|
|
17526
17633
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId) || beforeRaw === "" || !Number.isFinite(before) || before < 0) {
|
|
17527
17634
|
return c.json({ error: "bad session reference" }, 400);
|
|
17528
17635
|
}
|
|
17529
|
-
const jsonlPath = resolve23(
|
|
17636
|
+
const jsonlPath = resolve23(join35(projectDir, `${sessionId}.jsonl`));
|
|
17530
17637
|
if (!jsonlPath.startsWith(projectsRoot + sep7)) {
|
|
17531
17638
|
return c.json({ error: "bad session reference" }, 400);
|
|
17532
17639
|
}
|
|
17533
|
-
const meta = readSidecarMeta(
|
|
17640
|
+
const meta = readSidecarMeta(join35(projectDir, `${sessionId}.meta.json`));
|
|
17534
17641
|
const isPublicWebchat = meta.role === "public" && meta.channel === "webchat";
|
|
17535
17642
|
const owns = visitor.kind === "person" ? meta.personId === visitor.personId : meta.personId === null && meta.visitorId === visitor.visitorId;
|
|
17536
17643
|
if (!(isPublicWebchat && owns)) {
|
|
@@ -17546,7 +17653,7 @@ app9.get("/backfill", (c) => {
|
|
|
17546
17653
|
}
|
|
17547
17654
|
const fileEnd = (() => {
|
|
17548
17655
|
try {
|
|
17549
|
-
return
|
|
17656
|
+
return statSync18(jsonlPath).size;
|
|
17550
17657
|
} catch {
|
|
17551
17658
|
return 0;
|
|
17552
17659
|
}
|
|
@@ -17589,15 +17696,15 @@ app9.get("/stream", (c) => {
|
|
|
17589
17696
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
17590
17697
|
const projectDir = c.req.query("projectDir") ?? "";
|
|
17591
17698
|
const cfg = claudeConfigDir();
|
|
17592
|
-
const projectsRoot = cfg ? resolve23(
|
|
17699
|
+
const projectsRoot = cfg ? resolve23(join35(cfg, "projects")) : null;
|
|
17593
17700
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
|
|
17594
17701
|
return c.json({ error: "bad session reference" }, 400);
|
|
17595
17702
|
}
|
|
17596
|
-
const jsonlPath = resolve23(
|
|
17703
|
+
const jsonlPath = resolve23(join35(projectDir, `${sessionId}.jsonl`));
|
|
17597
17704
|
if (!jsonlPath.startsWith(projectsRoot + sep7)) {
|
|
17598
17705
|
return c.json({ error: "bad session reference" }, 400);
|
|
17599
17706
|
}
|
|
17600
|
-
const meta = readSidecarMeta(
|
|
17707
|
+
const meta = readSidecarMeta(join35(projectDir, `${sessionId}.meta.json`));
|
|
17601
17708
|
const isPublicWebchat = meta.role === "public" && meta.channel === "webchat";
|
|
17602
17709
|
const owns = visitor.kind === "person" ? meta.personId === visitor.personId : meta.personId === null && meta.visitorId === visitor.visitorId;
|
|
17603
17710
|
if (!(isPublicWebchat && owns)) {
|
|
@@ -17626,7 +17733,7 @@ data: ${JSON.stringify(turn)}
|
|
|
17626
17733
|
};
|
|
17627
17734
|
const fileEnd0 = (() => {
|
|
17628
17735
|
try {
|
|
17629
|
-
return
|
|
17736
|
+
return statSync18(jsonlPath).size;
|
|
17630
17737
|
} catch {
|
|
17631
17738
|
return 0;
|
|
17632
17739
|
}
|
|
@@ -17741,9 +17848,9 @@ app9.get("/attachment/:attachmentId", (c) => {
|
|
|
17741
17848
|
let dataFile;
|
|
17742
17849
|
let buffer;
|
|
17743
17850
|
try {
|
|
17744
|
-
dataFile =
|
|
17851
|
+
dataFile = readdirSync18(dir).find((f) => !f.endsWith(".meta.json") && !f.endsWith(EXTRACTED_TEXT_SUFFIX));
|
|
17745
17852
|
if (!dataFile) throw new Error("no data file");
|
|
17746
|
-
buffer =
|
|
17853
|
+
buffer = readFileSync27(resolve23(dir, dataFile));
|
|
17747
17854
|
} catch {
|
|
17748
17855
|
console.error(`${ATT_TAG} op=denied session=${ses} att=${at} reason=not-found`);
|
|
17749
17856
|
return new Response("Not found", { status: 404 });
|
|
@@ -17765,20 +17872,20 @@ var public_reader_default = app9;
|
|
|
17765
17872
|
|
|
17766
17873
|
// server/routes/webchat.ts
|
|
17767
17874
|
import { basename as basename11, dirname as dirname11 } from "path";
|
|
17768
|
-
import { join as
|
|
17769
|
-
import { existsSync as existsSync25, readdirSync as
|
|
17875
|
+
import { join as join38 } from "path";
|
|
17876
|
+
import { existsSync as existsSync25, readdirSync as readdirSync20, readFileSync as readFileSync30, renameSync as renameSync4, statSync as statSync19, writeFileSync as writeFileSync11 } from "fs";
|
|
17770
17877
|
|
|
17771
17878
|
// server/canonical-webchat-override.ts
|
|
17772
|
-
import { readFileSync as
|
|
17773
|
-
import { join as
|
|
17879
|
+
import { readFileSync as readFileSync28, writeFileSync as writeFileSync9, renameSync as renameSync2 } from "fs";
|
|
17880
|
+
import { join as join36 } from "path";
|
|
17774
17881
|
var FILE = "canonical-webchat-session.json";
|
|
17775
17882
|
var UUID2 = /^[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}$/;
|
|
17776
17883
|
function canonicalOverridePath(accountDir) {
|
|
17777
|
-
return
|
|
17884
|
+
return join36(accountDir, FILE);
|
|
17778
17885
|
}
|
|
17779
17886
|
function readRaw(accountDir) {
|
|
17780
17887
|
try {
|
|
17781
|
-
return JSON.parse(
|
|
17888
|
+
return JSON.parse(readFileSync28(canonicalOverridePath(accountDir), "utf8"));
|
|
17782
17889
|
} catch {
|
|
17783
17890
|
return null;
|
|
17784
17891
|
}
|
|
@@ -17891,8 +17998,8 @@ function isNewSessionEffortLevel(value) {
|
|
|
17891
17998
|
}
|
|
17892
17999
|
|
|
17893
18000
|
// ../services/claude-session-manager/src/sidecar-store.ts
|
|
17894
|
-
import { existsSync as existsSync24, mkdirSync as mkdirSync4, readdirSync as
|
|
17895
|
-
import { join as
|
|
18001
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync4, readdirSync as readdirSync19, readFileSync as readFileSync29, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync10 } from "fs";
|
|
18002
|
+
import { join as join37 } from "path";
|
|
17896
18003
|
function escapeRegExp(s) {
|
|
17897
18004
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
17898
18005
|
}
|
|
@@ -17900,7 +18007,7 @@ function createSidecarStore(config) {
|
|
|
17900
18007
|
const { suffix, validate: validate3 } = config;
|
|
17901
18008
|
const suffixRe = new RegExp(`${escapeRegExp(suffix)}$`);
|
|
17902
18009
|
function pathFor(sessionsDir, id) {
|
|
17903
|
-
return
|
|
18010
|
+
return join37(sessionsDir, `${id}${suffix}`);
|
|
17904
18011
|
}
|
|
17905
18012
|
function write(sessionsDir, id, record) {
|
|
17906
18013
|
mkdirSync4(sessionsDir, { recursive: true });
|
|
@@ -17921,7 +18028,7 @@ function createSidecarStore(config) {
|
|
|
17921
18028
|
function readFileAt(path) {
|
|
17922
18029
|
let raw;
|
|
17923
18030
|
try {
|
|
17924
|
-
raw =
|
|
18031
|
+
raw = readFileSync29(path, "utf8");
|
|
17925
18032
|
} catch {
|
|
17926
18033
|
return null;
|
|
17927
18034
|
}
|
|
@@ -17937,17 +18044,17 @@ function createSidecarStore(config) {
|
|
|
17937
18044
|
function readAll3(sessionsDir, onSkip) {
|
|
17938
18045
|
let names;
|
|
17939
18046
|
try {
|
|
17940
|
-
names =
|
|
18047
|
+
names = readdirSync19(sessionsDir, { withFileTypes: true }).filter((entry3) => entry3.isFile()).map((entry3) => entry3.name);
|
|
17941
18048
|
} catch {
|
|
17942
18049
|
return [];
|
|
17943
18050
|
}
|
|
17944
18051
|
const out = [];
|
|
17945
18052
|
for (const name of names) {
|
|
17946
18053
|
if (!suffixRe.test(name)) continue;
|
|
17947
|
-
const path =
|
|
18054
|
+
const path = join37(sessionsDir, name);
|
|
17948
18055
|
let raw;
|
|
17949
18056
|
try {
|
|
17950
|
-
raw =
|
|
18057
|
+
raw = readFileSync29(path, "utf8");
|
|
17951
18058
|
} catch {
|
|
17952
18059
|
onSkip?.(name, "unreadable");
|
|
17953
18060
|
continue;
|
|
@@ -18020,7 +18127,7 @@ var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9
|
|
|
18020
18127
|
function locateSession(sessionId) {
|
|
18021
18128
|
const dir = findSessionProjectDir(sessionId);
|
|
18022
18129
|
if (!dir) return { projectDir: null, channel: null, accountId: null };
|
|
18023
|
-
const meta = readSidecarMeta(
|
|
18130
|
+
const meta = readSidecarMeta(join38(dir, `${sessionId}.meta.json`));
|
|
18024
18131
|
return { projectDir: dir, channel: meta.channel, accountId: meta.accountId };
|
|
18025
18132
|
}
|
|
18026
18133
|
function resolveQuoted(sessionId, quotedUuid, sendId) {
|
|
@@ -18038,7 +18145,7 @@ function resolveQuoted(sessionId, quotedUuid, sendId) {
|
|
|
18038
18145
|
let line;
|
|
18039
18146
|
try {
|
|
18040
18147
|
const needle = `"uuid":"${quotedUuid}"`;
|
|
18041
|
-
line =
|
|
18148
|
+
line = readFileSync30(join38(projectDir, `${sessionId}.jsonl`), "utf8").split("\n").find((l) => l.includes(needle));
|
|
18042
18149
|
} catch {
|
|
18043
18150
|
log2(false, 0);
|
|
18044
18151
|
return void 0;
|
|
@@ -18055,15 +18162,15 @@ function resolveQuoted(sessionId, quotedUuid, sendId) {
|
|
|
18055
18162
|
function locateSidecar(sessionId) {
|
|
18056
18163
|
const cfg = claudeConfigDir();
|
|
18057
18164
|
if (!cfg) return null;
|
|
18058
|
-
const projectsRoot =
|
|
18165
|
+
const projectsRoot = join38(cfg, "projects");
|
|
18059
18166
|
let slugs;
|
|
18060
18167
|
try {
|
|
18061
|
-
slugs =
|
|
18168
|
+
slugs = readdirSync20(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
18062
18169
|
} catch {
|
|
18063
18170
|
return null;
|
|
18064
18171
|
}
|
|
18065
18172
|
for (const slug of slugs) {
|
|
18066
|
-
const metaPath =
|
|
18173
|
+
const metaPath = join38(projectsRoot, slug, `${sessionId}.meta.json`);
|
|
18067
18174
|
if (existsSync25(metaPath)) return readSidecarMeta(metaPath);
|
|
18068
18175
|
}
|
|
18069
18176
|
return null;
|
|
@@ -18073,7 +18180,7 @@ function readTargetOwner(sessionId) {
|
|
|
18073
18180
|
if (sidecar !== null) return { found: true, owner: sidecar.adminUserId };
|
|
18074
18181
|
const { projectDir } = locateSession(sessionId);
|
|
18075
18182
|
if (projectDir !== null) {
|
|
18076
|
-
return { found: true, owner: readSidecarMeta(
|
|
18183
|
+
return { found: true, owner: readSidecarMeta(join38(projectDir, `${sessionId}.meta.json`)).adminUserId };
|
|
18077
18184
|
}
|
|
18078
18185
|
return { found: false, owner: null };
|
|
18079
18186
|
}
|
|
@@ -18081,7 +18188,7 @@ function readSourceRowMeta(sessionId) {
|
|
|
18081
18188
|
const sidecar = locateSidecar(sessionId);
|
|
18082
18189
|
if (sidecar !== null) return sidecar;
|
|
18083
18190
|
const { projectDir } = locateSession(sessionId);
|
|
18084
|
-
if (projectDir !== null) return readSidecarMeta(
|
|
18191
|
+
if (projectDir !== null) return readSidecarMeta(join38(projectDir, `${sessionId}.meta.json`));
|
|
18085
18192
|
return null;
|
|
18086
18193
|
}
|
|
18087
18194
|
function ownedByRequester(owner, requesterUserId, primaryUserId) {
|
|
@@ -18094,7 +18201,7 @@ function sessionSidecarExists(sessionId) {
|
|
|
18094
18201
|
function jsonlSizeBytes(projectDir, sessionId) {
|
|
18095
18202
|
if (projectDir === null) return null;
|
|
18096
18203
|
try {
|
|
18097
|
-
return
|
|
18204
|
+
return statSync19(join38(projectDir, `${sessionId}.jsonl`)).size;
|
|
18098
18205
|
} catch {
|
|
18099
18206
|
return null;
|
|
18100
18207
|
}
|
|
@@ -18222,15 +18329,15 @@ function latestAdminWebchatSessionId(requesterUserId, primaryUserId, scopeAccoun
|
|
|
18222
18329
|
const cfg = claudeConfigDir();
|
|
18223
18330
|
if (!cfg) return null;
|
|
18224
18331
|
let best = null;
|
|
18225
|
-
for (const { path, isSubagent, archived } of enumerateJsonls(
|
|
18332
|
+
for (const { path, isSubagent, archived } of enumerateJsonls(join38(cfg, "projects"))) {
|
|
18226
18333
|
if (isSubagent || archived) continue;
|
|
18227
18334
|
const id = basename11(path).slice(0, -".jsonl".length);
|
|
18228
|
-
const meta = readSidecarMeta(
|
|
18335
|
+
const meta = readSidecarMeta(join38(dirname11(path), `${id}.meta.json`));
|
|
18229
18336
|
if (meta.role !== "admin" || meta.channel !== "webchat") continue;
|
|
18230
18337
|
if (multiAccount && meta.accountId !== scopeAccountId) continue;
|
|
18231
18338
|
let mtimeMs;
|
|
18232
18339
|
try {
|
|
18233
|
-
mtimeMs =
|
|
18340
|
+
mtimeMs = statSync19(path).mtimeMs;
|
|
18234
18341
|
} catch {
|
|
18235
18342
|
continue;
|
|
18236
18343
|
}
|
|
@@ -18585,9 +18692,9 @@ ${timeline}`;
|
|
|
18585
18692
|
console.error(`[webchat:settings] op=${op} outcome=refused value=${value} accountId=none reason=no-account-for-session`);
|
|
18586
18693
|
return c.json({ error: "account unresolved" }, 503);
|
|
18587
18694
|
}
|
|
18588
|
-
const accountJsonPath =
|
|
18695
|
+
const accountJsonPath = join38(account.accountDir, "account.json");
|
|
18589
18696
|
try {
|
|
18590
|
-
const parsed = JSON.parse(
|
|
18697
|
+
const parsed = JSON.parse(readFileSync30(accountJsonPath, "utf8"));
|
|
18591
18698
|
if (op === "model") parsed.adminModel = value;
|
|
18592
18699
|
else if (op === "effort") parsed.effort = value;
|
|
18593
18700
|
else parsed.adminPermissionMode = value;
|
|
@@ -18633,7 +18740,7 @@ ${timeline}`;
|
|
|
18633
18740
|
const cfg2 = claudeConfigDir();
|
|
18634
18741
|
if (cfg2) {
|
|
18635
18742
|
const source2 = resolveBridgeSource(
|
|
18636
|
-
|
|
18743
|
+
join38(cfg2, "sessions"),
|
|
18637
18744
|
target,
|
|
18638
18745
|
(id) => locateSession(id).projectDir !== null
|
|
18639
18746
|
);
|
|
@@ -18660,7 +18767,7 @@ ${timeline}`;
|
|
|
18660
18767
|
const cfg = claudeConfigDir();
|
|
18661
18768
|
let projectDir = null;
|
|
18662
18769
|
if (cfg) {
|
|
18663
|
-
for (const { path } of enumerateJsonls(
|
|
18770
|
+
for (const { path } of enumerateJsonls(join38(cfg, "projects"))) {
|
|
18664
18771
|
if (basename11(path) === `${sessionId}.jsonl`) {
|
|
18665
18772
|
projectDir = dirname11(path);
|
|
18666
18773
|
break;
|
|
@@ -18668,7 +18775,7 @@ ${timeline}`;
|
|
|
18668
18775
|
}
|
|
18669
18776
|
}
|
|
18670
18777
|
if (source === "latest" && requesterUserId !== null) {
|
|
18671
|
-
const owner = readSidecarMeta(
|
|
18778
|
+
const owner = readSidecarMeta(join38(projectDir ?? "", `${sessionId}.meta.json`)).adminUserId;
|
|
18672
18779
|
if (owner !== null && owner !== requesterUserId && requesterUserId !== primaryUserId) {
|
|
18673
18780
|
console.error(`[webchat:inbound] op=session-resolve-foreign key=${sessionId.slice(0, 8)} owner=${owner.slice(0, 8)} requester=${requesterUserId.slice(0, 8)}`);
|
|
18674
18781
|
}
|
|
@@ -18793,13 +18900,13 @@ var webchat_greeting_default = app10;
|
|
|
18793
18900
|
|
|
18794
18901
|
// server/routes/telegram.ts
|
|
18795
18902
|
import { homedir as homedir2 } from "os";
|
|
18796
|
-
import { resolve as resolve25, join as
|
|
18797
|
-
import { existsSync as existsSync29, readFileSync as
|
|
18903
|
+
import { resolve as resolve25, join as join43 } from "path";
|
|
18904
|
+
import { existsSync as existsSync29, readFileSync as readFileSync34 } from "fs";
|
|
18798
18905
|
|
|
18799
18906
|
// ../lib/telegram-managed-bot/src/index.ts
|
|
18800
18907
|
import { randomBytes } from "crypto";
|
|
18801
|
-
import { existsSync as existsSync26, readFileSync as
|
|
18802
|
-
import { dirname as dirname12, join as
|
|
18908
|
+
import { existsSync as existsSync26, readFileSync as readFileSync31, writeFileSync as writeFileSync12, mkdirSync as mkdirSync5 } from "fs";
|
|
18909
|
+
import { dirname as dirname12, join as join39 } from "path";
|
|
18803
18910
|
var TELEGRAM_API = "https://api.telegram.org";
|
|
18804
18911
|
var TELEGRAM_ALLOWED_UPDATES = [
|
|
18805
18912
|
"message",
|
|
@@ -18866,13 +18973,13 @@ async function setTelegramWebhook(botToken, webhookUrl, secretFilePath, fetchImp
|
|
|
18866
18973
|
return { ok: true, secret };
|
|
18867
18974
|
}
|
|
18868
18975
|
function writeTelegramBotEntry(accountDir, entry3) {
|
|
18869
|
-
const configPath3 =
|
|
18976
|
+
const configPath3 = join39(accountDir, "account.json");
|
|
18870
18977
|
if (!existsSync26(configPath3)) {
|
|
18871
18978
|
return { ok: false, error: `account.json not found at ${configPath3}` };
|
|
18872
18979
|
}
|
|
18873
18980
|
let config;
|
|
18874
18981
|
try {
|
|
18875
|
-
config = JSON.parse(
|
|
18982
|
+
config = JSON.parse(readFileSync31(configPath3, "utf-8"));
|
|
18876
18983
|
} catch (e) {
|
|
18877
18984
|
return { ok: false, error: `account.json parse failed: ${e.message}` };
|
|
18878
18985
|
}
|
|
@@ -19767,7 +19874,7 @@ function routeTelegramUpdate(input) {
|
|
|
19767
19874
|
|
|
19768
19875
|
// app/lib/telegram/inbound/media.ts
|
|
19769
19876
|
var import_dist5 = __toESM(require_dist4(), 1);
|
|
19770
|
-
import { join as
|
|
19877
|
+
import { join as join40 } from "path";
|
|
19771
19878
|
var TAG30 = "[telegram-inbound]";
|
|
19772
19879
|
var TELEGRAM_MEDIA_DIR = "/tmp/maxy-media";
|
|
19773
19880
|
var DOWNLOAD_TIMEOUT_MS = 45e3;
|
|
@@ -19795,7 +19902,7 @@ async function downloadTelegramMedia(input) {
|
|
|
19795
19902
|
if (!meta.ok) {
|
|
19796
19903
|
result = { ...base, failure: meta.failure };
|
|
19797
19904
|
} else {
|
|
19798
|
-
const path =
|
|
19905
|
+
const path = join40(
|
|
19799
19906
|
dir,
|
|
19800
19907
|
`tg-${(0, import_dist5.pathSafe)(input.botId)}-${(0, import_dist5.pathSafe)(item.fileUniqueId)}.${(0, import_dist5.extensionFor)(meta.filePath, item.mimetype)}`
|
|
19801
19908
|
);
|
|
@@ -20662,8 +20769,8 @@ async function handleDispatchMedia(p) {
|
|
|
20662
20769
|
}
|
|
20663
20770
|
|
|
20664
20771
|
// app/lib/telegram/live-location.ts
|
|
20665
|
-
import { existsSync as existsSync27, mkdirSync as mkdirSync6, readFileSync as
|
|
20666
|
-
import { join as
|
|
20772
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync6, readFileSync as readFileSync32, readdirSync as readdirSync21, statSync as statSync20, writeFileSync as writeFileSync13 } from "fs";
|
|
20773
|
+
import { join as join41 } from "path";
|
|
20667
20774
|
var TAG37 = "[telegram-inbound]";
|
|
20668
20775
|
var LIVE_LOCATION_FILE = "telegram-live-location.json";
|
|
20669
20776
|
var LIVE_LOCATION_CENSUS_TAG = "[telegram-live-location-census]";
|
|
@@ -20678,7 +20785,7 @@ function isRecord(v) {
|
|
|
20678
20785
|
function readAll(path) {
|
|
20679
20786
|
if (!existsSync27(path)) return {};
|
|
20680
20787
|
try {
|
|
20681
|
-
const parsed = JSON.parse(
|
|
20788
|
+
const parsed = JSON.parse(readFileSync32(path, "utf-8"));
|
|
20682
20789
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
20683
20790
|
const out = {};
|
|
20684
20791
|
for (const [k, v] of Object.entries(parsed)) {
|
|
@@ -20695,7 +20802,7 @@ function isExpired(rec, now) {
|
|
|
20695
20802
|
function writeLiveLocation(input) {
|
|
20696
20803
|
const { accountDir, botId, senderId, now, emit } = input;
|
|
20697
20804
|
const key2 = liveLocationKey(botId, senderId);
|
|
20698
|
-
const path =
|
|
20805
|
+
const path = join41(accountDir, LIVE_LOCATION_FILE);
|
|
20699
20806
|
const stored = readAll(path);
|
|
20700
20807
|
const livePeriodS = input.livePeriodS ?? stored[key2]?.livePeriodS ?? null;
|
|
20701
20808
|
if (livePeriodS === null) {
|
|
@@ -20744,9 +20851,9 @@ function liveLocationCensusLine(accountsRoot, now) {
|
|
|
20744
20851
|
let expired = 0;
|
|
20745
20852
|
let oldestAgeMs = 0;
|
|
20746
20853
|
try {
|
|
20747
|
-
for (const entry3 of
|
|
20748
|
-
const path =
|
|
20749
|
-
if (!existsSync27(path) || !
|
|
20854
|
+
for (const entry3 of readdirSync21(accountsRoot)) {
|
|
20855
|
+
const path = join41(accountsRoot, entry3, LIVE_LOCATION_FILE);
|
|
20856
|
+
if (!existsSync27(path) || !statSync20(path).isFile()) continue;
|
|
20750
20857
|
for (const rec of Object.values(readAll(path))) {
|
|
20751
20858
|
records5 += 1;
|
|
20752
20859
|
if (isExpired(rec, now)) expired += 1;
|
|
@@ -20765,8 +20872,8 @@ function liveLocationCensusLine(accountsRoot, now) {
|
|
|
20765
20872
|
}
|
|
20766
20873
|
|
|
20767
20874
|
// app/lib/telegram/business-connection.ts
|
|
20768
|
-
import { existsSync as existsSync28, mkdirSync as mkdirSync7, readFileSync as
|
|
20769
|
-
import { join as
|
|
20875
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync7, readFileSync as readFileSync33, writeFileSync as writeFileSync14 } from "fs";
|
|
20876
|
+
import { join as join42 } from "path";
|
|
20770
20877
|
var TAG38 = "[telegram-inbound]";
|
|
20771
20878
|
var BUSINESS_CONNECTION_FILE = "telegram-business-connection.json";
|
|
20772
20879
|
function truncateConnectionId(id) {
|
|
@@ -20780,7 +20887,7 @@ function isRecord2(v) {
|
|
|
20780
20887
|
function readAll2(path) {
|
|
20781
20888
|
if (!existsSync28(path)) return {};
|
|
20782
20889
|
try {
|
|
20783
|
-
const parsed = JSON.parse(
|
|
20890
|
+
const parsed = JSON.parse(readFileSync33(path, "utf-8"));
|
|
20784
20891
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
20785
20892
|
const out = {};
|
|
20786
20893
|
for (const [k, v] of Object.entries(parsed)) {
|
|
@@ -20816,7 +20923,7 @@ function writeBusinessConnection(input) {
|
|
|
20816
20923
|
rights,
|
|
20817
20924
|
at: now
|
|
20818
20925
|
};
|
|
20819
|
-
const path =
|
|
20926
|
+
const path = join42(accountDir, BUSINESS_CONNECTION_FILE);
|
|
20820
20927
|
const all = readAll2(path);
|
|
20821
20928
|
all[botId] = next;
|
|
20822
20929
|
try {
|
|
@@ -20830,12 +20937,12 @@ function writeBusinessConnection(input) {
|
|
|
20830
20937
|
return { written: true, reason: "ok" };
|
|
20831
20938
|
}
|
|
20832
20939
|
function readBusinessConnection(accountDir, botId) {
|
|
20833
|
-
const rec = readAll2(
|
|
20940
|
+
const rec = readAll2(join42(accountDir, BUSINESS_CONNECTION_FILE))[botId];
|
|
20834
20941
|
if (!rec || !rec.isEnabled) return null;
|
|
20835
20942
|
return rec;
|
|
20836
20943
|
}
|
|
20837
20944
|
function readAllBusinessConnections(accountDir) {
|
|
20838
|
-
return readAll2(
|
|
20945
|
+
return readAll2(join42(accountDir, BUSINESS_CONNECTION_FILE));
|
|
20839
20946
|
}
|
|
20840
20947
|
|
|
20841
20948
|
// app/lib/telegram/business-window.ts
|
|
@@ -20891,10 +20998,10 @@ function logValue4(v) {
|
|
|
20891
20998
|
}
|
|
20892
20999
|
function configDirName() {
|
|
20893
21000
|
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT ?? resolve25(process.cwd(), "..");
|
|
20894
|
-
const brandPath =
|
|
21001
|
+
const brandPath = join43(platformRoot5, "config", "brand.json");
|
|
20895
21002
|
if (existsSync29(brandPath)) {
|
|
20896
21003
|
try {
|
|
20897
|
-
return JSON.parse(
|
|
21004
|
+
return JSON.parse(readFileSync34(brandPath, "utf-8")).configDir ?? ".maxy";
|
|
20898
21005
|
} catch {
|
|
20899
21006
|
}
|
|
20900
21007
|
}
|
|
@@ -20922,7 +21029,7 @@ function provisionedWebhookUrl(c, botId) {
|
|
|
20922
21029
|
}
|
|
20923
21030
|
function accountConfig(accountDir) {
|
|
20924
21031
|
try {
|
|
20925
|
-
return JSON.parse(
|
|
21032
|
+
return JSON.parse(readFileSync34(join43(accountDir, "account.json"), "utf-8"));
|
|
20926
21033
|
} catch {
|
|
20927
21034
|
return {};
|
|
20928
21035
|
}
|
|
@@ -21004,7 +21111,7 @@ app11.post("/", async (c) => {
|
|
|
21004
21111
|
console.error(`${TAG39} op=secret botId=${botId} result=missing-file`);
|
|
21005
21112
|
return c.json({ ok: false }, 401);
|
|
21006
21113
|
}
|
|
21007
|
-
const expected =
|
|
21114
|
+
const expected = readFileSync34(sp, "utf-8").trim();
|
|
21008
21115
|
const got = c.req.header("x-telegram-bot-api-secret-token") ?? "";
|
|
21009
21116
|
if (got !== expected) {
|
|
21010
21117
|
console.error(`${TAG39} op=secret botId=${botId} result=mismatch`);
|
|
@@ -21949,16 +22056,16 @@ function mountTelegramRoutes(app81, telegramRoutes) {
|
|
|
21949
22056
|
}
|
|
21950
22057
|
|
|
21951
22058
|
// server/routes/quickbooks.ts
|
|
21952
|
-
import { join as
|
|
21953
|
-
import { existsSync as existsSync30, readFileSync as
|
|
22059
|
+
import { join as join44 } from "path";
|
|
22060
|
+
import { existsSync as existsSync30, readFileSync as readFileSync35, writeFileSync as writeFileSync15, mkdirSync as mkdirSync8, rmSync as rmSync4, renameSync as renameSync5 } from "fs";
|
|
21954
22061
|
var TAG40 = "[quickbooks]";
|
|
21955
22062
|
var INTUIT_TOKEN_URL = "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer";
|
|
21956
22063
|
var STATE_RE = /^[A-Za-z0-9_-]+$/;
|
|
21957
22064
|
function pendingPath(accountDir, state) {
|
|
21958
|
-
return
|
|
22065
|
+
return join44(accountDir, "secrets", "quickbooks-pending", `${state}.json`);
|
|
21959
22066
|
}
|
|
21960
22067
|
function storePath(accountDir) {
|
|
21961
|
-
return
|
|
22068
|
+
return join44(accountDir, "secrets", "quickbooks.json");
|
|
21962
22069
|
}
|
|
21963
22070
|
async function completeConsent(args) {
|
|
21964
22071
|
const { accountDir, code, realmId } = args;
|
|
@@ -21977,7 +22084,7 @@ async function completeConsent(args) {
|
|
|
21977
22084
|
try {
|
|
21978
22085
|
let pending;
|
|
21979
22086
|
try {
|
|
21980
|
-
pending = JSON.parse(
|
|
22087
|
+
pending = JSON.parse(readFileSync35(claimFile, "utf-8"));
|
|
21981
22088
|
} catch {
|
|
21982
22089
|
console.error(`${TAG40} op=callback state=${state} stateValid=false realmId=${realmId ?? ""}`);
|
|
21983
22090
|
return { ok: false, status: 400, message: "Authorization state could not be read.", stateValid: false };
|
|
@@ -21993,7 +22100,7 @@ async function completeConsent(args) {
|
|
|
21993
22100
|
if (!existsSync30(storePath(accountDir))) {
|
|
21994
22101
|
return { ok: false, status: 500, message: "No QuickBooks credentials are stored for this account.", stateValid: true };
|
|
21995
22102
|
}
|
|
21996
|
-
const store2 = JSON.parse(
|
|
22103
|
+
const store2 = JSON.parse(readFileSync35(storePath(accountDir), "utf-8"));
|
|
21997
22104
|
const form = new URLSearchParams({
|
|
21998
22105
|
grant_type: "authorization_code",
|
|
21999
22106
|
code,
|
|
@@ -22025,9 +22132,9 @@ async function completeConsent(args) {
|
|
|
22025
22132
|
refreshTokenExpiry: now + (body.x_refresh_token_expires_in ?? 864e4) * 1e3,
|
|
22026
22133
|
lastRefresh: now
|
|
22027
22134
|
};
|
|
22028
|
-
mkdirSync8(
|
|
22135
|
+
mkdirSync8(join44(accountDir, "secrets"), { recursive: true });
|
|
22029
22136
|
writeFileSync15(storePath(accountDir), JSON.stringify(store2, null, 2), { mode: 384 });
|
|
22030
|
-
const persisted = JSON.parse(
|
|
22137
|
+
const persisted = JSON.parse(readFileSync35(storePath(accountDir), "utf-8")).connections?.[realmId]?.refreshToken === body.refresh_token;
|
|
22031
22138
|
console.error(`${TAG40} op=token-exchange realmId=${realmId} persisted=${persisted}`);
|
|
22032
22139
|
return { ok: persisted, status: persisted ? 200 : 500, message: persisted ? `Connected company ${realmId}.` : "Failed to persist the connection.", stateValid: true };
|
|
22033
22140
|
} finally {
|
|
@@ -22058,7 +22165,7 @@ var quickbooks_default = app12;
|
|
|
22058
22165
|
|
|
22059
22166
|
// server/routes/onboarding.ts
|
|
22060
22167
|
import { spawn, spawnSync as spawnSync2, execFileSync as execFileSync4 } from "child_process";
|
|
22061
|
-
import { openSync as
|
|
22168
|
+
import { openSync as openSync9, closeSync as closeSync9, appendFileSync as appendFileSync4, writeFileSync as writeFileSync17, writeSync, existsSync as existsSync32, readFileSync as readFileSync37, unlinkSync as unlinkSync3 } from "fs";
|
|
22062
22169
|
import { createHash as createHash4, randomUUID as randomUUID5 } from "crypto";
|
|
22063
22170
|
|
|
22064
22171
|
// app/lib/claude-spawn-env.ts
|
|
@@ -22067,7 +22174,7 @@ function claudeBin() {
|
|
|
22067
22174
|
}
|
|
22068
22175
|
|
|
22069
22176
|
// server/routes/onboarding.ts
|
|
22070
|
-
import { dirname as dirname14, join as
|
|
22177
|
+
import { dirname as dirname14, join as join46 } from "path";
|
|
22071
22178
|
|
|
22072
22179
|
// app/lib/claude-keychain.ts
|
|
22073
22180
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
@@ -22198,19 +22305,19 @@ function readHostCredsBlob(service) {
|
|
|
22198
22305
|
}
|
|
22199
22306
|
|
|
22200
22307
|
// ../lib/admins-write/src/index.ts
|
|
22201
|
-
import { existsSync as existsSync31, readFileSync as
|
|
22202
|
-
import { dirname as dirname13, join as
|
|
22308
|
+
import { existsSync as existsSync31, readFileSync as readFileSync36, writeFileSync as writeFileSync16, renameSync as renameSync6, mkdirSync as mkdirSync9, readdirSync as readdirSync22, statSync as statSync21, appendFileSync as appendFileSync3 } from "fs";
|
|
22309
|
+
import { dirname as dirname13, join as join45 } from "path";
|
|
22203
22310
|
function id8(value) {
|
|
22204
22311
|
return value.slice(0, 8);
|
|
22205
22312
|
}
|
|
22206
22313
|
function formatAuditRowIds(userIds) {
|
|
22207
22314
|
return userIds.map(id8).join(",");
|
|
22208
22315
|
}
|
|
22209
|
-
function appendUsersAuditLine(audit,
|
|
22316
|
+
function appendUsersAuditLine(audit, fields2) {
|
|
22210
22317
|
const sess = audit.session ? ` session=${id8(audit.session)}` : "";
|
|
22211
22318
|
const actor = audit.actor.includes("-") ? id8(audit.actor) : audit.actor;
|
|
22212
22319
|
const targetFields = audit.target !== void 0 ? ` target=${audit.target.includes("-") ? id8(audit.target) : audit.target} explicitUserId=${audit.explicitUserId ? "true" : "false"}` : "";
|
|
22213
|
-
const line = `[users-audit] action=${
|
|
22320
|
+
const line = `[users-audit] action=${fields2.action} actor=${actor}${targetFields}${sess} field=${fields2.field} rowsBefore=${fields2.rowsBefore} rowsAfter=${fields2.rowsAfter} ts=${(/* @__PURE__ */ new Date()).toISOString()}
|
|
22214
22321
|
`;
|
|
22215
22322
|
try {
|
|
22216
22323
|
mkdirSync9(dirname13(audit.logFile), { recursive: true, mode: 448 });
|
|
@@ -22221,8 +22328,8 @@ function appendUsersAuditLine(audit, fields) {
|
|
|
22221
22328
|
);
|
|
22222
22329
|
}
|
|
22223
22330
|
}
|
|
22224
|
-
function logUsersAudit(audit,
|
|
22225
|
-
appendUsersAuditLine(audit,
|
|
22331
|
+
function logUsersAudit(audit, fields2) {
|
|
22332
|
+
appendUsersAuditLine(audit, fields2);
|
|
22226
22333
|
}
|
|
22227
22334
|
function logLine(input, result) {
|
|
22228
22335
|
const userIdShort = input.userId.slice(0, 8);
|
|
@@ -22241,7 +22348,7 @@ function writeAdminEntry(input) {
|
|
|
22241
22348
|
try {
|
|
22242
22349
|
let users = [];
|
|
22243
22350
|
if (existsSync31(input.usersFile)) {
|
|
22244
|
-
const raw =
|
|
22351
|
+
const raw = readFileSync36(input.usersFile, "utf-8").trim();
|
|
22245
22352
|
if (raw) {
|
|
22246
22353
|
const parsed = JSON.parse(raw);
|
|
22247
22354
|
if (!Array.isArray(parsed)) {
|
|
@@ -22283,11 +22390,11 @@ function writeAdminEntry(input) {
|
|
|
22283
22390
|
return result;
|
|
22284
22391
|
}
|
|
22285
22392
|
try {
|
|
22286
|
-
const accountJsonPath =
|
|
22393
|
+
const accountJsonPath = join45(input.accountDir, "account.json");
|
|
22287
22394
|
if (!existsSync31(accountJsonPath)) {
|
|
22288
22395
|
throw new Error(`account.json not found at ${accountJsonPath}`);
|
|
22289
22396
|
}
|
|
22290
|
-
const config = JSON.parse(
|
|
22397
|
+
const config = JSON.parse(readFileSync36(accountJsonPath, "utf-8"));
|
|
22291
22398
|
const admins = config.admins ?? [];
|
|
22292
22399
|
if (admins.some((a) => a.userId === input.userId)) {
|
|
22293
22400
|
result.accountJsonResult = "noop";
|
|
@@ -22309,7 +22416,7 @@ function computeAdminStoreDivergence(input) {
|
|
|
22309
22416
|
const usersUserIds = /* @__PURE__ */ new Set();
|
|
22310
22417
|
if (existsSync31(input.usersFile)) {
|
|
22311
22418
|
try {
|
|
22312
|
-
const raw =
|
|
22419
|
+
const raw = readFileSync36(input.usersFile, "utf-8").trim();
|
|
22313
22420
|
if (raw) {
|
|
22314
22421
|
const users = JSON.parse(raw);
|
|
22315
22422
|
for (const u of users) {
|
|
@@ -22324,24 +22431,24 @@ function computeAdminStoreDivergence(input) {
|
|
|
22324
22431
|
if (existsSync31(input.accountsDir)) {
|
|
22325
22432
|
let entries2;
|
|
22326
22433
|
try {
|
|
22327
|
-
entries2 =
|
|
22434
|
+
entries2 = readdirSync22(input.accountsDir);
|
|
22328
22435
|
} catch (err) {
|
|
22329
22436
|
result.errors.push({ source: input.accountsDir, detail: err instanceof Error ? err.message : String(err) });
|
|
22330
22437
|
return result;
|
|
22331
22438
|
}
|
|
22332
22439
|
for (const entry3 of entries2) {
|
|
22333
22440
|
if (entry3.startsWith(".")) continue;
|
|
22334
|
-
const accountDir =
|
|
22441
|
+
const accountDir = join45(input.accountsDir, entry3);
|
|
22335
22442
|
try {
|
|
22336
|
-
if (!
|
|
22443
|
+
if (!statSync21(accountDir).isDirectory()) continue;
|
|
22337
22444
|
} catch {
|
|
22338
22445
|
continue;
|
|
22339
22446
|
}
|
|
22340
|
-
const accountJsonPath =
|
|
22447
|
+
const accountJsonPath = join45(accountDir, "account.json");
|
|
22341
22448
|
if (!existsSync31(accountJsonPath)) continue;
|
|
22342
22449
|
let admins = [];
|
|
22343
22450
|
try {
|
|
22344
|
-
const config = JSON.parse(
|
|
22451
|
+
const config = JSON.parse(readFileSync36(accountJsonPath, "utf-8"));
|
|
22345
22452
|
admins = config.admins ?? [];
|
|
22346
22453
|
} catch (err) {
|
|
22347
22454
|
result.errors.push({ source: accountJsonPath, detail: err instanceof Error ? err.message : String(err) });
|
|
@@ -22390,7 +22497,7 @@ function hashPin2(pin) {
|
|
|
22390
22497
|
}
|
|
22391
22498
|
function readUsersFile2() {
|
|
22392
22499
|
if (!existsSync32(USERS_FILE)) return null;
|
|
22393
|
-
const raw =
|
|
22500
|
+
const raw = readFileSync37(USERS_FILE, "utf-8").trim();
|
|
22394
22501
|
if (!raw) return [];
|
|
22395
22502
|
return JSON.parse(raw);
|
|
22396
22503
|
}
|
|
@@ -22521,7 +22628,7 @@ app13.post("/claude-auth", async (c) => {
|
|
|
22521
22628
|
ensureLogDir();
|
|
22522
22629
|
appendFileSync4(logPath("claude-auth"), `==== attempt ${attemptId} ${(/* @__PURE__ */ new Date()).toISOString()} ====
|
|
22523
22630
|
`);
|
|
22524
|
-
const claudeAuthLogFd =
|
|
22631
|
+
const claudeAuthLogFd = openSync9(logPath("claude-auth"), "a");
|
|
22525
22632
|
const onClaudeOutput = (chunk) => writeSync(claudeAuthLogFd, chunk);
|
|
22526
22633
|
if (process.platform === "darwin") {
|
|
22527
22634
|
vncLog("claude-auth", { action: "start", transport: "native", platform: "darwin" });
|
|
@@ -22538,7 +22645,7 @@ app13.post("/claude-auth", async (c) => {
|
|
|
22538
22645
|
claudeProc2.stdout?.on("data", onClaudeOutput);
|
|
22539
22646
|
claudeProc2.stderr?.on("data", onClaudeOutput);
|
|
22540
22647
|
claudeProc2.once("close", () => {
|
|
22541
|
-
|
|
22648
|
+
closeSync9(claudeAuthLogFd);
|
|
22542
22649
|
const writebackResult = bridgeKeychainToFile({
|
|
22543
22650
|
platform: process.platform,
|
|
22544
22651
|
before: darwinCredsBefore,
|
|
@@ -22551,7 +22658,7 @@ app13.post("/claude-auth", async (c) => {
|
|
|
22551
22658
|
});
|
|
22552
22659
|
persistKeychainService(
|
|
22553
22660
|
writebackResult,
|
|
22554
|
-
(service) => writeFileSync17(
|
|
22661
|
+
(service) => writeFileSync17(join46(dirname14(CLAUDE_CREDENTIALS_FILE), ".keychain-service"), service, { mode: 384 }),
|
|
22555
22662
|
(line) => console.log(line)
|
|
22556
22663
|
);
|
|
22557
22664
|
if (pendingAuthLogin?.child === claudeProc2) pendingAuthLogin = null;
|
|
@@ -22576,7 +22683,7 @@ app13.post("/claude-auth", async (c) => {
|
|
|
22576
22683
|
claudeProc.stdout?.on("data", onClaudeOutput);
|
|
22577
22684
|
claudeProc.stderr?.on("data", onClaudeOutput);
|
|
22578
22685
|
claudeProc.once("close", () => {
|
|
22579
|
-
|
|
22686
|
+
closeSync9(claudeAuthLogFd);
|
|
22580
22687
|
if (pendingAuthLogin?.child === claudeProc) pendingAuthLogin = null;
|
|
22581
22688
|
});
|
|
22582
22689
|
await waitForAuthPage(2e4);
|
|
@@ -22641,7 +22748,7 @@ app13.post("/set-pin", async (c) => {
|
|
|
22641
22748
|
let installOwner = null;
|
|
22642
22749
|
if (existsSync32(INSTALL_OWNER_FILE)) {
|
|
22643
22750
|
try {
|
|
22644
|
-
const raw =
|
|
22751
|
+
const raw = readFileSync37(INSTALL_OWNER_FILE, "utf-8").trim();
|
|
22645
22752
|
if (raw.length > 0) installOwner = raw;
|
|
22646
22753
|
} catch (err) {
|
|
22647
22754
|
console.error(`[set-pin] install-owner-read-failed path=${INSTALL_OWNER_FILE} error=${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -22789,7 +22896,7 @@ app13.put("/set-pin", requireAdminSession, async (c) => {
|
|
|
22789
22896
|
let installOwner = null;
|
|
22790
22897
|
if (existsSync32(INSTALL_OWNER_FILE)) {
|
|
22791
22898
|
try {
|
|
22792
|
-
const raw =
|
|
22899
|
+
const raw = readFileSync37(INSTALL_OWNER_FILE, "utf-8").trim();
|
|
22793
22900
|
if (raw.length > 0) installOwner = raw;
|
|
22794
22901
|
} catch (err) {
|
|
22795
22902
|
console.error(`[set-pin] install-owner-read-failed path=${INSTALL_OWNER_FILE} error=${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -23246,9 +23353,9 @@ app14.post("/probe", async (c) => {
|
|
|
23246
23353
|
var field_default = app14;
|
|
23247
23354
|
|
|
23248
23355
|
// server/routes/client-error.ts
|
|
23249
|
-
import { appendFileSync as appendFileSync5, existsSync as existsSync33, renameSync as renameSync8, statSync as
|
|
23250
|
-
import { join as
|
|
23251
|
-
var CLIENT_ERRORS_LOG =
|
|
23356
|
+
import { appendFileSync as appendFileSync5, existsSync as existsSync33, renameSync as renameSync8, statSync as statSync22 } from "fs";
|
|
23357
|
+
import { join as join47 } from "path";
|
|
23358
|
+
var CLIENT_ERRORS_LOG = join47(LOG_DIR, "client-errors.log");
|
|
23252
23359
|
var MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
23253
23360
|
var MAX_BODY_SIZE = 8 * 1024;
|
|
23254
23361
|
var MAX_STACK_LEN = 2e3;
|
|
@@ -23306,7 +23413,7 @@ function stackHead(stack) {
|
|
|
23306
23413
|
function rotateIfNeeded() {
|
|
23307
23414
|
try {
|
|
23308
23415
|
if (!existsSync33(CLIENT_ERRORS_LOG)) return;
|
|
23309
|
-
const stats =
|
|
23416
|
+
const stats = statSync22(CLIENT_ERRORS_LOG);
|
|
23310
23417
|
if (stats.size < MAX_LOG_SIZE) return;
|
|
23311
23418
|
renameSync8(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
|
|
23312
23419
|
} catch (err) {
|
|
@@ -23662,17 +23769,17 @@ app17.get("/", requireAdminSession, async (c) => {
|
|
|
23662
23769
|
var accounts_default = app17;
|
|
23663
23770
|
|
|
23664
23771
|
// server/routes/admin/logs.ts
|
|
23665
|
-
import { existsSync as existsSync35, readdirSync as
|
|
23772
|
+
import { existsSync as existsSync35, readdirSync as readdirSync23, readFileSync as readFileSync38, statSync as statSync23 } from "fs";
|
|
23666
23773
|
import { resolve as resolve26, basename as basename13 } from "path";
|
|
23667
23774
|
|
|
23668
23775
|
// app/lib/logs-read-resolve.ts
|
|
23669
23776
|
import { existsSync as existsSync34 } from "fs";
|
|
23670
|
-
import { join as
|
|
23777
|
+
import { join as join48 } from "path";
|
|
23671
23778
|
function resolveSessionLogPaths(filename, logDirs) {
|
|
23672
23779
|
const tried = [filename];
|
|
23673
23780
|
const hits = [];
|
|
23674
23781
|
for (const dir of logDirs) {
|
|
23675
|
-
const fullPath =
|
|
23782
|
+
const fullPath = join48(dir, filename);
|
|
23676
23783
|
if (existsSync34(fullPath)) {
|
|
23677
23784
|
hits.push({ path: fullPath, dir });
|
|
23678
23785
|
}
|
|
@@ -23698,8 +23805,8 @@ app18.get("/", async (c) => {
|
|
|
23698
23805
|
const filePath = resolve26(dir, safe);
|
|
23699
23806
|
searched.push(filePath);
|
|
23700
23807
|
try {
|
|
23701
|
-
const buffer =
|
|
23702
|
-
const onDiskBytes =
|
|
23808
|
+
const buffer = readFileSync38(filePath);
|
|
23809
|
+
const onDiskBytes = statSync23(filePath).size;
|
|
23703
23810
|
const headers = {
|
|
23704
23811
|
"Content-Type": "text/plain; charset=utf-8",
|
|
23705
23812
|
"Content-Length": String(buffer.byteLength)
|
|
@@ -23763,8 +23870,8 @@ app18.get("/", async (c) => {
|
|
|
23763
23870
|
console.info(`[admin/logs] resolved cacheKey=${cacheKeySlice} sessionId=${sessionIdSlice} via=${primaryId === cacheKey ? "cacheKey" : primaryId === sessionKeyFromConv ? "reverse-lookup" : "sessionId-fallback"}`);
|
|
23764
23871
|
try {
|
|
23765
23872
|
const filename = basename13(hit.path);
|
|
23766
|
-
const buffer =
|
|
23767
|
-
const onDiskBytes =
|
|
23873
|
+
const buffer = readFileSync38(hit.path);
|
|
23874
|
+
const onDiskBytes = statSync23(hit.path).size;
|
|
23768
23875
|
const headers = {
|
|
23769
23876
|
"Content-Type": "text/plain; charset=utf-8",
|
|
23770
23877
|
"Content-Length": String(buffer.byteLength)
|
|
@@ -23801,18 +23908,18 @@ app18.get("/", async (c) => {
|
|
|
23801
23908
|
if (!existsSync35(dir)) continue;
|
|
23802
23909
|
let files;
|
|
23803
23910
|
try {
|
|
23804
|
-
files =
|
|
23911
|
+
files = readdirSync23(dir).filter((f) => f.endsWith(".log"));
|
|
23805
23912
|
} catch (err) {
|
|
23806
23913
|
const reason = err instanceof Error ? err.message : String(err);
|
|
23807
23914
|
console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
|
|
23808
23915
|
continue;
|
|
23809
23916
|
}
|
|
23810
|
-
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime:
|
|
23917
|
+
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync23(resolve26(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
|
|
23811
23918
|
seen.add(name);
|
|
23812
23919
|
try {
|
|
23813
|
-
const content =
|
|
23814
|
-
const
|
|
23815
|
-
logs[name] =
|
|
23920
|
+
const content = readFileSync38(resolve26(dir, name));
|
|
23921
|
+
const tail2 = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
|
|
23922
|
+
logs[name] = tail2.trim() || "(empty)";
|
|
23816
23923
|
} catch (err) {
|
|
23817
23924
|
const reason = err instanceof Error ? err.message : String(err);
|
|
23818
23925
|
console.debug(`[admin/logs] read-fail name=${name} reason=${reason}`);
|
|
@@ -23932,7 +24039,7 @@ var attachment_default = app20;
|
|
|
23932
24039
|
|
|
23933
24040
|
// server/routes/admin/session-upload.ts
|
|
23934
24041
|
import { readFile as readFile8 } from "fs/promises";
|
|
23935
|
-
import { existsSync as existsSync37, statSync as
|
|
24042
|
+
import { existsSync as existsSync37, statSync as statSync24 } from "fs";
|
|
23936
24043
|
var app21 = new Hono();
|
|
23937
24044
|
app21.get("/", requireAdminSession, async (c) => {
|
|
23938
24045
|
const cacheKey = c.var.cacheKey;
|
|
@@ -23953,7 +24060,7 @@ app21.get("/", requireAdminSession, async (c) => {
|
|
|
23953
24060
|
return c.json({ error: "Not found" }, 404);
|
|
23954
24061
|
}
|
|
23955
24062
|
const resolution = resolveClaudeUploadsPath(`${sessionId}/${file}`);
|
|
23956
|
-
if (!resolution.ok || !existsSync37(resolution.absolute) || !
|
|
24063
|
+
if (!resolution.ok || !existsSync37(resolution.absolute) || !statSync24(resolution.absolute).isFile()) {
|
|
23957
24064
|
console.log(`[session-upload] op=miss session=${short2} file=${file} status=404 reason=absent`);
|
|
23958
24065
|
return c.json({ error: "Not found" }, 404);
|
|
23959
24066
|
}
|
|
@@ -23975,13 +24082,13 @@ var session_upload_default = app21;
|
|
|
23975
24082
|
|
|
23976
24083
|
// server/routes/admin/agents.ts
|
|
23977
24084
|
import { resolve as resolve28 } from "path";
|
|
23978
|
-
import { readdirSync as
|
|
24085
|
+
import { readdirSync as readdirSync25, readFileSync as readFileSync40, existsSync as existsSync39, rmSync as rmSync5, renameSync as renameSync9, mkdirSync as mkdirSync10, writeFileSync as writeFileSync18, chmodSync } from "fs";
|
|
23979
24086
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
23980
24087
|
|
|
23981
24088
|
// ../services/claude-session-manager/src/tool-surface.ts
|
|
23982
|
-
import { readFileSync as
|
|
24089
|
+
import { readFileSync as readFileSync39, readdirSync as readdirSync24, statSync as statSync25, existsSync as existsSync38 } from "fs";
|
|
23983
24090
|
import { createHash as createHash5 } from "crypto";
|
|
23984
|
-
import { join as
|
|
24091
|
+
import { join as join49 } from "path";
|
|
23985
24092
|
|
|
23986
24093
|
// ../services/claude-session-manager/src/canonical-tool-names.ts
|
|
23987
24094
|
function canonicalToolName(plugin, tool) {
|
|
@@ -24234,15 +24341,15 @@ function loadToolSurface(pluginsRoots) {
|
|
|
24234
24341
|
const riskByTool = /* @__PURE__ */ new Map();
|
|
24235
24342
|
const manifestPaths = /* @__PURE__ */ new Map();
|
|
24236
24343
|
const loadOne = (pluginsRoot, plugin) => {
|
|
24237
|
-
const pluginDir =
|
|
24344
|
+
const pluginDir = join49(pluginsRoot, plugin);
|
|
24238
24345
|
try {
|
|
24239
|
-
if (!
|
|
24346
|
+
if (!statSync25(pluginDir).isDirectory()) return;
|
|
24240
24347
|
} catch {
|
|
24241
24348
|
return;
|
|
24242
24349
|
}
|
|
24243
|
-
const manifestPath =
|
|
24350
|
+
const manifestPath = join49(pluginDir, "PLUGIN.md");
|
|
24244
24351
|
if (!existsSync38(manifestPath)) return;
|
|
24245
|
-
const raw =
|
|
24352
|
+
const raw = readFileSync39(manifestPath, "utf-8");
|
|
24246
24353
|
const frontmatter = extractFrontmatter(raw, plugin);
|
|
24247
24354
|
const tools = parseToolsBlock(frontmatter, plugin);
|
|
24248
24355
|
if (tools.length === 0) return;
|
|
@@ -24261,7 +24368,7 @@ function loadToolSurface(pluginsRoots) {
|
|
|
24261
24368
|
`${plugin}: mcpServers has entry but manifestPaths is missing \u2014 invariant violated, both maps must be written together`
|
|
24262
24369
|
);
|
|
24263
24370
|
}
|
|
24264
|
-
const priorSha = createHash5("sha256").update(
|
|
24371
|
+
const priorSha = createHash5("sha256").update(readFileSync39(priorPath)).digest("hex").slice(0, 8);
|
|
24265
24372
|
const newSha = createHash5("sha256").update(raw).digest("hex").slice(0, 8);
|
|
24266
24373
|
throw new ToolSurfaceError(
|
|
24267
24374
|
"mcp-plugin-duplicate",
|
|
@@ -24284,15 +24391,15 @@ function loadToolSurface(pluginsRoots) {
|
|
|
24284
24391
|
}
|
|
24285
24392
|
};
|
|
24286
24393
|
for (const root of roots) {
|
|
24287
|
-
const entries2 =
|
|
24394
|
+
const entries2 = readdirSync24(root).sort();
|
|
24288
24395
|
for (const plugin of entries2) {
|
|
24289
|
-
const pluginDir =
|
|
24396
|
+
const pluginDir = join49(root, plugin);
|
|
24290
24397
|
loadOne(root, plugin);
|
|
24291
|
-
const subRoot =
|
|
24398
|
+
const subRoot = join49(pluginDir, "plugins");
|
|
24292
24399
|
let subEntries;
|
|
24293
24400
|
try {
|
|
24294
|
-
if (!
|
|
24295
|
-
subEntries =
|
|
24401
|
+
if (!statSync25(subRoot).isDirectory()) continue;
|
|
24402
|
+
subEntries = readdirSync24(subRoot).sort();
|
|
24296
24403
|
} catch {
|
|
24297
24404
|
continue;
|
|
24298
24405
|
}
|
|
@@ -24424,7 +24531,7 @@ var SLUG_UNSAFE = (s) => s.includes("/") || s.includes("..") || s.includes("\\")
|
|
|
24424
24531
|
function subdirs(dir) {
|
|
24425
24532
|
if (!existsSync39(dir)) return [];
|
|
24426
24533
|
try {
|
|
24427
|
-
return
|
|
24534
|
+
return readdirSync25(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
24428
24535
|
} catch {
|
|
24429
24536
|
return [];
|
|
24430
24537
|
}
|
|
@@ -24456,7 +24563,7 @@ function loadRiskSurface() {
|
|
|
24456
24563
|
function readDisabledStoreStrict(accountDir) {
|
|
24457
24564
|
const p = resolve28(accountDir, DISABLED_STORE);
|
|
24458
24565
|
if (!existsSync39(p)) return /* @__PURE__ */ new Set();
|
|
24459
|
-
const parsed = JSON.parse(
|
|
24566
|
+
const parsed = JSON.parse(readFileSync40(p, "utf-8"));
|
|
24460
24567
|
if (!Array.isArray(parsed.disabled)) throw new Error("disabled is not an array");
|
|
24461
24568
|
return new Set(parsed.disabled.filter((x) => typeof x === "string"));
|
|
24462
24569
|
}
|
|
@@ -24476,7 +24583,7 @@ function authoredAgentFiles(accountDir) {
|
|
|
24476
24583
|
const dir = resolve28(pluginsDir, plugin, "agents");
|
|
24477
24584
|
if (!existsSync39(dir)) continue;
|
|
24478
24585
|
try {
|
|
24479
|
-
for (const entry3 of
|
|
24586
|
+
for (const entry3 of readdirSync25(dir)) {
|
|
24480
24587
|
if (!entry3.endsWith(".md")) continue;
|
|
24481
24588
|
const path = resolve28(dir, entry3);
|
|
24482
24589
|
const paths = byName.get(entry3);
|
|
@@ -24497,7 +24604,7 @@ function shippedSourceDirs(accountDir) {
|
|
|
24497
24604
|
];
|
|
24498
24605
|
}
|
|
24499
24606
|
function readRowFields(path) {
|
|
24500
|
-
const { fm } = splitFrontmatter(
|
|
24607
|
+
const { fm } = splitFrontmatter(readFileSync40(path, "utf-8"));
|
|
24501
24608
|
return {
|
|
24502
24609
|
name: fm.name ?? "",
|
|
24503
24610
|
description: fm.description ?? "",
|
|
@@ -24530,9 +24637,9 @@ function compareToAuthored(candidatePath, authoredPaths, filename) {
|
|
|
24530
24637
|
anyUnreadable = true;
|
|
24531
24638
|
continue;
|
|
24532
24639
|
}
|
|
24533
|
-
const
|
|
24534
|
-
if (
|
|
24535
|
-
firstDivergence ??= { authoredPath: path, fields };
|
|
24640
|
+
const fields2 = divergentFields(candidate, authored);
|
|
24641
|
+
if (fields2.length === 0) return { verdict: "matched" };
|
|
24642
|
+
firstDivergence ??= { authoredPath: path, fields: fields2 };
|
|
24536
24643
|
}
|
|
24537
24644
|
if (firstDivergence) return { verdict: "divergent", ...firstDivergence };
|
|
24538
24645
|
if (anyUnreadable) return { verdict: "unreadable" };
|
|
@@ -24550,7 +24657,7 @@ function listShipped(accountDir, riskByTool, disabled, riskSurfaceFailed, author
|
|
|
24550
24657
|
for (const dir of dirs) {
|
|
24551
24658
|
if (!existsSync39(dir)) continue;
|
|
24552
24659
|
try {
|
|
24553
|
-
for (const entry3 of
|
|
24660
|
+
for (const entry3 of readdirSync25(dir)) if (entry3.endsWith(".md")) names.add(entry3);
|
|
24554
24661
|
} catch (err) {
|
|
24555
24662
|
console.error(`[admin/agents] op=list-shipped read-failed dir=${dir} error="${err}"`);
|
|
24556
24663
|
}
|
|
@@ -24578,7 +24685,7 @@ function listShipped(accountDir, riskByTool, disabled, riskSurfaceFailed, author
|
|
|
24578
24685
|
}
|
|
24579
24686
|
}
|
|
24580
24687
|
try {
|
|
24581
|
-
const { fm } = splitFrontmatter(
|
|
24688
|
+
const { fm } = splitFrontmatter(readFileSync40(resolve28(source, filename), "utf-8"));
|
|
24582
24689
|
if (!fm.name) {
|
|
24583
24690
|
shippedSkipped++;
|
|
24584
24691
|
console.error(`[admin/agents] op=list-shipped-skip file=${filename} reason=no-name`);
|
|
@@ -24640,14 +24747,14 @@ function listSpecialists(accountDir, riskByTool, riskSurfaceFailed) {
|
|
|
24640
24747
|
if (!existsSync39(agentsDirP)) continue;
|
|
24641
24748
|
let entries2;
|
|
24642
24749
|
try {
|
|
24643
|
-
entries2 =
|
|
24750
|
+
entries2 = readdirSync25(agentsDirP, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
24644
24751
|
} catch {
|
|
24645
24752
|
continue;
|
|
24646
24753
|
}
|
|
24647
24754
|
for (const entry3 of entries2) {
|
|
24648
24755
|
if (!entry3.isFile() || !entry3.name.endsWith(".md")) continue;
|
|
24649
24756
|
try {
|
|
24650
|
-
const { fm } = splitFrontmatter(
|
|
24757
|
+
const { fm } = splitFrontmatter(readFileSync40(resolve28(agentsDirP, entry3.name), "utf-8"));
|
|
24651
24758
|
if (!fm.name) {
|
|
24652
24759
|
specialistsSkipped++;
|
|
24653
24760
|
console.error(`[admin/agents] op=list-specialist-skip plugin=${plugin} file=${entry3.name}`);
|
|
@@ -24709,14 +24816,14 @@ app22.get("/", requireAdminSession, (c) => {
|
|
|
24709
24816
|
const agentsDir = resolve28(account.accountDir, "agents");
|
|
24710
24817
|
if (existsSync39(agentsDir)) {
|
|
24711
24818
|
try {
|
|
24712
|
-
const entries2 =
|
|
24819
|
+
const entries2 = readdirSync25(agentsDir, { withFileTypes: true });
|
|
24713
24820
|
for (const entry3 of entries2.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
24714
24821
|
if (!entry3.isDirectory()) continue;
|
|
24715
24822
|
if (entry3.name === "admin") continue;
|
|
24716
24823
|
const configPath3 = resolve28(agentsDir, entry3.name, "config.json");
|
|
24717
24824
|
if (!existsSync39(configPath3)) continue;
|
|
24718
24825
|
try {
|
|
24719
|
-
const config = JSON.parse(
|
|
24826
|
+
const config = JSON.parse(readFileSync40(configPath3, "utf-8"));
|
|
24720
24827
|
agents.push({
|
|
24721
24828
|
slug: entry3.name,
|
|
24722
24829
|
displayName: config.displayName ?? entry3.name,
|
|
@@ -24798,7 +24905,7 @@ app22.get("/:slug", requireAdminSession, (c) => {
|
|
|
24798
24905
|
const dirs = shippedSourceDirs(account.accountDir);
|
|
24799
24906
|
const source = dirs.find((d) => existsSync39(resolve28(d, `${slug}.md`)));
|
|
24800
24907
|
if (!source) return c.json({ error: "Agent not found" }, 404);
|
|
24801
|
-
const { fm, body } = splitFrontmatter(
|
|
24908
|
+
const { fm, body } = splitFrontmatter(readFileSync40(resolve28(source, `${slug}.md`), "utf-8"));
|
|
24802
24909
|
const { riskByTool, failed: failed2 } = loadRiskSurface();
|
|
24803
24910
|
const tools = parseToolsLine(fm.tools);
|
|
24804
24911
|
const r = classify(tools, riskByTool, failed2 !== null);
|
|
@@ -24830,7 +24937,7 @@ app22.get("/:slug", requireAdminSession, (c) => {
|
|
|
24830
24937
|
if (SLUG_UNSAFE(pluginParam)) return c.json({ error: "Invalid plugin" }, 400);
|
|
24831
24938
|
const file = resolve28(account.accountDir, "plugins", pluginParam, "agents", `${slug}.md`);
|
|
24832
24939
|
if (!existsSync39(file)) return c.json({ error: "Agent not found" }, 404);
|
|
24833
|
-
const { fm, body } = splitFrontmatter(
|
|
24940
|
+
const { fm, body } = splitFrontmatter(readFileSync40(file, "utf-8"));
|
|
24834
24941
|
const skills = subdirs(resolve28(account.accountDir, "plugins", pluginParam, "skills"));
|
|
24835
24942
|
const { riskByTool, failed: failed2 } = loadRiskSurface();
|
|
24836
24943
|
const tools = parseToolsLine(fm.tools);
|
|
@@ -24863,7 +24970,7 @@ app22.get("/:slug", requireAdminSession, (c) => {
|
|
|
24863
24970
|
if (!existsSync39(configPath3)) return c.json({ error: "Agent not found" }, 404);
|
|
24864
24971
|
let config;
|
|
24865
24972
|
try {
|
|
24866
|
-
config = JSON.parse(
|
|
24973
|
+
config = JSON.parse(readFileSync40(configPath3, "utf-8"));
|
|
24867
24974
|
} catch {
|
|
24868
24975
|
console.error(`[admin/agents] op=detail slug=${slug} error="config.json parse failed"`);
|
|
24869
24976
|
return c.json({ error: "Agent config unreadable" }, 500);
|
|
@@ -24874,7 +24981,7 @@ app22.get("/:slug", requireAdminSession, (c) => {
|
|
|
24874
24981
|
const p = resolve28(agentDir, file);
|
|
24875
24982
|
try {
|
|
24876
24983
|
if (existsSync39(p)) {
|
|
24877
|
-
docs[key2] =
|
|
24984
|
+
docs[key2] = readFileSync40(p, "utf-8");
|
|
24878
24985
|
present[key2] = true;
|
|
24879
24986
|
} else {
|
|
24880
24987
|
docs[key2] = "";
|
|
@@ -24936,9 +25043,9 @@ function reconcileAuthoredRoutingLine(accountDir, accountId, op, source) {
|
|
|
24936
25043
|
const agentsMd = resolve28(accountDir, "agents", "admin", "AGENTS.md");
|
|
24937
25044
|
if (!existsSync39(agentsMd) || !existsSync39(source)) return false;
|
|
24938
25045
|
try {
|
|
24939
|
-
const { fm } = splitFrontmatter(
|
|
25046
|
+
const { fm } = splitFrontmatter(readFileSync40(source, "utf-8"));
|
|
24940
25047
|
if (!fm.name) return false;
|
|
24941
|
-
const lines =
|
|
25048
|
+
const lines = readFileSync40(agentsMd, "utf-8").split("\n");
|
|
24942
25049
|
const prefix = `- **specialists:${fm.name}**:`;
|
|
24943
25050
|
const without = lines.filter((l) => !l.startsWith(prefix));
|
|
24944
25051
|
const next = op === "disable" ? without : [...without, `${prefix} ${fm.description ?? ""}`.trimEnd()];
|
|
@@ -25516,21 +25623,21 @@ app23.post("/:id/resume", async (c) => {
|
|
|
25516
25623
|
if (bridge.reason === "conversation-not-found") {
|
|
25517
25624
|
return c.json({ error: "Conversation not found" }, 404);
|
|
25518
25625
|
}
|
|
25519
|
-
const
|
|
25520
|
-
console.error(`[session] middleware-reject status=401 code=session-not-registered reason="cookie-bridge-rejected:${bridge.reason}" path=${c.req.path} cacheKey=${
|
|
25626
|
+
const tail2 = cacheKey.slice(0, 8);
|
|
25627
|
+
console.error(`[session] middleware-reject status=401 code=session-not-registered reason="cookie-bridge-rejected:${bridge.reason}" path=${c.req.path} cacheKey=${tail2}\u2026`);
|
|
25521
25628
|
return c.json({ error: "Invalid or expired admin session", code: "session-not-registered" }, 401);
|
|
25522
25629
|
}
|
|
25523
25630
|
bridged = true;
|
|
25524
25631
|
result = validateSession(cacheKey, "admin", signedSessionToken);
|
|
25525
25632
|
if (!result.ok) {
|
|
25526
|
-
const
|
|
25527
|
-
console.error(`[session] middleware-reject status=401 code=session-not-registered reason="post-bridge re-validate failed" path=${c.req.path} cacheKey=${
|
|
25633
|
+
const tail2 = cacheKey.slice(0, 8);
|
|
25634
|
+
console.error(`[session] middleware-reject status=401 code=session-not-registered reason="post-bridge re-validate failed" path=${c.req.path} cacheKey=${tail2}\u2026`);
|
|
25528
25635
|
return c.json({ error: "Invalid or expired admin session", code: "session-not-registered" }, 401);
|
|
25529
25636
|
}
|
|
25530
25637
|
} else {
|
|
25531
|
-
const
|
|
25638
|
+
const tail2 = cacheKey.slice(0, 8);
|
|
25532
25639
|
const wireCode = result.reason === "agent-type-mismatch" ? "session-not-registered" : result.reason;
|
|
25533
|
-
console.error(`[session] middleware-reject status=401 code=${wireCode} reason="invalid or expired admin session" path=${c.req.path} cacheKey=${
|
|
25640
|
+
console.error(`[session] middleware-reject status=401 code=${wireCode} reason="invalid or expired admin session" path=${c.req.path} cacheKey=${tail2}\u2026`);
|
|
25534
25641
|
return c.json({ error: "Invalid or expired admin session", code: wireCode }, 401);
|
|
25535
25642
|
}
|
|
25536
25643
|
}
|
|
@@ -25796,8 +25903,8 @@ app23.put("/:id/label", requireAdminSession, async (c) => {
|
|
|
25796
25903
|
var sessions_default = app23;
|
|
25797
25904
|
|
|
25798
25905
|
// app/lib/claude-agent/spawn-context.ts
|
|
25799
|
-
import { existsSync as existsSync41, readFileSync as
|
|
25800
|
-
import { dirname as dirname15, resolve as resolve29, join as
|
|
25906
|
+
import { existsSync as existsSync41, readFileSync as readFileSync41, readdirSync as readdirSync26, statSync as statSync26 } from "fs";
|
|
25907
|
+
import { dirname as dirname15, resolve as resolve29, join as join50 } from "path";
|
|
25801
25908
|
async function resolveOwnerProfileBlock(accountId, userId) {
|
|
25802
25909
|
if (!userId) return { ok: false, reason: "missing-user-id" };
|
|
25803
25910
|
try {
|
|
@@ -25838,14 +25945,14 @@ function frontmatterField(manifest, field2) {
|
|
|
25838
25945
|
function extractPluginToolDescriptions(pluginDir) {
|
|
25839
25946
|
const out = /* @__PURE__ */ new Map();
|
|
25840
25947
|
const candidates = [
|
|
25841
|
-
|
|
25842
|
-
|
|
25948
|
+
join50(pluginDir, "mcp/dist/index.js"),
|
|
25949
|
+
join50(pluginDir, "mcp/src/index.ts")
|
|
25843
25950
|
];
|
|
25844
25951
|
let raw = null;
|
|
25845
25952
|
for (const path of candidates) {
|
|
25846
25953
|
if (!existsSync41(path)) continue;
|
|
25847
25954
|
try {
|
|
25848
|
-
raw =
|
|
25955
|
+
raw = readFileSync41(path, "utf-8");
|
|
25849
25956
|
break;
|
|
25850
25957
|
} catch {
|
|
25851
25958
|
}
|
|
@@ -25896,24 +26003,24 @@ function listPluginDirs(accountPluginsDir) {
|
|
|
25896
26003
|
const out = /* @__PURE__ */ new Map();
|
|
25897
26004
|
const platformPlugins = resolve29(PLATFORM_ROOT, "plugins");
|
|
25898
26005
|
if (existsSync41(platformPlugins)) {
|
|
25899
|
-
for (const name of
|
|
25900
|
-
const dir =
|
|
26006
|
+
for (const name of readdirSync26(platformPlugins)) {
|
|
26007
|
+
const dir = join50(platformPlugins, name);
|
|
25901
26008
|
try {
|
|
25902
|
-
if (
|
|
26009
|
+
if (statSync26(dir).isDirectory()) out.set(name, dir);
|
|
25903
26010
|
} catch {
|
|
25904
26011
|
}
|
|
25905
26012
|
}
|
|
25906
26013
|
}
|
|
25907
26014
|
const premiumRoot = resolve29(dirname15(PLATFORM_ROOT), "premium-plugins");
|
|
25908
26015
|
if (existsSync41(premiumRoot)) {
|
|
25909
|
-
for (const bundle of
|
|
25910
|
-
const bundlePlugins =
|
|
26016
|
+
for (const bundle of readdirSync26(premiumRoot)) {
|
|
26017
|
+
const bundlePlugins = join50(premiumRoot, bundle, "plugins");
|
|
25911
26018
|
if (!existsSync41(bundlePlugins)) continue;
|
|
25912
26019
|
try {
|
|
25913
|
-
for (const name of
|
|
25914
|
-
const dir =
|
|
26020
|
+
for (const name of readdirSync26(bundlePlugins)) {
|
|
26021
|
+
const dir = join50(bundlePlugins, name);
|
|
25915
26022
|
try {
|
|
25916
|
-
if (
|
|
26023
|
+
if (statSync26(dir).isDirectory()) out.set(name, dir);
|
|
25917
26024
|
} catch {
|
|
25918
26025
|
}
|
|
25919
26026
|
}
|
|
@@ -25923,11 +26030,11 @@ function listPluginDirs(accountPluginsDir) {
|
|
|
25923
26030
|
}
|
|
25924
26031
|
if (accountPluginsDir && existsSync41(accountPluginsDir)) {
|
|
25925
26032
|
try {
|
|
25926
|
-
for (const name of
|
|
26033
|
+
for (const name of readdirSync26(accountPluginsDir)) {
|
|
25927
26034
|
if (out.has(name)) continue;
|
|
25928
|
-
const dir =
|
|
26035
|
+
const dir = join50(accountPluginsDir, name);
|
|
25929
26036
|
try {
|
|
25930
|
-
if (
|
|
26037
|
+
if (statSync26(dir).isDirectory()) out.set(name, dir);
|
|
25931
26038
|
} catch {
|
|
25932
26039
|
}
|
|
25933
26040
|
}
|
|
@@ -25942,9 +26049,9 @@ function accountPluginsDirFor(accountId) {
|
|
|
25942
26049
|
function listAccountPluginNames(accountPluginsDir) {
|
|
25943
26050
|
if (!existsSync41(accountPluginsDir)) return [];
|
|
25944
26051
|
try {
|
|
25945
|
-
return
|
|
26052
|
+
return readdirSync26(accountPluginsDir).filter((name) => {
|
|
25946
26053
|
try {
|
|
25947
|
-
return
|
|
26054
|
+
return statSync26(join50(accountPluginsDir, name)).isDirectory();
|
|
25948
26055
|
} catch {
|
|
25949
26056
|
return false;
|
|
25950
26057
|
}
|
|
@@ -25957,7 +26064,7 @@ function readEnabledPlugins(accountId) {
|
|
|
25957
26064
|
const accountFile = resolve29(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
25958
26065
|
if (!existsSync41(accountFile)) return /* @__PURE__ */ new Set();
|
|
25959
26066
|
try {
|
|
25960
|
-
const parsed = JSON.parse(
|
|
26067
|
+
const parsed = JSON.parse(readFileSync41(accountFile, "utf-8"));
|
|
25961
26068
|
return new Set(
|
|
25962
26069
|
Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
|
|
25963
26070
|
);
|
|
@@ -25969,7 +26076,7 @@ function readFrontmatter(path) {
|
|
|
25969
26076
|
if (!existsSync41(path)) return null;
|
|
25970
26077
|
let raw;
|
|
25971
26078
|
try {
|
|
25972
|
-
raw =
|
|
26079
|
+
raw = readFileSync41(path, "utf-8");
|
|
25973
26080
|
} catch {
|
|
25974
26081
|
return null;
|
|
25975
26082
|
}
|
|
@@ -25987,7 +26094,7 @@ function computeActivePlugins(accountId) {
|
|
|
25987
26094
|
for (const name of emitNames) {
|
|
25988
26095
|
const dir = pluginDirs.get(name);
|
|
25989
26096
|
if (!dir) continue;
|
|
25990
|
-
const fm = readFrontmatter(
|
|
26097
|
+
const fm = readFrontmatter(join50(dir, "PLUGIN.md"));
|
|
25991
26098
|
if (!fm) continue;
|
|
25992
26099
|
const description = frontmatterField(`---
|
|
25993
26100
|
${fm}
|
|
@@ -26004,7 +26111,7 @@ ${fm}
|
|
|
26004
26111
|
`plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
|
|
26005
26112
|
);
|
|
26006
26113
|
if (toolNames.length > 0 && descMap.size === 0) {
|
|
26007
|
-
const hasSource = existsSync41(
|
|
26114
|
+
const hasSource = existsSync41(join50(dir, "mcp/dist/index.js")) || existsSync41(join50(dir, "mcp/src/index.ts"));
|
|
26008
26115
|
if (hasSource) {
|
|
26009
26116
|
console.warn(
|
|
26010
26117
|
`[spawn-context] WARN plugin=${name} mcp source present but tool-description regex matched zero entries \u2014 SDK upgrade may have changed the registration shape`
|
|
@@ -26014,7 +26121,7 @@ ${fm}
|
|
|
26014
26121
|
const skillPaths = parseSkillPathsFromFrontmatter(fm);
|
|
26015
26122
|
const skills = [];
|
|
26016
26123
|
for (const relPath of skillPaths) {
|
|
26017
|
-
const skillPath =
|
|
26124
|
+
const skillPath = join50(dir, relPath);
|
|
26018
26125
|
const skillFm = readFrontmatter(skillPath);
|
|
26019
26126
|
if (!skillFm) continue;
|
|
26020
26127
|
const skillName = frontmatterField(`---
|
|
@@ -26034,7 +26141,7 @@ function computeSpecialistDomains(accountId) {
|
|
|
26034
26141
|
if (!existsSync41(specialistsDir)) return [];
|
|
26035
26142
|
let entries2;
|
|
26036
26143
|
try {
|
|
26037
|
-
entries2 =
|
|
26144
|
+
entries2 = readdirSync26(specialistsDir);
|
|
26038
26145
|
} catch {
|
|
26039
26146
|
return [];
|
|
26040
26147
|
}
|
|
@@ -26058,7 +26165,7 @@ function computeSpecialistDomains(accountId) {
|
|
|
26058
26165
|
const out = [];
|
|
26059
26166
|
for (const file of entries2.sort()) {
|
|
26060
26167
|
if (!file.endsWith(".md")) continue;
|
|
26061
|
-
const fm = readFrontmatter(
|
|
26168
|
+
const fm = readFrontmatter(join50(specialistsDir, file));
|
|
26062
26169
|
if (!fm) continue;
|
|
26063
26170
|
const wrapped = `---
|
|
26064
26171
|
${fm}
|
|
@@ -26080,7 +26187,7 @@ function computeDormantPlugins(accountId) {
|
|
|
26080
26187
|
if (!existsSync41(accountFile)) return [];
|
|
26081
26188
|
let enabled;
|
|
26082
26189
|
try {
|
|
26083
|
-
const raw =
|
|
26190
|
+
const raw = readFileSync41(accountFile, "utf-8");
|
|
26084
26191
|
const parsed = JSON.parse(raw);
|
|
26085
26192
|
enabled = new Set(
|
|
26086
26193
|
Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
|
|
@@ -26095,7 +26202,7 @@ function computeDormantPlugins(accountId) {
|
|
|
26095
26202
|
if (!existsSync41(pluginsDir)) return [];
|
|
26096
26203
|
let entries2;
|
|
26097
26204
|
try {
|
|
26098
|
-
entries2 =
|
|
26205
|
+
entries2 = readdirSync26(pluginsDir);
|
|
26099
26206
|
} catch {
|
|
26100
26207
|
return [];
|
|
26101
26208
|
}
|
|
@@ -26106,7 +26213,7 @@ function computeDormantPlugins(accountId) {
|
|
|
26106
26213
|
if (!existsSync41(manifestPath)) continue;
|
|
26107
26214
|
let manifest;
|
|
26108
26215
|
try {
|
|
26109
|
-
manifest =
|
|
26216
|
+
manifest = readFileSync41(manifestPath, "utf-8");
|
|
26110
26217
|
} catch {
|
|
26111
26218
|
continue;
|
|
26112
26219
|
}
|
|
@@ -26120,13 +26227,13 @@ function computeDormantPlugins(accountId) {
|
|
|
26120
26227
|
}
|
|
26121
26228
|
|
|
26122
26229
|
// server/routes/admin/claude-sessions.ts
|
|
26123
|
-
import { existsSync as existsSync42, readFileSync as
|
|
26230
|
+
import { existsSync as existsSync42, readFileSync as readFileSync42 } from "fs";
|
|
26124
26231
|
import { resolve as resolve30 } from "path";
|
|
26125
26232
|
function readTunnelState(brandConfigDir) {
|
|
26126
26233
|
const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
|
|
26127
26234
|
if (!existsSync42(statePath)) return null;
|
|
26128
26235
|
try {
|
|
26129
|
-
const parsed = JSON.parse(
|
|
26236
|
+
const parsed = JSON.parse(readFileSync42(statePath, "utf-8"));
|
|
26130
26237
|
const tunnelId = typeof parsed.tunnelId === "string" ? parsed.tunnelId : null;
|
|
26131
26238
|
const tunnelName = typeof parsed.tunnelName === "string" ? parsed.tunnelName : null;
|
|
26132
26239
|
const domain = typeof parsed.domain === "string" ? parsed.domain : null;
|
|
@@ -26140,7 +26247,7 @@ function resolveTunnelUrl() {
|
|
|
26140
26247
|
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve30(process.cwd(), "..");
|
|
26141
26248
|
let brand;
|
|
26142
26249
|
try {
|
|
26143
|
-
brand = JSON.parse(
|
|
26250
|
+
brand = JSON.parse(readFileSync42(resolve30(platformRoot5, "config", "brand.json"), "utf-8"));
|
|
26144
26251
|
} catch {
|
|
26145
26252
|
return null;
|
|
26146
26253
|
}
|
|
@@ -26341,7 +26448,7 @@ app25.post("/", async (c) => {
|
|
|
26341
26448
|
var log_ingest_default = app25;
|
|
26342
26449
|
|
|
26343
26450
|
// server/routes/admin/session-blocked.ts
|
|
26344
|
-
import { join as
|
|
26451
|
+
import { join as join51 } from "path";
|
|
26345
26452
|
var TAG44 = "[blocked-tool-notify]";
|
|
26346
26453
|
function isLoopbackAddr4(addr) {
|
|
26347
26454
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
@@ -26388,7 +26495,7 @@ app26.post("/", async (c) => {
|
|
|
26388
26495
|
if (!tool) return c.json({ error: "tool-required" }, 400);
|
|
26389
26496
|
const text = blockedNotificationText({ sessionId, agentId, tool, blockedForMs });
|
|
26390
26497
|
const projectDir = findSessionProjectDir(sessionId);
|
|
26391
|
-
const meta = projectDir ? readSidecarMeta(
|
|
26498
|
+
const meta = projectDir ? readSidecarMeta(join51(projectDir, `${sessionId}.meta.json`)) : { role: null, channel: null, senderId: null, accountId: null };
|
|
26392
26499
|
const account = validateAccountId2(meta.accountId ?? "");
|
|
26393
26500
|
if (!account) {
|
|
26394
26501
|
console.error(
|
|
@@ -26587,7 +26694,7 @@ import { createReadStream as createReadStream2, createWriteStream as createWrite
|
|
|
26587
26694
|
import { readdir as readdir4, readFile as readFile10, stat as stat6, mkdir as mkdir2, unlink as unlink3, rename as rename3, rmdir } from "fs/promises";
|
|
26588
26695
|
import { realpathSync as realpathSync7 } from "fs";
|
|
26589
26696
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
26590
|
-
import { basename as basename15, dirname as dirname16, join as
|
|
26697
|
+
import { basename as basename15, dirname as dirname16, join as join53, relative as relative6, resolve as resolve32, sep as sep9 } from "path";
|
|
26591
26698
|
import { Readable as Readable2 } from "stream";
|
|
26592
26699
|
|
|
26593
26700
|
// ../lib/graph-trash/src/index.ts
|
|
@@ -26905,7 +27012,7 @@ async function cascadeDeleteDocument(params) {
|
|
|
26905
27012
|
|
|
26906
27013
|
// app/lib/file-index.ts
|
|
26907
27014
|
import * as fsp from "fs/promises";
|
|
26908
|
-
import { resolve as resolve31, relative as relative5, join as
|
|
27015
|
+
import { resolve as resolve31, relative as relative5, join as join52, basename as basename14, extname, sep as sep8 } from "path";
|
|
26909
27016
|
import { tmpdir as tmpdir3 } from "os";
|
|
26910
27017
|
import { execFile } from "child_process";
|
|
26911
27018
|
import { promisify } from "util";
|
|
@@ -26987,7 +27094,7 @@ async function extractPdf(absolute) {
|
|
|
26987
27094
|
return stdout.trim();
|
|
26988
27095
|
}
|
|
26989
27096
|
async function ocrPdf(absolute) {
|
|
26990
|
-
const outPdf =
|
|
27097
|
+
const outPdf = join52(tmpdir3(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
|
|
26991
27098
|
try {
|
|
26992
27099
|
await execFileAsync(
|
|
26993
27100
|
"ocrmypdf",
|
|
@@ -27049,7 +27156,7 @@ async function readDisplayName(absolute) {
|
|
|
27049
27156
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
27050
27157
|
if (base === `${stem}.meta.json`) return null;
|
|
27051
27158
|
try {
|
|
27052
|
-
const raw = await fsp.readFile(
|
|
27159
|
+
const raw = await fsp.readFile(join52(dir, `${stem}.meta.json`), "utf-8");
|
|
27053
27160
|
const meta = JSON.parse(raw);
|
|
27054
27161
|
const dn = meta.displayName ?? meta.filename;
|
|
27055
27162
|
return typeof dn === "string" && dn.length > 0 ? dn : null;
|
|
@@ -27070,7 +27177,7 @@ async function walkSubtree(root, dataRoot, out) {
|
|
|
27070
27177
|
for (const entry3 of entries2) {
|
|
27071
27178
|
if (entry3.isSymbolicLink()) continue;
|
|
27072
27179
|
if (entry3.isDirectory() && entry3.name === ".uploads-tmp") continue;
|
|
27073
|
-
const abs =
|
|
27180
|
+
const abs = join52(root, entry3.name);
|
|
27074
27181
|
if (entry3.isDirectory()) {
|
|
27075
27182
|
const sub = await walkSubtree(abs, dataRoot, out);
|
|
27076
27183
|
if (!sub.clean) clean = false;
|
|
@@ -27443,7 +27550,7 @@ var UPLOAD_TMP_DIR = ".uploads-tmp";
|
|
|
27443
27550
|
var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
27444
27551
|
async function readMeta2(absDir, baseName) {
|
|
27445
27552
|
try {
|
|
27446
|
-
const raw = await readFile10(
|
|
27553
|
+
const raw = await readFile10(join53(absDir, `${baseName}.meta.json`), "utf8");
|
|
27447
27554
|
const parsed = JSON.parse(raw);
|
|
27448
27555
|
if (typeof parsed?.filename === "string") {
|
|
27449
27556
|
return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
|
|
@@ -27498,7 +27605,7 @@ async function servableFilesIn(dirAbs, uuid) {
|
|
|
27498
27605
|
}
|
|
27499
27606
|
async function enrich(absolute, entry3, accountNames) {
|
|
27500
27607
|
if (entry3.kind === "directory" && UUID_RE3.test(entry3.name)) {
|
|
27501
|
-
const dirAbs =
|
|
27608
|
+
const dirAbs = join53(absolute, entry3.name);
|
|
27502
27609
|
const meta = await readMeta2(dirAbs, entry3.name);
|
|
27503
27610
|
if (meta?.filename) {
|
|
27504
27611
|
const servable = await servableFilesIn(dirAbs, entry3.name);
|
|
@@ -27507,7 +27614,7 @@ async function enrich(absolute, entry3, accountNames) {
|
|
|
27507
27614
|
let size = null;
|
|
27508
27615
|
let modifiedAt = entry3.modifiedAt;
|
|
27509
27616
|
try {
|
|
27510
|
-
const st = await stat6(
|
|
27617
|
+
const st = await stat6(join53(dirAbs, innerName));
|
|
27511
27618
|
size = st.size;
|
|
27512
27619
|
modifiedAt = st.mtime.toISOString();
|
|
27513
27620
|
} catch {
|
|
@@ -27719,7 +27826,7 @@ app28.get("/", requireAdminSession, async (c) => {
|
|
|
27719
27826
|
const childRel = relPath === "" || relPath === "." ? name : `${relPath}/${name}`;
|
|
27720
27827
|
const protectedEntry = isProtectedFromDeletion(childRel).protected;
|
|
27721
27828
|
try {
|
|
27722
|
-
const entryPath =
|
|
27829
|
+
const entryPath = join53(absolute, name);
|
|
27723
27830
|
const s = await stat6(entryPath);
|
|
27724
27831
|
entries2.push({
|
|
27725
27832
|
name,
|
|
@@ -27748,7 +27855,7 @@ app28.get("/", requireAdminSession, async (c) => {
|
|
|
27748
27855
|
const displayPath = buildDisplayPath(relPath, accountNames);
|
|
27749
27856
|
if (groupReq || isAccountRoot(relPath)) {
|
|
27750
27857
|
const acctId = relPath.split("/")[1] ?? accountId;
|
|
27751
|
-
const schemaMd = await readFile10(
|
|
27858
|
+
const schemaMd = await readFile10(join53(absolute, "SCHEMA.md"), "utf8").catch(() => null);
|
|
27752
27859
|
const groups = classifyAccountRoot(schemaMd, entries2.map((e) => e.name));
|
|
27753
27860
|
console.error(
|
|
27754
27861
|
`[data-schema] op=classify account=${acctId} status=${groups.parsed ? "ok" : "parse-failed"} reason=${groups.reason} entries=${entries2.length} home=${groups.home.join(",") || "none"} system=${groups.system.length} unknown=${groups.unknown.join(",") || "none"}`
|
|
@@ -27786,7 +27893,7 @@ app28.get("/", requireAdminSession, async (c) => {
|
|
|
27786
27893
|
for (const name of homeDirs) {
|
|
27787
27894
|
const base = byName.get(name);
|
|
27788
27895
|
try {
|
|
27789
|
-
const dirents = await readdir4(
|
|
27896
|
+
const dirents = await readdir4(join53(absolute, name), { withFileTypes: true });
|
|
27790
27897
|
const visible = dirents.filter((d) => !d.name.startsWith("."));
|
|
27791
27898
|
visible.sort((a, b) => {
|
|
27792
27899
|
const ad = a.isDirectory() ? 0 : 1;
|
|
@@ -27851,7 +27958,7 @@ app28.get("/download", requireAdminSession, async (c) => {
|
|
|
27851
27958
|
console.error(`[data] op=scratchpad-no-session sessionId="${sessionId.slice(0, 8)}\u2026"`);
|
|
27852
27959
|
return c.json({ error: "Not found" }, 404);
|
|
27853
27960
|
}
|
|
27854
|
-
const meta = readSidecarMeta(
|
|
27961
|
+
const meta = readSidecarMeta(join53(projectDir, `${sessionId}.meta.json`));
|
|
27855
27962
|
if (!meta.accountId || meta.accountId !== accountId) {
|
|
27856
27963
|
console.error(`[data] account-scope-blocked root="scratchpad" sessionId="${sessionId.slice(0, 8)}\u2026" account=${accountId.slice(0, 8)}\u2026`);
|
|
27857
27964
|
return c.json({ error: "Not found" }, 404);
|
|
@@ -27945,7 +28052,7 @@ async function* walkRegularFiles(dirAbsolute) {
|
|
|
27945
28052
|
const dirents = await readdir4(dirAbsolute, { withFileTypes: true });
|
|
27946
28053
|
for (const d of dirents) {
|
|
27947
28054
|
if (d.isSymbolicLink()) continue;
|
|
27948
|
-
const child =
|
|
28055
|
+
const child = join53(dirAbsolute, d.name);
|
|
27949
28056
|
if (d.isDirectory()) {
|
|
27950
28057
|
yield* walkRegularFiles(child);
|
|
27951
28058
|
continue;
|
|
@@ -28051,7 +28158,7 @@ async function resolveUploadTarget(c, accountId, uid) {
|
|
|
28051
28158
|
const base = resolveSharedOrOwnAccountWrite(rawDir, accountId, "POST /api/admin/files/upload");
|
|
28052
28159
|
if (!base.ok) return { ok: false, status: base.status, error: base.error };
|
|
28053
28160
|
const relDir = relpath ? dirname16(relpath) : ".";
|
|
28054
|
-
const destRel = relDir === "." ? base.relative :
|
|
28161
|
+
const destRel = relDir === "." ? base.relative : join53(base.relative, relDir);
|
|
28055
28162
|
if ((0, import_dist.isSharedPath)(destRel)) {
|
|
28056
28163
|
const gate2 = gateSharedWrite(base.absolute, destRel, accountId, "POST /api/admin/files/upload");
|
|
28057
28164
|
if (!gate2.ok) return { ok: false, status: gate2.status, error: gate2.error };
|
|
@@ -28437,7 +28544,7 @@ app28.delete("/", requireAdminSession, async (c) => {
|
|
|
28437
28544
|
const dot = base.lastIndexOf(".");
|
|
28438
28545
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
28439
28546
|
const containerDir = dirname16(absolute);
|
|
28440
|
-
const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ?
|
|
28547
|
+
const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join53(containerDir, `${stem}.meta.json`) : null;
|
|
28441
28548
|
const isAttachmentContainer = UUID_RE3.test(stem) && basename15(containerDir) === stem;
|
|
28442
28549
|
await unlink3(absolute);
|
|
28443
28550
|
if (sidecarPath) {
|
|
@@ -28447,7 +28554,7 @@ app28.delete("/", requireAdminSession, async (c) => {
|
|
|
28447
28554
|
}
|
|
28448
28555
|
}
|
|
28449
28556
|
if (isAttachmentContainer) {
|
|
28450
|
-
await unlink3(
|
|
28557
|
+
await unlink3(join53(containerDir, `${stem}${EXTRACTED_TEXT_SUFFIX}`)).catch(() => {
|
|
28451
28558
|
});
|
|
28452
28559
|
await rmdir(containerDir).catch(() => {
|
|
28453
28560
|
});
|
|
@@ -29562,8 +29669,8 @@ function isHiddenByDefault(label) {
|
|
|
29562
29669
|
|
|
29563
29670
|
// server/lib/top-level-labels.ts
|
|
29564
29671
|
var import_dist14 = __toESM(require_dist9(), 1);
|
|
29565
|
-
import { readdirSync as
|
|
29566
|
-
import { join as
|
|
29672
|
+
import { readdirSync as readdirSync27, readFileSync as readFileSync43 } from "fs";
|
|
29673
|
+
import { join as join54, resolve as resolve33 } from "path";
|
|
29567
29674
|
var STATIC_TOP_LEVEL_LABELS = Object.freeze(
|
|
29568
29675
|
/* @__PURE__ */ new Set([
|
|
29569
29676
|
// Base-schema infra (schema-base.md has no top-level section).
|
|
@@ -29667,7 +29774,7 @@ function parseTopLevelLabels(content) {
|
|
|
29667
29774
|
}
|
|
29668
29775
|
function resolveReferencesDir() {
|
|
29669
29776
|
if (process.env.MAXY_PLATFORM_ROOT) {
|
|
29670
|
-
return
|
|
29777
|
+
return join54(process.env.MAXY_PLATFORM_ROOT, "plugins", "memory", "references");
|
|
29671
29778
|
}
|
|
29672
29779
|
return resolve33(import.meta.dirname, "../../../plugins/memory/references");
|
|
29673
29780
|
}
|
|
@@ -29675,9 +29782,9 @@ function parseTableTopLevelLabels(referencesDir) {
|
|
|
29675
29782
|
const labels = /* @__PURE__ */ new Set();
|
|
29676
29783
|
const contributingFiles = [];
|
|
29677
29784
|
try {
|
|
29678
|
-
const fileNames =
|
|
29785
|
+
const fileNames = readdirSync27(referencesDir).filter((f) => f.startsWith("schema-") && f.endsWith(".md")).sort();
|
|
29679
29786
|
for (const fileName of fileNames) {
|
|
29680
|
-
const content =
|
|
29787
|
+
const content = readFileSync43(join54(referencesDir, fileName), "utf-8");
|
|
29681
29788
|
const parsed = parseTopLevelLabels(content);
|
|
29682
29789
|
if (parsed.length > 0) contributingFiles.push(fileName);
|
|
29683
29790
|
for (const label of parsed) labels.add(label);
|
|
@@ -31015,19 +31122,19 @@ function isWithin(target, root) {
|
|
|
31015
31122
|
var sidebar_artefacts_default = app35;
|
|
31016
31123
|
|
|
31017
31124
|
// server/channel-session-override.ts
|
|
31018
|
-
import { readFileSync as
|
|
31019
|
-
import { join as
|
|
31125
|
+
import { readFileSync as readFileSync44, writeFileSync as writeFileSync19, renameSync as renameSync10 } from "fs";
|
|
31126
|
+
import { join as join55 } from "path";
|
|
31020
31127
|
var FILE2 = "channel-session-override.json";
|
|
31021
31128
|
var UUID3 = /^[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}$/;
|
|
31022
31129
|
function channelOverridePath(accountDir) {
|
|
31023
|
-
return
|
|
31130
|
+
return join55(accountDir, FILE2);
|
|
31024
31131
|
}
|
|
31025
31132
|
function senderKey(channel, senderId) {
|
|
31026
31133
|
return `${channel}:${senderId}`;
|
|
31027
31134
|
}
|
|
31028
31135
|
function readRaw2(accountDir) {
|
|
31029
31136
|
try {
|
|
31030
|
-
return JSON.parse(
|
|
31137
|
+
return JSON.parse(readFileSync44(channelOverridePath(accountDir), "utf8"));
|
|
31031
31138
|
} catch {
|
|
31032
31139
|
return null;
|
|
31033
31140
|
}
|
|
@@ -31465,24 +31572,24 @@ var session_rc_spawn_default = app41;
|
|
|
31465
31572
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
31466
31573
|
|
|
31467
31574
|
// server/wa-descriptor.ts
|
|
31468
|
-
import { resolve as resolve35, join as
|
|
31575
|
+
import { resolve as resolve35, join as join56 } from "path";
|
|
31469
31576
|
function waGatewayUrl() {
|
|
31470
31577
|
return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
|
|
31471
31578
|
}
|
|
31472
31579
|
function waServerPath() {
|
|
31473
|
-
return process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve35(process.env.MAXY_PLATFORM_ROOT ??
|
|
31580
|
+
return process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve35(process.env.MAXY_PLATFORM_ROOT ?? join56(__dirname, ".."), "services/whatsapp-channel/dist/server.js");
|
|
31474
31581
|
}
|
|
31475
31582
|
function waChannelDescriptor(senderId) {
|
|
31476
31583
|
return { senderId, gatewayUrl: waGatewayUrl(), serverPath: waServerPath() };
|
|
31477
31584
|
}
|
|
31478
31585
|
|
|
31479
31586
|
// server/telegram-descriptor.ts
|
|
31480
|
-
import { resolve as resolve36, join as
|
|
31587
|
+
import { resolve as resolve36, join as join57 } from "path";
|
|
31481
31588
|
function telegramGatewayUrl() {
|
|
31482
31589
|
return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
|
|
31483
31590
|
}
|
|
31484
31591
|
function telegramServerPath() {
|
|
31485
|
-
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve36(process.env.MAXY_PLATFORM_ROOT ??
|
|
31592
|
+
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve36(process.env.MAXY_PLATFORM_ROOT ?? join57(__dirname, ".."), "services/telegram-channel/dist/server.js");
|
|
31486
31593
|
}
|
|
31487
31594
|
function telegramChannelDescriptor(senderId) {
|
|
31488
31595
|
return { senderId, gatewayUrl: telegramGatewayUrl(), serverPath: telegramServerPath() };
|
|
@@ -31653,12 +31760,12 @@ function parseCpuStat(blob) {
|
|
|
31653
31760
|
const line = blob.split("\n", 1)[0] ?? "";
|
|
31654
31761
|
const parts = line.trim().split(/\s+/);
|
|
31655
31762
|
if (parts[0] !== "cpu") throw new Error(`unexpected /proc/stat header: ${parts[0] ?? "(empty)"}`);
|
|
31656
|
-
const
|
|
31657
|
-
if (
|
|
31763
|
+
const fields2 = parts.slice(1).map((n) => Number.parseInt(n, 10));
|
|
31764
|
+
if (fields2.length < 4 || fields2.some((n) => !Number.isFinite(n))) {
|
|
31658
31765
|
throw new Error("malformed /proc/stat cpu line");
|
|
31659
31766
|
}
|
|
31660
|
-
const idle =
|
|
31661
|
-
const total =
|
|
31767
|
+
const idle = fields2[3] + (fields2[4] ?? 0);
|
|
31768
|
+
const total = fields2.reduce((a, b) => a + b, 0);
|
|
31662
31769
|
return { idle, total };
|
|
31663
31770
|
}
|
|
31664
31771
|
function cpuPctFromSamples(a, b) {
|
|
@@ -31768,14 +31875,14 @@ app43.get("/", async (c) => {
|
|
|
31768
31875
|
var system_stats_default = app43;
|
|
31769
31876
|
|
|
31770
31877
|
// server/routes/admin/health.ts
|
|
31771
|
-
import { existsSync as existsSync45, readFileSync as
|
|
31772
|
-
import { resolve as resolve37, join as
|
|
31878
|
+
import { existsSync as existsSync45, readFileSync as readFileSync45 } from "fs";
|
|
31879
|
+
import { resolve as resolve37, join as join58 } from "path";
|
|
31773
31880
|
var PLATFORM_ROOT4 = process.env.MAXY_PLATFORM_ROOT ?? resolve37(process.cwd(), "..");
|
|
31774
31881
|
var brandHostname = "maxy";
|
|
31775
|
-
var brandJsonPath =
|
|
31882
|
+
var brandJsonPath = join58(PLATFORM_ROOT4, "config", "brand.json");
|
|
31776
31883
|
if (existsSync45(brandJsonPath)) {
|
|
31777
31884
|
try {
|
|
31778
|
-
const brand = JSON.parse(
|
|
31885
|
+
const brand = JSON.parse(readFileSync45(brandJsonPath, "utf-8"));
|
|
31779
31886
|
if (brand.hostname) brandHostname = brand.hostname;
|
|
31780
31887
|
} catch {
|
|
31781
31888
|
}
|
|
@@ -31785,7 +31892,7 @@ var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
|
31785
31892
|
var PROBE_TIMEOUT_MS = 1e3;
|
|
31786
31893
|
function readVersion() {
|
|
31787
31894
|
if (!existsSync45(VERSION_FILE)) return "unknown";
|
|
31788
|
-
return
|
|
31895
|
+
return readFileSync45(VERSION_FILE, "utf-8").trim() || "unknown";
|
|
31789
31896
|
}
|
|
31790
31897
|
async function probeConversationDb() {
|
|
31791
31898
|
let session;
|
|
@@ -31840,7 +31947,7 @@ import { randomUUID as randomUUID10 } from "crypto";
|
|
|
31840
31947
|
|
|
31841
31948
|
// ../lib/account-ingest-token/src/index.ts
|
|
31842
31949
|
import { randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
31843
|
-
import { existsSync as existsSync46, readdirSync as
|
|
31950
|
+
import { existsSync as existsSync46, readdirSync as readdirSync28, readFileSync as readFileSync46, writeFileSync as writeFileSync20 } from "fs";
|
|
31844
31951
|
import { resolve as resolve38 } from "path";
|
|
31845
31952
|
var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
31846
31953
|
var INGEST_TOKEN_FIELD = "ingestToken";
|
|
@@ -31852,7 +31959,7 @@ function readConfig2(accountsDir, accountId) {
|
|
|
31852
31959
|
const path = configPath2(accountsDir, accountId);
|
|
31853
31960
|
if (!existsSync46(path)) return null;
|
|
31854
31961
|
try {
|
|
31855
|
-
const parsed = JSON.parse(
|
|
31962
|
+
const parsed = JSON.parse(readFileSync46(path, "utf-8"));
|
|
31856
31963
|
return parsed !== null && typeof parsed === "object" ? parsed : null;
|
|
31857
31964
|
} catch {
|
|
31858
31965
|
return null;
|
|
@@ -31866,7 +31973,7 @@ function listAccountIdsOnDisk(accountsDir) {
|
|
|
31866
31973
|
if (!existsSync46(accountsDir)) return [];
|
|
31867
31974
|
let entries2;
|
|
31868
31975
|
try {
|
|
31869
|
-
entries2 =
|
|
31976
|
+
entries2 = readdirSync28(accountsDir);
|
|
31870
31977
|
} catch {
|
|
31871
31978
|
return [];
|
|
31872
31979
|
}
|
|
@@ -32393,9 +32500,9 @@ function renderWrite(write) {
|
|
|
32393
32500
|
const val = String(v).slice(0, 200);
|
|
32394
32501
|
kv.push(`${k}=${val}`);
|
|
32395
32502
|
}
|
|
32396
|
-
const
|
|
32397
|
-
if (
|
|
32398
|
-
return `- ${label}: ${
|
|
32503
|
+
const tail2 = [parts.join(" "), kv.join("; ")].filter((s) => s.length > 0).join(" \u2014 ");
|
|
32504
|
+
if (tail2.length === 0) return null;
|
|
32505
|
+
return `- ${label}: ${tail2}`;
|
|
32399
32506
|
}
|
|
32400
32507
|
function formatPreviousContext(writes) {
|
|
32401
32508
|
if (writes.length === 0) return null;
|
|
@@ -32705,7 +32812,7 @@ var browser_default = app51;
|
|
|
32705
32812
|
// server/routes/admin/calendar.ts
|
|
32706
32813
|
import { existsSync as existsSync47 } from "fs";
|
|
32707
32814
|
import { randomUUID as randomUUID11 } from "crypto";
|
|
32708
|
-
import { join as
|
|
32815
|
+
import { join as join60 } from "path";
|
|
32709
32816
|
|
|
32710
32817
|
// server/lib/calendar-ics.ts
|
|
32711
32818
|
var CRLF = "\r\n";
|
|
@@ -32805,8 +32912,8 @@ function countVEvents(ics) {
|
|
|
32805
32912
|
}
|
|
32806
32913
|
|
|
32807
32914
|
// server/lib/calendar-availability.ts
|
|
32808
|
-
import { readFileSync as
|
|
32809
|
-
import { join as
|
|
32915
|
+
import { readFileSync as readFileSync47 } from "fs";
|
|
32916
|
+
import { join as join59 } from "path";
|
|
32810
32917
|
var AVAILABILITY_FILENAME = "calendar-availability.json";
|
|
32811
32918
|
var REQUIRED_KEYS = [
|
|
32812
32919
|
"timezone",
|
|
@@ -32815,10 +32922,10 @@ var REQUIRED_KEYS = [
|
|
|
32815
32922
|
"weekly"
|
|
32816
32923
|
];
|
|
32817
32924
|
function readAvailabilityConfig(accountDir) {
|
|
32818
|
-
const path =
|
|
32925
|
+
const path = join59(accountDir, AVAILABILITY_FILENAME);
|
|
32819
32926
|
let raw;
|
|
32820
32927
|
try {
|
|
32821
|
-
raw =
|
|
32928
|
+
raw = readFileSync47(path, "utf-8");
|
|
32822
32929
|
} catch {
|
|
32823
32930
|
throw new Error(`availability not configured: ${path} not found`);
|
|
32824
32931
|
}
|
|
@@ -33204,16 +33311,16 @@ app52.patch("/meetings/:id", requireAdminSession, async (c) => {
|
|
|
33204
33311
|
}
|
|
33205
33312
|
const id = c.req.param("id");
|
|
33206
33313
|
const body = await safeJson(c) ?? {};
|
|
33207
|
-
const
|
|
33208
|
-
if (
|
|
33314
|
+
const fields2 = EDITABLE_FIELDS.filter((f) => f in body);
|
|
33315
|
+
if (fields2.length === 0) {
|
|
33209
33316
|
return c.json({ error: "No editable field supplied (title, startsAt, endsAt, location, description, privateNote)" }, 400);
|
|
33210
33317
|
}
|
|
33211
|
-
const setClauses =
|
|
33318
|
+
const setClauses = fields2.map(
|
|
33212
33319
|
(f) => f === "startsAt" || f === "endsAt" ? `m.${f} = datetime($${f})` : `m.${f} = $${f}`
|
|
33213
33320
|
);
|
|
33214
33321
|
setClauses.push("m.updatedAt = datetime()");
|
|
33215
33322
|
const params = { accountId, id };
|
|
33216
|
-
for (const f of
|
|
33323
|
+
for (const f of fields2) params[f] = body[f];
|
|
33217
33324
|
const session = getSession();
|
|
33218
33325
|
try {
|
|
33219
33326
|
const res = await session.run(
|
|
@@ -33224,12 +33331,12 @@ app52.patch("/meetings/:id", requireAdminSession, async (c) => {
|
|
|
33224
33331
|
params
|
|
33225
33332
|
);
|
|
33226
33333
|
if (res.records.length === 0) {
|
|
33227
|
-
console.warn(`[calendar-edit] account=${accountId.slice(0, 8)} uid=absent fields=${
|
|
33334
|
+
console.warn(`[calendar-edit] account=${accountId.slice(0, 8)} uid=absent fields=${fields2.join(",")} found=0`);
|
|
33228
33335
|
return c.json({ error: "Meeting not found for this account" }, 404);
|
|
33229
33336
|
}
|
|
33230
33337
|
const r = res.records[0];
|
|
33231
33338
|
const uid = r.get("uid");
|
|
33232
|
-
console.log(`[calendar-edit] account=${accountId.slice(0, 8)} uid=${uid ?? "absent"} fields=${
|
|
33339
|
+
console.log(`[calendar-edit] account=${accountId.slice(0, 8)} uid=${uid ?? "absent"} fields=${fields2.join(",")}`);
|
|
33233
33340
|
return c.json({ meeting: mapMeeting(r) });
|
|
33234
33341
|
} catch (err) {
|
|
33235
33342
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -33373,7 +33480,7 @@ app52.get("/booking-link", requireAdminSession, (c) => {
|
|
|
33373
33480
|
}
|
|
33374
33481
|
const id83 = account.accountId.slice(0, 8);
|
|
33375
33482
|
try {
|
|
33376
|
-
if (!existsSync47(
|
|
33483
|
+
if (!existsSync47(join60(account.accountDir, AVAILABILITY_FILENAME))) {
|
|
33377
33484
|
console.log(`[calendar] op=booking-link accountId=${id83} bookingDomain=none source=availability-config`);
|
|
33378
33485
|
return c.json({ bookingDomain: null });
|
|
33379
33486
|
}
|
|
@@ -33392,8 +33499,8 @@ app52.get("/booking-link", requireAdminSession, (c) => {
|
|
|
33392
33499
|
var calendar_default = app52;
|
|
33393
33500
|
|
|
33394
33501
|
// server/routes/admin/data-portal.ts
|
|
33395
|
-
import { existsSync as existsSync48, readFileSync as
|
|
33396
|
-
import { join as
|
|
33502
|
+
import { existsSync as existsSync48, readFileSync as readFileSync48 } from "fs";
|
|
33503
|
+
import { join as join61 } from "path";
|
|
33397
33504
|
var app53 = new Hono();
|
|
33398
33505
|
var PORTAL_FILENAME = "data-portal.json";
|
|
33399
33506
|
app53.get("/portal-link", requireAdminSession, (c) => {
|
|
@@ -33404,12 +33511,12 @@ app53.get("/portal-link", requireAdminSession, (c) => {
|
|
|
33404
33511
|
}
|
|
33405
33512
|
const id83 = account.accountId.slice(0, 8);
|
|
33406
33513
|
try {
|
|
33407
|
-
const path =
|
|
33514
|
+
const path = join61(account.accountDir, PORTAL_FILENAME);
|
|
33408
33515
|
if (!existsSync48(path)) {
|
|
33409
33516
|
console.log(`[data-portal] op=portal-link accountId=${id83} portalDomain=none source=data-portal-config`);
|
|
33410
33517
|
return c.json({ portalDomain: null });
|
|
33411
33518
|
}
|
|
33412
|
-
const cfg = JSON.parse(
|
|
33519
|
+
const cfg = JSON.parse(readFileSync48(path, "utf-8"));
|
|
33413
33520
|
const portalDomain = typeof cfg.portalDomain === "string" && cfg.portalDomain.trim() ? cfg.portalDomain.trim() : null;
|
|
33414
33521
|
console.log(`[data-portal] op=portal-link accountId=${id83} portalDomain=${portalDomain ?? "none"} source=data-portal-config`);
|
|
33415
33522
|
return c.json({ portalDomain });
|
|
@@ -33422,8 +33529,8 @@ app53.get("/portal-link", requireAdminSession, (c) => {
|
|
|
33422
33529
|
var data_portal_default = app53;
|
|
33423
33530
|
|
|
33424
33531
|
// server/routes/admin/dispatch-planner.ts
|
|
33425
|
-
import { existsSync as existsSync49, readFileSync as
|
|
33426
|
-
import { join as
|
|
33532
|
+
import { existsSync as existsSync49, readFileSync as readFileSync49 } from "fs";
|
|
33533
|
+
import { join as join62 } from "path";
|
|
33427
33534
|
var app54 = new Hono();
|
|
33428
33535
|
var PORTAL_FILENAME2 = "data-portal.json";
|
|
33429
33536
|
app54.get("/planner-link", requireAdminSession, (c) => {
|
|
@@ -33436,15 +33543,15 @@ app54.get("/planner-link", requireAdminSession, (c) => {
|
|
|
33436
33543
|
}
|
|
33437
33544
|
const id83 = account.accountId.slice(0, 8);
|
|
33438
33545
|
try {
|
|
33439
|
-
const portalPath =
|
|
33440
|
-
const dispatchConfigured = existsSync49(
|
|
33546
|
+
const portalPath = join62(account.accountDir, PORTAL_FILENAME2);
|
|
33547
|
+
const dispatchConfigured = existsSync49(join62(account.accountDir, "dispatch", "config.json"));
|
|
33441
33548
|
if (!existsSync49(portalPath) || !dispatchConfigured) {
|
|
33442
33549
|
console.log(
|
|
33443
33550
|
`[dispatch-planner] op=planner-link accountId=${id83} plannerUrl=none portal=${existsSync49(portalPath)} dispatch=${dispatchConfigured}`
|
|
33444
33551
|
);
|
|
33445
33552
|
return c.json({ plannerUrl: null });
|
|
33446
33553
|
}
|
|
33447
|
-
const cfg = JSON.parse(
|
|
33554
|
+
const cfg = JSON.parse(readFileSync49(portalPath, "utf-8"));
|
|
33448
33555
|
const domain = typeof cfg.portalDomain === "string" && cfg.portalDomain.trim() ? cfg.portalDomain.trim() : null;
|
|
33449
33556
|
const plannerUrl = domain ? `https://${domain}/planner` : null;
|
|
33450
33557
|
console.log(
|
|
@@ -33462,11 +33569,11 @@ var dispatch_planner_default = app54;
|
|
|
33462
33569
|
// server/routes/admin/routines.ts
|
|
33463
33570
|
import cronParser from "cron-parser";
|
|
33464
33571
|
import { int as int2 } from "neo4j-driver";
|
|
33465
|
-
import { readFileSync as
|
|
33572
|
+
import { readFileSync as readFileSync51 } from "fs";
|
|
33466
33573
|
import { resolve as resolve40 } from "path";
|
|
33467
33574
|
|
|
33468
33575
|
// ../lib/agent-dispatch-rule/src/index.ts
|
|
33469
|
-
import { readFileSync as
|
|
33576
|
+
import { readFileSync as readFileSync50 } from "fs";
|
|
33470
33577
|
import { resolve as resolve39 } from "path";
|
|
33471
33578
|
function normalizeE1642(value) {
|
|
33472
33579
|
let candidate = value.trim().replace(/[\s\-().]/g, "");
|
|
@@ -33484,7 +33591,7 @@ function phonesMatch2(a, b) {
|
|
|
33484
33591
|
function readChannelAdmins(accountDir, channel) {
|
|
33485
33592
|
let config = {};
|
|
33486
33593
|
try {
|
|
33487
|
-
config = JSON.parse(
|
|
33594
|
+
config = JSON.parse(readFileSync50(resolve39(accountDir, "account.json"), "utf-8"));
|
|
33488
33595
|
} catch {
|
|
33489
33596
|
config = {};
|
|
33490
33597
|
}
|
|
@@ -33591,23 +33698,39 @@ function listDispatchDestinations(input) {
|
|
|
33591
33698
|
const byDestination = (a, b) => a.destination.localeCompare(b.destination);
|
|
33592
33699
|
return [...managers.sort(byDestination), ...admins.sort(byDestination), ...telegram];
|
|
33593
33700
|
}
|
|
33594
|
-
function isDispatchable(
|
|
33595
|
-
if (
|
|
33596
|
-
return Boolean(
|
|
33701
|
+
function isDispatchable(fields2) {
|
|
33702
|
+
if (fields2.agentChannel && fields2.agentDestination && fields2.agentPrompt) return true;
|
|
33703
|
+
return Boolean(fields2.actionPlugin && fields2.actionTool);
|
|
33597
33704
|
}
|
|
33598
|
-
function dispatchGapReason(
|
|
33599
|
-
if (
|
|
33705
|
+
function dispatchGapReason(fields2) {
|
|
33706
|
+
if (fields2.agentChannel || fields2.agentDestination || fields2.agentPrompt) {
|
|
33600
33707
|
const missing = [];
|
|
33601
|
-
if (!
|
|
33602
|
-
if (!
|
|
33603
|
-
if (!
|
|
33708
|
+
if (!fields2.agentChannel) missing.push("channel");
|
|
33709
|
+
if (!fields2.agentDestination) missing.push("destination");
|
|
33710
|
+
if (!fields2.agentPrompt) missing.push("prompt");
|
|
33604
33711
|
return `no-${missing.join("+")}`;
|
|
33605
33712
|
}
|
|
33606
|
-
if (
|
|
33607
|
-
return
|
|
33713
|
+
if (fields2.actionPlugin || fields2.actionTool) {
|
|
33714
|
+
return fields2.actionTool ? "no-action-plugin" : "no-action-tool";
|
|
33608
33715
|
}
|
|
33609
33716
|
return "no-dispatch-configured";
|
|
33610
33717
|
}
|
|
33718
|
+
function carrierVerdict(accountDir, botId, destination) {
|
|
33719
|
+
let config = {};
|
|
33720
|
+
try {
|
|
33721
|
+
config = JSON.parse(readFileSync50(resolve39(accountDir, "account.json"), "utf-8"));
|
|
33722
|
+
} catch {
|
|
33723
|
+
return { ok: false, reason: "absent" };
|
|
33724
|
+
}
|
|
33725
|
+
const bots = Array.isArray(config.telegram?.bots) ? config.telegram.bots : [];
|
|
33726
|
+
const entry3 = bots.find(
|
|
33727
|
+
(raw) => raw && typeof raw === "object" && raw.id === botId
|
|
33728
|
+
);
|
|
33729
|
+
if (!entry3) return { ok: false, reason: "absent" };
|
|
33730
|
+
if (entry3.role !== "admin") return { ok: false, reason: "not-admin" };
|
|
33731
|
+
const users = Array.isArray(entry3.adminUsers) ? entry3.adminUsers.filter((u) => typeof u === "number") : [];
|
|
33732
|
+
return users.includes(Number(destination)) ? { ok: true } : { ok: false, reason: "not-listed" };
|
|
33733
|
+
}
|
|
33611
33734
|
|
|
33612
33735
|
// server/routes/admin/routines.ts
|
|
33613
33736
|
var { parseExpression } = cronParser;
|
|
@@ -33652,7 +33775,7 @@ function gateWatermarkPath(eventId) {
|
|
|
33652
33775
|
}
|
|
33653
33776
|
function readGateLastCommitAt(eventId) {
|
|
33654
33777
|
try {
|
|
33655
|
-
const parsed = JSON.parse(
|
|
33778
|
+
const parsed = JSON.parse(readFileSync51(gateWatermarkPath(eventId), "utf-8"));
|
|
33656
33779
|
return typeof parsed?.lastCommitAt === "string" ? parsed.lastCommitAt : null;
|
|
33657
33780
|
} catch {
|
|
33658
33781
|
return null;
|
|
@@ -33762,9 +33885,9 @@ function describeDispatchGap(reason) {
|
|
|
33762
33885
|
destination: "a destination",
|
|
33763
33886
|
prompt: "an instruction"
|
|
33764
33887
|
};
|
|
33765
|
-
const
|
|
33766
|
-
if (
|
|
33767
|
-
const list =
|
|
33888
|
+
const fields2 = reason.startsWith("no-") ? reason.slice(3).split("+") : [];
|
|
33889
|
+
if (fields2.length > 0 && fields2.every((f) => f in words)) {
|
|
33890
|
+
const list = fields2.map((f) => words[f]);
|
|
33768
33891
|
const joined = list.length === 1 ? list[0] : `${list.slice(0, -1).join(", ")} and ${list[list.length - 1]}`;
|
|
33769
33892
|
return `This routine has no ${joined.replace(/^an? /, "")} set, so arming it would deliver nothing.`;
|
|
33770
33893
|
}
|
|
@@ -34093,7 +34216,7 @@ app55.patch("/:eventId", requireAdminSession, async (c) => {
|
|
|
34093
34216
|
const id83 = eventId.slice(0, 8);
|
|
34094
34217
|
const setClauses = [];
|
|
34095
34218
|
const params = { eventId, accountId };
|
|
34096
|
-
const
|
|
34219
|
+
const fields2 = [];
|
|
34097
34220
|
let nextRunLog = "unchanged";
|
|
34098
34221
|
let bindingLog = "";
|
|
34099
34222
|
const hasChannel = "agentChannel" in body;
|
|
@@ -34177,7 +34300,7 @@ app55.patch("/:eventId", requireAdminSession, async (c) => {
|
|
|
34177
34300
|
setClauses.push("e.agentChannel = $agentChannel", "e.agentDestination = $agentDestination");
|
|
34178
34301
|
params.agentChannel = channel;
|
|
34179
34302
|
params.agentDestination = destination;
|
|
34180
|
-
|
|
34303
|
+
fields2.push("agentChannel", "agentDestination");
|
|
34181
34304
|
bindingLog = ` channel=${channel} destination=${destination.slice(-4)}`;
|
|
34182
34305
|
}
|
|
34183
34306
|
if (clearing) {
|
|
@@ -34190,13 +34313,13 @@ app55.patch("/:eventId", requireAdminSession, async (c) => {
|
|
|
34190
34313
|
);
|
|
34191
34314
|
}
|
|
34192
34315
|
setClauses.push("e.agentChannel = null", "e.agentDestination = null");
|
|
34193
|
-
|
|
34316
|
+
fields2.push("agentChannel", "agentDestination");
|
|
34194
34317
|
bindingLog = " channel=none destination=none";
|
|
34195
34318
|
}
|
|
34196
34319
|
if (typeof body.agentPrompt === "string") {
|
|
34197
34320
|
setClauses.push("e.agentPrompt = $agentPrompt");
|
|
34198
34321
|
params.agentPrompt = body.agentPrompt;
|
|
34199
|
-
|
|
34322
|
+
fields2.push("agentPrompt");
|
|
34200
34323
|
setClauses.push("e.operatorEdited = $operatorEdited");
|
|
34201
34324
|
params.operatorEdited = (/* @__PURE__ */ new Date()).toISOString();
|
|
34202
34325
|
}
|
|
@@ -34213,7 +34336,7 @@ app55.patch("/:eventId", requireAdminSession, async (c) => {
|
|
|
34213
34336
|
}
|
|
34214
34337
|
setClauses.push("e.name = $name");
|
|
34215
34338
|
params.name = nextName;
|
|
34216
|
-
|
|
34339
|
+
fields2.push("name");
|
|
34217
34340
|
setClauses.push("e.operatorEdited = $operatorEdited");
|
|
34218
34341
|
params.operatorEdited = (/* @__PURE__ */ new Date()).toISOString();
|
|
34219
34342
|
}
|
|
@@ -34227,7 +34350,7 @@ app55.patch("/:eventId", requireAdminSession, async (c) => {
|
|
|
34227
34350
|
nextDescription = typeof raw === "string" && raw.trim().length > 0 ? raw : null;
|
|
34228
34351
|
setClauses.push("e.description = $description");
|
|
34229
34352
|
params.description = nextDescription;
|
|
34230
|
-
|
|
34353
|
+
fields2.push("description");
|
|
34231
34354
|
setClauses.push("e.operatorEdited = $operatorEdited");
|
|
34232
34355
|
params.operatorEdited = (/* @__PURE__ */ new Date()).toISOString();
|
|
34233
34356
|
}
|
|
@@ -34242,7 +34365,7 @@ app55.patch("/:eventId", requireAdminSession, async (c) => {
|
|
|
34242
34365
|
params.embedding = embedding;
|
|
34243
34366
|
} else {
|
|
34244
34367
|
embedLog = " embed=failed";
|
|
34245
|
-
console.error(`[admin:routines] op=patch id=${id83} fields=${
|
|
34368
|
+
console.error(`[admin:routines] op=patch id=${id83} fields=${fields2.join("+")} embed=failed`);
|
|
34246
34369
|
}
|
|
34247
34370
|
}
|
|
34248
34371
|
if (typeof body.recurrence === "string") {
|
|
@@ -34252,7 +34375,7 @@ app55.patch("/:eventId", requireAdminSession, async (c) => {
|
|
|
34252
34375
|
setClauses.push("e.recurrence = $recurrence", "e.nextRun = $nextRun");
|
|
34253
34376
|
params.recurrence = body.recurrence;
|
|
34254
34377
|
params.nextRun = nextRun;
|
|
34255
|
-
|
|
34378
|
+
fields2.push("recurrence");
|
|
34256
34379
|
nextRunLog = nextRun;
|
|
34257
34380
|
} catch (err) {
|
|
34258
34381
|
const reason = err instanceof Error ? err.message : String(err);
|
|
@@ -34278,7 +34401,7 @@ app55.patch("/:eventId", requireAdminSession, async (c) => {
|
|
|
34278
34401
|
return c.json({ error: "Routine not found" }, 404);
|
|
34279
34402
|
}
|
|
34280
34403
|
const nameLog = nextName === null ? "" : ` name=len:${nextName.length} operatorEdited=stamped`;
|
|
34281
|
-
console.log(`[admin:routines] op=patch id=${id83} fields=${
|
|
34404
|
+
console.log(`[admin:routines] op=patch id=${id83} fields=${fields2.join("+")} outcome=ok nextRun=${nextRunLog} cron=${params.recurrence ?? "unchanged"}${bindingLog}${nameLog}${embedLog}`);
|
|
34282
34405
|
return c.json({ routine: mapRoutine(res.records[0]) });
|
|
34283
34406
|
} catch (err) {
|
|
34284
34407
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -34529,7 +34652,7 @@ app55.delete("/:eventId", requireAdminSession, async (c) => {
|
|
|
34529
34652
|
var routines_default = app55;
|
|
34530
34653
|
|
|
34531
34654
|
// server/routes/admin/skills.ts
|
|
34532
|
-
import { existsSync as existsSync50, readdirSync as
|
|
34655
|
+
import { existsSync as existsSync50, readdirSync as readdirSync29, readFileSync as readFileSync52, rmSync as rmSync6 } from "fs";
|
|
34533
34656
|
import { resolve as resolve41 } from "path";
|
|
34534
34657
|
var app56 = new Hono();
|
|
34535
34658
|
var NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
@@ -34555,7 +34678,7 @@ function stripQuotes(s) {
|
|
|
34555
34678
|
function subdirs2(dir) {
|
|
34556
34679
|
if (!existsSync50(dir)) return [];
|
|
34557
34680
|
try {
|
|
34558
|
-
return
|
|
34681
|
+
return readdirSync29(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
34559
34682
|
} catch {
|
|
34560
34683
|
return [];
|
|
34561
34684
|
}
|
|
@@ -34578,9 +34701,9 @@ app56.get("/", requireAdminSession, async (c) => {
|
|
|
34578
34701
|
const skillMd = resolve41(skillsDir, skill, "SKILL.md");
|
|
34579
34702
|
if (!existsSync50(skillMd)) continue;
|
|
34580
34703
|
try {
|
|
34581
|
-
const { frontmatter } = splitSkillMd(
|
|
34704
|
+
const { frontmatter } = splitSkillMd(readFileSync52(skillMd, "utf-8"));
|
|
34582
34705
|
const refsDir = resolve41(skillsDir, skill, "references");
|
|
34583
|
-
const refCount = existsSync50(refsDir) ?
|
|
34706
|
+
const refCount = existsSync50(refsDir) ? readdirSync29(refsDir, { withFileTypes: true }).filter((e) => e.isFile()).length : 0;
|
|
34584
34707
|
skills.push({ plugin, skill, description: frontmatter.description, refCount });
|
|
34585
34708
|
} catch (err) {
|
|
34586
34709
|
console.error(`[admin:skills] op=list-skip plugin=${plugin} skill=${skill} reason="${err instanceof Error ? err.message : String(err)}"`);
|
|
@@ -34608,9 +34731,9 @@ app56.get("/:plugin/:skill", requireAdminSession, async (c) => {
|
|
|
34608
34731
|
console.log(`[admin:skills] op=get plugin=${plugin} skill=${skill} found=${found}`);
|
|
34609
34732
|
if (!found) return c.json({ error: "Skill not found" }, 404);
|
|
34610
34733
|
try {
|
|
34611
|
-
const { frontmatter, body } = splitSkillMd(
|
|
34734
|
+
const { frontmatter, body } = splitSkillMd(readFileSync52(skillMd, "utf-8"));
|
|
34612
34735
|
const refsDir = resolve41(skillDir, "references");
|
|
34613
|
-
const references = existsSync50(refsDir) ?
|
|
34736
|
+
const references = existsSync50(refsDir) ? readdirSync29(refsDir, { withFileTypes: true }).filter((e) => e.isFile()).map((e) => e.name).sort() : [];
|
|
34614
34737
|
return c.json({ skill: { plugin, skill, frontmatter, body, references } });
|
|
34615
34738
|
} catch (err) {
|
|
34616
34739
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -34654,7 +34777,7 @@ app56.delete("/:plugin/:skill", requireAdminSession, async (c) => {
|
|
|
34654
34777
|
var skills_default = app56;
|
|
34655
34778
|
|
|
34656
34779
|
// server/routes/admin/tasks-list.ts
|
|
34657
|
-
import { basename as basename17, join as
|
|
34780
|
+
import { basename as basename17, join as join63 } from "path";
|
|
34658
34781
|
|
|
34659
34782
|
// app/lib/time-entry-format.ts
|
|
34660
34783
|
function secondsBetween(startIso, endIso) {
|
|
@@ -34830,7 +34953,7 @@ async function computeTaskList(accountId) {
|
|
|
34830
34953
|
dangling = 0;
|
|
34831
34954
|
} else if (cfg !== null) {
|
|
34832
34955
|
try {
|
|
34833
|
-
const walk = enumerateJsonlsWithSkips(
|
|
34956
|
+
const walk = enumerateJsonlsWithSkips(join63(cfg, "projects"));
|
|
34834
34957
|
if (walk.skipped > 0) {
|
|
34835
34958
|
console.error(
|
|
34836
34959
|
`${TAG51} op=session-dangling-census-incomplete account=${accountId} skipped=${walk.skipped} detail="a slug the walk could not read contributes no session ids, so its links cannot be judged"`
|
|
@@ -35242,12 +35365,12 @@ app62.post("/", requireAdminSession, async (c) => {
|
|
|
35242
35365
|
var task_delete_default = app62;
|
|
35243
35366
|
|
|
35244
35367
|
// app/lib/admin-roster.ts
|
|
35245
|
-
import { existsSync as existsSync51, readdirSync as
|
|
35368
|
+
import { existsSync as existsSync51, readdirSync as readdirSync30, readFileSync as readFileSync53 } from "fs";
|
|
35246
35369
|
import { resolve as resolve42 } from "path";
|
|
35247
35370
|
function readHouseAdminUserIds(accountsDir = ACCOUNTS_DIR) {
|
|
35248
35371
|
let entries2;
|
|
35249
35372
|
try {
|
|
35250
|
-
entries2 =
|
|
35373
|
+
entries2 = readdirSync30(accountsDir);
|
|
35251
35374
|
} catch {
|
|
35252
35375
|
return [];
|
|
35253
35376
|
}
|
|
@@ -35255,7 +35378,7 @@ function readHouseAdminUserIds(accountsDir = ACCOUNTS_DIR) {
|
|
|
35255
35378
|
const cfgPath = resolve42(accountsDir, entry3, "account.json");
|
|
35256
35379
|
if (!existsSync51(cfgPath)) continue;
|
|
35257
35380
|
try {
|
|
35258
|
-
const cfg = JSON.parse(
|
|
35381
|
+
const cfg = JSON.parse(readFileSync53(cfgPath, "utf-8"));
|
|
35259
35382
|
if (cfg.role !== "house") continue;
|
|
35260
35383
|
if (!Array.isArray(cfg.admins)) return [];
|
|
35261
35384
|
return cfg.admins.map(
|
|
@@ -35670,7 +35793,7 @@ app67.get("/", requireAdminSession, async (c) => {
|
|
|
35670
35793
|
var dispatch_destinations_default = app67;
|
|
35671
35794
|
|
|
35672
35795
|
// server/routes/admin/activity.ts
|
|
35673
|
-
import { readdirSync as
|
|
35796
|
+
import { readdirSync as readdirSync31 } from "fs";
|
|
35674
35797
|
var app68 = new Hono();
|
|
35675
35798
|
var TAG62 = "[activity]";
|
|
35676
35799
|
function resolveHouseAccountId2(accounts) {
|
|
@@ -35686,7 +35809,7 @@ function requestToken() {
|
|
|
35686
35809
|
var short = (id) => id ? id.slice(0, 8) : "unset";
|
|
35687
35810
|
function countAccountDirsOnDisk() {
|
|
35688
35811
|
try {
|
|
35689
|
-
return
|
|
35812
|
+
return readdirSync31(ACCOUNTS_DIR, { withFileTypes: true }).filter(
|
|
35690
35813
|
(e) => e.isDirectory() && !e.name.startsWith(".")
|
|
35691
35814
|
).length;
|
|
35692
35815
|
} catch {
|
|
@@ -36097,7 +36220,7 @@ app72.route("/request-magic-link", request_magic_link_default);
|
|
|
36097
36220
|
var access_default = app72;
|
|
36098
36221
|
|
|
36099
36222
|
// server/routes/sites.ts
|
|
36100
|
-
import { existsSync as existsSync52, readFileSync as
|
|
36223
|
+
import { existsSync as existsSync52, readFileSync as readFileSync54, realpathSync as realpathSync8, statSync as statSync28 } from "fs";
|
|
36101
36224
|
import { resolve as resolve45 } from "path";
|
|
36102
36225
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
36103
36226
|
var MIME = {
|
|
@@ -36163,7 +36286,7 @@ app73.get("/:rel{.*}", (c) => {
|
|
|
36163
36286
|
}
|
|
36164
36287
|
let stat11;
|
|
36165
36288
|
try {
|
|
36166
|
-
stat11 = existsSync52(filePath) ?
|
|
36289
|
+
stat11 = existsSync52(filePath) ? statSync28(filePath) : null;
|
|
36167
36290
|
} catch {
|
|
36168
36291
|
stat11 = null;
|
|
36169
36292
|
}
|
|
@@ -36201,7 +36324,7 @@ app73.get("/:rel{.*}", (c) => {
|
|
|
36201
36324
|
}
|
|
36202
36325
|
let body;
|
|
36203
36326
|
try {
|
|
36204
|
-
body =
|
|
36327
|
+
body = readFileSync54(realPath);
|
|
36205
36328
|
} catch (err) {
|
|
36206
36329
|
const code = err?.code;
|
|
36207
36330
|
if (code === "EISDIR") {
|
|
@@ -36237,7 +36360,7 @@ var sites_default = app73;
|
|
|
36237
36360
|
|
|
36238
36361
|
// app/lib/visitor-token.ts
|
|
36239
36362
|
import { createHmac as createHmac2, randomBytes as randomBytes3, timingSafeEqual as timingSafeEqual3 } from "crypto";
|
|
36240
|
-
import { mkdirSync as mkdirSync12, readFileSync as
|
|
36363
|
+
import { mkdirSync as mkdirSync12, readFileSync as readFileSync55, writeFileSync as writeFileSync21 } from "fs";
|
|
36241
36364
|
import { dirname as dirname17 } from "path";
|
|
36242
36365
|
var TOKEN_PREFIX = "v1.";
|
|
36243
36366
|
var SECRET_BYTES = 32;
|
|
@@ -36246,7 +36369,7 @@ var cachedSecret = null;
|
|
|
36246
36369
|
function getSecret() {
|
|
36247
36370
|
if (cachedSecret) return cachedSecret;
|
|
36248
36371
|
try {
|
|
36249
|
-
const hex2 =
|
|
36372
|
+
const hex2 = readFileSync55(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
36250
36373
|
if (hex2.length === SECRET_BYTES * 2) {
|
|
36251
36374
|
cachedSecret = Buffer.from(hex2, "hex");
|
|
36252
36375
|
return cachedSecret;
|
|
@@ -36260,7 +36383,7 @@ function getSecret() {
|
|
|
36260
36383
|
console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
|
|
36261
36384
|
} catch {
|
|
36262
36385
|
}
|
|
36263
|
-
const hex =
|
|
36386
|
+
const hex = readFileSync55(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
36264
36387
|
cachedSecret = Buffer.from(hex, "hex");
|
|
36265
36388
|
return cachedSecret;
|
|
36266
36389
|
}
|
|
@@ -36313,8 +36436,8 @@ var VISITOR_COOKIE_NAME = "mxy_v";
|
|
|
36313
36436
|
var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
|
|
36314
36437
|
|
|
36315
36438
|
// app/lib/brand-config.ts
|
|
36316
|
-
import { existsSync as existsSync53, readFileSync as
|
|
36317
|
-
import { join as
|
|
36439
|
+
import { existsSync as existsSync53, readFileSync as readFileSync56 } from "fs";
|
|
36440
|
+
import { join as join64 } from "path";
|
|
36318
36441
|
var cached2 = null;
|
|
36319
36442
|
var cachedAttempted = false;
|
|
36320
36443
|
function readBrandConfig() {
|
|
@@ -36322,10 +36445,10 @@ function readBrandConfig() {
|
|
|
36322
36445
|
cachedAttempted = true;
|
|
36323
36446
|
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT;
|
|
36324
36447
|
if (!platformRoot5) return null;
|
|
36325
|
-
const brandPath =
|
|
36448
|
+
const brandPath = join64(platformRoot5, "config", "brand.json");
|
|
36326
36449
|
if (!existsSync53(brandPath)) return null;
|
|
36327
36450
|
try {
|
|
36328
|
-
cached2 = JSON.parse(
|
|
36451
|
+
cached2 = JSON.parse(readFileSync56(brandPath, "utf-8"));
|
|
36329
36452
|
return cached2;
|
|
36330
36453
|
} catch {
|
|
36331
36454
|
return null;
|
|
@@ -37091,7 +37214,7 @@ var calendar_public_default = app78;
|
|
|
37091
37214
|
// server/routes/portal-fetch.ts
|
|
37092
37215
|
import { createReadStream as createReadStream3 } from "fs";
|
|
37093
37216
|
import { stat as stat8, readFile as readFile12, realpath } from "fs/promises";
|
|
37094
|
-
import { join as
|
|
37217
|
+
import { join as join65, resolve as resolve47, sep as sep11 } from "path";
|
|
37095
37218
|
import { Readable as Readable3 } from "stream";
|
|
37096
37219
|
var app79 = new Hono();
|
|
37097
37220
|
var TAG65 = "[portal-fetch]";
|
|
@@ -37164,7 +37287,7 @@ function isValidAccountId2(value) {
|
|
|
37164
37287
|
}
|
|
37165
37288
|
async function readExposeFolders2(accountDir) {
|
|
37166
37289
|
try {
|
|
37167
|
-
const cfg = JSON.parse(await readFile12(
|
|
37290
|
+
const cfg = JSON.parse(await readFile12(join65(accountDir, "data-portal.json"), "utf8"));
|
|
37168
37291
|
return Array.isArray(cfg?.exposeFolders) ? cfg.exposeFolders.filter((f) => typeof f === "string") : [];
|
|
37169
37292
|
} catch {
|
|
37170
37293
|
return [];
|
|
@@ -37173,7 +37296,7 @@ async function readExposeFolders2(accountDir) {
|
|
|
37173
37296
|
async function resolveFetchTarget(accountDir, relPath, ownerId) {
|
|
37174
37297
|
let schemaText = null;
|
|
37175
37298
|
try {
|
|
37176
|
-
schemaText = await readFile12(
|
|
37299
|
+
schemaText = await readFile12(join65(accountDir, "SCHEMA.md"), "utf8");
|
|
37177
37300
|
} catch {
|
|
37178
37301
|
schemaText = null;
|
|
37179
37302
|
}
|
|
@@ -37343,8 +37466,8 @@ function startTimeEntryCensus(openSession, opts = {}) {
|
|
|
37343
37466
|
}
|
|
37344
37467
|
|
|
37345
37468
|
// app/lib/ledger-census.ts
|
|
37346
|
-
import { readdirSync as
|
|
37347
|
-
import { join as
|
|
37469
|
+
import { readdirSync as readdirSync32, readFileSync as readFileSync57, statSync as statSync29 } from "fs";
|
|
37470
|
+
import { join as join66 } from "path";
|
|
37348
37471
|
|
|
37349
37472
|
// ../lib/ledger-core/dist/reconcile.js
|
|
37350
37473
|
var LEDGER_INDEX_NAMES = [
|
|
@@ -37392,16 +37515,16 @@ var DAY_MS = 864e5;
|
|
|
37392
37515
|
function countWriteRejects24h(logDir, now) {
|
|
37393
37516
|
let entries2;
|
|
37394
37517
|
try {
|
|
37395
|
-
entries2 =
|
|
37518
|
+
entries2 = readdirSync32(logDir).filter((f) => f.startsWith("mcp-ledger-") && f.endsWith(".log"));
|
|
37396
37519
|
} catch {
|
|
37397
37520
|
return 0;
|
|
37398
37521
|
}
|
|
37399
37522
|
let total = 0;
|
|
37400
37523
|
for (const name of entries2) {
|
|
37401
|
-
const path =
|
|
37524
|
+
const path = join66(logDir, name);
|
|
37402
37525
|
try {
|
|
37403
|
-
if (now -
|
|
37404
|
-
for (const line of
|
|
37526
|
+
if (now - statSync29(path).mtimeMs > DAY_MS) continue;
|
|
37527
|
+
for (const line of readFileSync57(path, "utf8").split("\n")) {
|
|
37405
37528
|
if (line.includes("[graph-write] reject")) total += 1;
|
|
37406
37529
|
}
|
|
37407
37530
|
} catch {
|
|
@@ -37502,8 +37625,8 @@ function startLedgerCensus(openSession, opts = {}) {
|
|
|
37502
37625
|
}
|
|
37503
37626
|
|
|
37504
37627
|
// app/lib/dispatch-census.ts
|
|
37505
|
-
import { readFileSync as
|
|
37506
|
-
import { join as
|
|
37628
|
+
import { readFileSync as readFileSync58 } from "fs";
|
|
37629
|
+
import { join as join67 } from "path";
|
|
37507
37630
|
|
|
37508
37631
|
// ../lib/canonical-instant/src/index.ts
|
|
37509
37632
|
var CANONICAL_INSTANT_PATTERN = "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z";
|
|
@@ -37541,7 +37664,7 @@ function percentile(sortedAsc, p) {
|
|
|
37541
37664
|
function auditConfigFile(accountDir) {
|
|
37542
37665
|
let cfg;
|
|
37543
37666
|
try {
|
|
37544
|
-
cfg = JSON.parse(
|
|
37667
|
+
cfg = JSON.parse(readFileSync58(join67(accountDir, "dispatch", "config.json"), "utf-8"));
|
|
37545
37668
|
} catch {
|
|
37546
37669
|
return null;
|
|
37547
37670
|
}
|
|
@@ -37566,7 +37689,7 @@ function auditConfigFile(accountDir) {
|
|
|
37566
37689
|
function terminalStatuses(accountDir) {
|
|
37567
37690
|
try {
|
|
37568
37691
|
const cfg = JSON.parse(
|
|
37569
|
-
|
|
37692
|
+
readFileSync58(join67(accountDir, "dispatch", "config.json"), "utf-8")
|
|
37570
37693
|
);
|
|
37571
37694
|
return {
|
|
37572
37695
|
job: (cfg.statuses?.job ?? []).filter((s) => s.terminal).map((s) => s.name),
|
|
@@ -37996,8 +38119,8 @@ function startGraphHealthTimer() {
|
|
|
37996
38119
|
}
|
|
37997
38120
|
|
|
37998
38121
|
// app/lib/shared-folder-census.ts
|
|
37999
|
-
import { existsSync as existsSync55, statSync as
|
|
38000
|
-
import { join as
|
|
38122
|
+
import { existsSync as existsSync55, statSync as statSync30, readdirSync as readdirSync33 } from "fs";
|
|
38123
|
+
import { join as join68 } from "path";
|
|
38001
38124
|
var import_dist17 = __toESM(require_dist(), 1);
|
|
38002
38125
|
var TAG69 = "[shared-census]";
|
|
38003
38126
|
var WIRED_SURFACES = 3;
|
|
@@ -38005,12 +38128,12 @@ function countFiles(dir) {
|
|
|
38005
38128
|
let n = 0;
|
|
38006
38129
|
let entries2;
|
|
38007
38130
|
try {
|
|
38008
|
-
entries2 =
|
|
38131
|
+
entries2 = readdirSync33(dir, { withFileTypes: true });
|
|
38009
38132
|
} catch {
|
|
38010
38133
|
return 0;
|
|
38011
38134
|
}
|
|
38012
38135
|
for (const e of entries2) {
|
|
38013
|
-
if (e.isDirectory()) n += countFiles(
|
|
38136
|
+
if (e.isDirectory()) n += countFiles(join68(dir, e.name));
|
|
38014
38137
|
else if (e.isFile()) n++;
|
|
38015
38138
|
}
|
|
38016
38139
|
return n;
|
|
@@ -38021,7 +38144,7 @@ function runSharedFolderCensus(dataRoot = DATA_ROOT) {
|
|
|
38021
38144
|
let isDir = false;
|
|
38022
38145
|
if (exists) {
|
|
38023
38146
|
try {
|
|
38024
|
-
isDir =
|
|
38147
|
+
isDir = statSync30(root).isDirectory();
|
|
38025
38148
|
} catch {
|
|
38026
38149
|
isDir = false;
|
|
38027
38150
|
}
|
|
@@ -38059,9 +38182,9 @@ function startAccountsStateCensus() {
|
|
|
38059
38182
|
}
|
|
38060
38183
|
|
|
38061
38184
|
// app/lib/cred-refresh-census.ts
|
|
38062
|
-
import { readdirSync as
|
|
38185
|
+
import { readdirSync as readdirSync34, readFileSync as readFileSync59 } from "fs";
|
|
38063
38186
|
import { homedir as homedir4 } from "os";
|
|
38064
|
-
import { join as
|
|
38187
|
+
import { join as join69 } from "path";
|
|
38065
38188
|
var TAG71 = "[claude-auth]";
|
|
38066
38189
|
function refreshTokenLength(raw) {
|
|
38067
38190
|
let data;
|
|
@@ -38077,7 +38200,7 @@ function refreshTokenLength(raw) {
|
|
|
38077
38200
|
function surveyBrandCredentials(home) {
|
|
38078
38201
|
let entries2;
|
|
38079
38202
|
try {
|
|
38080
|
-
entries2 =
|
|
38203
|
+
entries2 = readdirSync34(home);
|
|
38081
38204
|
} catch {
|
|
38082
38205
|
return [];
|
|
38083
38206
|
}
|
|
@@ -38086,7 +38209,7 @@ function surveyBrandCredentials(home) {
|
|
|
38086
38209
|
if (!entry3.startsWith(".")) continue;
|
|
38087
38210
|
let raw;
|
|
38088
38211
|
try {
|
|
38089
|
-
raw =
|
|
38212
|
+
raw = readFileSync59(join69(home, entry3, ".claude", ".credentials.json"), "utf-8");
|
|
38090
38213
|
} catch {
|
|
38091
38214
|
continue;
|
|
38092
38215
|
}
|
|
@@ -38348,7 +38471,7 @@ async function migrateUploads(opts = {}) {
|
|
|
38348
38471
|
// app/lib/migrate-admin-webchat-sidecars.ts
|
|
38349
38472
|
import { readdir as readdir7, readFile as readFile13, rename as rename5, writeFile as writeFile4, unlink as unlink4 } from "fs/promises";
|
|
38350
38473
|
import { existsSync as existsSync56 } from "fs";
|
|
38351
|
-
import { join as
|
|
38474
|
+
import { join as join70 } from "path";
|
|
38352
38475
|
var ADMIN_ROLE2 = "admin";
|
|
38353
38476
|
var WEBCHAT_CHANNEL2 = "webchat";
|
|
38354
38477
|
var SESSION_META_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.meta\.json$/i;
|
|
@@ -38393,7 +38516,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
38393
38516
|
}
|
|
38394
38517
|
for (const slug of slugs) {
|
|
38395
38518
|
if (!slug.isDirectory()) continue;
|
|
38396
|
-
const slugDir =
|
|
38519
|
+
const slugDir = join70(projectsRoot, slug.name);
|
|
38397
38520
|
let entries2;
|
|
38398
38521
|
try {
|
|
38399
38522
|
entries2 = await readdir7(slugDir, { withFileTypes: true });
|
|
@@ -38402,9 +38525,9 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
38402
38525
|
}
|
|
38403
38526
|
for (const entry3 of entries2) {
|
|
38404
38527
|
if (entry3.isFile() && SESSION_META_RE.test(entry3.name)) {
|
|
38405
|
-
out.push(
|
|
38528
|
+
out.push(join70(slugDir, entry3.name));
|
|
38406
38529
|
} else if (entry3.isDirectory() && entry3.name === "subagents") {
|
|
38407
|
-
const subDir =
|
|
38530
|
+
const subDir = join70(slugDir, entry3.name);
|
|
38408
38531
|
let subs;
|
|
38409
38532
|
try {
|
|
38410
38533
|
subs = await readdir7(subDir, { withFileTypes: true });
|
|
@@ -38412,7 +38535,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
38412
38535
|
continue;
|
|
38413
38536
|
}
|
|
38414
38537
|
for (const s of subs) {
|
|
38415
|
-
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(
|
|
38538
|
+
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join70(subDir, s.name));
|
|
38416
38539
|
}
|
|
38417
38540
|
}
|
|
38418
38541
|
}
|
|
@@ -38424,7 +38547,7 @@ function shortId(path) {
|
|
|
38424
38547
|
return base.slice(0, 8);
|
|
38425
38548
|
}
|
|
38426
38549
|
async function migrateAdminWebchatSidecars(opts = {}) {
|
|
38427
|
-
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ?
|
|
38550
|
+
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join70(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
|
|
38428
38551
|
const usersFile = opts.usersFile ?? USERS_FILE;
|
|
38429
38552
|
const accountId = opts.accountId ?? resolveAccount()?.accountId ?? null;
|
|
38430
38553
|
const resolveName = opts.resolveName ?? defaultResolveName;
|
|
@@ -38501,7 +38624,7 @@ async function migrateAdminWebchatSidecars(opts = {}) {
|
|
|
38501
38624
|
// app/lib/migrate-sidecar-account-ids.ts
|
|
38502
38625
|
import { readdir as readdir8, readFile as readFile14, rename as rename6, writeFile as writeFile5, unlink as unlink5 } from "fs/promises";
|
|
38503
38626
|
import { existsSync as existsSync57 } from "fs";
|
|
38504
|
-
import { join as
|
|
38627
|
+
import { join as join71 } from "path";
|
|
38505
38628
|
var SESSION_META_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.meta\.json$/i;
|
|
38506
38629
|
function projectSlugForCwd(cwd) {
|
|
38507
38630
|
return cwd.replace(/\//g, "-");
|
|
@@ -38547,7 +38670,7 @@ async function collectSidecars(projectsRoot) {
|
|
|
38547
38670
|
}
|
|
38548
38671
|
for (const slug of slugs) {
|
|
38549
38672
|
if (!slug.isDirectory()) continue;
|
|
38550
|
-
const slugDir =
|
|
38673
|
+
const slugDir = join71(projectsRoot, slug.name);
|
|
38551
38674
|
let entries2;
|
|
38552
38675
|
try {
|
|
38553
38676
|
entries2 = await readdir8(slugDir, { withFileTypes: true });
|
|
@@ -38556,9 +38679,9 @@ async function collectSidecars(projectsRoot) {
|
|
|
38556
38679
|
}
|
|
38557
38680
|
for (const entry3 of entries2) {
|
|
38558
38681
|
if (entry3.isFile() && SESSION_META_RE2.test(entry3.name)) {
|
|
38559
|
-
out.push({ path:
|
|
38682
|
+
out.push({ path: join71(slugDir, entry3.name), slug: slug.name });
|
|
38560
38683
|
} else if (entry3.isDirectory() && (entry3.name === "subagents" || entry3.name === "archive")) {
|
|
38561
|
-
const subDir =
|
|
38684
|
+
const subDir = join71(slugDir, entry3.name);
|
|
38562
38685
|
let subs;
|
|
38563
38686
|
try {
|
|
38564
38687
|
subs = await readdir8(subDir, { withFileTypes: true });
|
|
@@ -38567,7 +38690,7 @@ async function collectSidecars(projectsRoot) {
|
|
|
38567
38690
|
}
|
|
38568
38691
|
for (const s of subs) {
|
|
38569
38692
|
if (s.isFile() && SESSION_META_RE2.test(s.name)) {
|
|
38570
|
-
out.push({ path:
|
|
38693
|
+
out.push({ path: join71(subDir, s.name), slug: slug.name });
|
|
38571
38694
|
}
|
|
38572
38695
|
}
|
|
38573
38696
|
}
|
|
@@ -38576,7 +38699,7 @@ async function collectSidecars(projectsRoot) {
|
|
|
38576
38699
|
return out;
|
|
38577
38700
|
}
|
|
38578
38701
|
async function migrateSidecarAccountIds(opts = {}) {
|
|
38579
|
-
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ?
|
|
38702
|
+
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join71(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
|
|
38580
38703
|
const accounts = opts.accounts ?? listValidAccounts();
|
|
38581
38704
|
const result = {
|
|
38582
38705
|
scanned: 0,
|
|
@@ -40199,8 +40322,8 @@ function createWebchatChannelRoutes(deps) {
|
|
|
40199
40322
|
}
|
|
40200
40323
|
|
|
40201
40324
|
// app/lib/webchat/gateway/resolve-turn-answer.ts
|
|
40202
|
-
import { existsSync as existsSync58, openSync as
|
|
40203
|
-
import { join as
|
|
40325
|
+
import { existsSync as existsSync58, openSync as openSync10, readSync as readSync9, closeSync as closeSync10, readdirSync as readdirSync35 } from "fs";
|
|
40326
|
+
import { join as join72 } from "path";
|
|
40204
40327
|
|
|
40205
40328
|
// app/lib/channel-delivery/outbound-guard.ts
|
|
40206
40329
|
var INTERNAL_LEAK_PATTERNS = [
|
|
@@ -40242,13 +40365,13 @@ function resolveTurnAnswer(p) {
|
|
|
40242
40365
|
if (!(length > 0)) return "";
|
|
40243
40366
|
let text;
|
|
40244
40367
|
try {
|
|
40245
|
-
const fd =
|
|
40368
|
+
const fd = openSync10(path, "r");
|
|
40246
40369
|
try {
|
|
40247
40370
|
const buf = Buffer.alloc(length);
|
|
40248
|
-
|
|
40371
|
+
readSync9(fd, buf, 0, length, p.segmentStart);
|
|
40249
40372
|
text = buf.toString("utf8");
|
|
40250
40373
|
} finally {
|
|
40251
|
-
|
|
40374
|
+
closeSync10(fd);
|
|
40252
40375
|
}
|
|
40253
40376
|
} catch {
|
|
40254
40377
|
return "";
|
|
@@ -40264,12 +40387,12 @@ function findJsonl(projectsRoot, sessionId) {
|
|
|
40264
40387
|
if (!existsSync58(projectsRoot)) return null;
|
|
40265
40388
|
let slugs;
|
|
40266
40389
|
try {
|
|
40267
|
-
slugs =
|
|
40390
|
+
slugs = readdirSync35(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
40268
40391
|
} catch {
|
|
40269
40392
|
return null;
|
|
40270
40393
|
}
|
|
40271
40394
|
for (const slug of slugs) {
|
|
40272
|
-
const live =
|
|
40395
|
+
const live = join72(projectsRoot, slug, `${sessionId}.jsonl`);
|
|
40273
40396
|
if (existsSync58(live)) return live;
|
|
40274
40397
|
}
|
|
40275
40398
|
return null;
|
|
@@ -41651,21 +41774,21 @@ function refusalNoticeText(reason) {
|
|
|
41651
41774
|
}
|
|
41652
41775
|
async function sendRefusalNotice(input) {
|
|
41653
41776
|
if (notified.has(input.doorId)) return;
|
|
41654
|
-
const
|
|
41777
|
+
const fields2 = `channel=${input.channel} sender=${input.sender} reason=${input.reason}`;
|
|
41655
41778
|
if (!input.send) {
|
|
41656
|
-
console.error(`${TAG74} op=refusal-notice-failed ${
|
|
41779
|
+
console.error(`${TAG74} op=refusal-notice-failed ${fields2} error=no-target`);
|
|
41657
41780
|
return;
|
|
41658
41781
|
}
|
|
41659
41782
|
try {
|
|
41660
41783
|
await input.send(guardOutbound(input.sender, refusalNoticeText(input.reason)));
|
|
41661
41784
|
} catch (e) {
|
|
41662
41785
|
console.error(
|
|
41663
|
-
`${TAG74} op=refusal-notice-failed ${
|
|
41786
|
+
`${TAG74} op=refusal-notice-failed ${fields2} error=${e instanceof Error ? e.message : String(e)}`
|
|
41664
41787
|
);
|
|
41665
41788
|
return;
|
|
41666
41789
|
}
|
|
41667
41790
|
notified.add(input.doorId);
|
|
41668
|
-
console.error(`${TAG74} op=refusal-notice ${
|
|
41791
|
+
console.error(`${TAG74} op=refusal-notice ${fields2} status=${input.status}`);
|
|
41669
41792
|
}
|
|
41670
41793
|
function clearRefusalNotice(doorId) {
|
|
41671
41794
|
notified.delete(doorId);
|
|
@@ -42672,7 +42795,7 @@ var sessions3 = /* @__PURE__ */ new Map();
|
|
|
42672
42795
|
function entry2(sessionId) {
|
|
42673
42796
|
let e = sessions3.get(sessionId);
|
|
42674
42797
|
if (!e) {
|
|
42675
|
-
e = { armed: 0, suppressed: 0, delivered: 0
|
|
42798
|
+
e = { armed: 0, suppressed: 0, delivered: 0 };
|
|
42676
42799
|
sessions3.set(sessionId, e);
|
|
42677
42800
|
}
|
|
42678
42801
|
return e;
|
|
@@ -42687,59 +42810,23 @@ function noteCardDelivered(sessionId) {
|
|
|
42687
42810
|
const e = sessions3.get(sessionId);
|
|
42688
42811
|
if (e && e.armed > 0) e.delivered += 1;
|
|
42689
42812
|
}
|
|
42690
|
-
function noteCardPersisted(sessionId) {
|
|
42691
|
-
entry2(sessionId).persisted += 1;
|
|
42692
|
-
}
|
|
42693
|
-
function noteCardSent(sessionId) {
|
|
42694
|
-
entry2(sessionId).sent += 1;
|
|
42695
|
-
}
|
|
42696
|
-
function noteCardCrossChat(sessionId) {
|
|
42697
|
-
entry2(sessionId).crossChat += 1;
|
|
42698
|
-
}
|
|
42699
42813
|
function cardCensusLines() {
|
|
42700
42814
|
let armed3 = 0;
|
|
42701
42815
|
let suppressed = 0;
|
|
42702
42816
|
let delivered = 0;
|
|
42703
|
-
let persisted = 0;
|
|
42704
|
-
let sent = 0;
|
|
42705
|
-
let crossChat = 0;
|
|
42706
42817
|
for (const e of sessions3.values()) {
|
|
42707
42818
|
armed3 += e.armed;
|
|
42708
42819
|
suppressed += e.suppressed;
|
|
42709
42820
|
delivered += e.delivered;
|
|
42710
|
-
persisted += e.persisted;
|
|
42711
|
-
sent += e.sent;
|
|
42712
|
-
crossChat += e.crossChat;
|
|
42713
42821
|
}
|
|
42714
42822
|
const silent = Math.max(0, armed3 - suppressed - delivered);
|
|
42715
42823
|
return [
|
|
42716
|
-
`[telegram-card-suppression-census] sessions=${sessions3.size} armed=${armed3} suppressed=${suppressed} silent-turns=${silent}
|
|
42824
|
+
`[telegram-card-suppression-census] sessions=${sessions3.size} armed=${armed3} suppressed=${suppressed} silent-turns=${silent}`
|
|
42717
42825
|
];
|
|
42718
42826
|
}
|
|
42719
42827
|
|
|
42720
42828
|
// app/lib/telegram/gateway/native-file-follower.ts
|
|
42721
42829
|
var TELEGRAM_CARD_TOOL = "mcp__telegram__telegram-card";
|
|
42722
|
-
var CARD_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
42723
|
-
"mcp__telegram__telegram-card",
|
|
42724
|
-
"mcp__plugin_telegram_telegram__telegram-card"
|
|
42725
|
-
]);
|
|
42726
|
-
var CARD_RESULT_RE = /card-result: outcome=(sent|edited|unchanged|none) messageId=(\d+|none)(?: botId=(-?\d+) chatId=(-?\d+))?/;
|
|
42727
|
-
function parseCardButtons(input) {
|
|
42728
|
-
const rows = input?.buttons;
|
|
42729
|
-
if (!Array.isArray(rows)) return [];
|
|
42730
|
-
const out = [];
|
|
42731
|
-
for (const row of rows) {
|
|
42732
|
-
if (!Array.isArray(row)) continue;
|
|
42733
|
-
for (const b of row) {
|
|
42734
|
-
if (!b || typeof b !== "object") continue;
|
|
42735
|
-
const text = b.text;
|
|
42736
|
-
if (typeof text !== "string") continue;
|
|
42737
|
-
const data = b.callbackData;
|
|
42738
|
-
out.push({ text, data: typeof data === "string" ? data : null });
|
|
42739
|
-
}
|
|
42740
|
-
}
|
|
42741
|
-
return out;
|
|
42742
|
-
}
|
|
42743
42830
|
var CHAT_ACTION_REFRESH_MS = 4e3;
|
|
42744
42831
|
function startTelegramNativeFileFollower(input) {
|
|
42745
42832
|
const entry3 = {
|
|
@@ -42760,9 +42847,7 @@ function startTelegramNativeFileFollower(input) {
|
|
|
42760
42847
|
// The chat id the document is addressed to (set per spawn from the inbound).
|
|
42761
42848
|
replyTarget: input.chatId
|
|
42762
42849
|
};
|
|
42763
|
-
const pendingCards = /* @__PURE__ */ new Map();
|
|
42764
42850
|
const channelKey = input.senderId;
|
|
42765
|
-
const numericSenderId = parseTelegramChannelKey(channelKey)?.senderId ?? input.chatId;
|
|
42766
42851
|
let lastChatActionAt = Number.NEGATIVE_INFINITY;
|
|
42767
42852
|
let turnOpen = false;
|
|
42768
42853
|
let cardSentThisTurn = false;
|
|
@@ -42851,13 +42936,6 @@ function startTelegramNativeFileFollower(input) {
|
|
|
42851
42936
|
// before it reaches the optional answerCallbackQuery, so there is no card
|
|
42852
42937
|
// call that posts nothing and no bare acknowledgement to keep the text for.
|
|
42853
42938
|
onToolUse: (tool) => {
|
|
42854
|
-
if (CARD_TOOL_NAMES.has(tool.name) && tool.id) {
|
|
42855
|
-
const text = tool.input?.text;
|
|
42856
|
-
pendingCards.set(tool.id, {
|
|
42857
|
-
text: typeof text === "string" ? text : "",
|
|
42858
|
-
buttons: parseCardButtons(tool.input)
|
|
42859
|
-
});
|
|
42860
|
-
}
|
|
42861
42939
|
if (tool.name !== TELEGRAM_CARD_TOOL) return;
|
|
42862
42940
|
cardSentThisTurn = true;
|
|
42863
42941
|
noteCardArmed(input.sessionId);
|
|
@@ -42865,75 +42943,6 @@ function startTelegramNativeFileFollower(input) {
|
|
|
42865
42943
|
`[telegram-public] op=card-armed sessionId=${input.sessionId.slice(0, 8)} tool=${tool.name}`
|
|
42866
42944
|
);
|
|
42867
42945
|
},
|
|
42868
|
-
// Task 2677 — the card's send outcome and message id arrive here, parsed out
|
|
42869
|
-
// of the result text card.ts encoded them into. On a confirmed send write one
|
|
42870
|
-
// outbound store row keyed by the card message id; on an edit patch that same
|
|
42871
|
-
// row (Telegram reuses the id for an edit); unchanged/none write nothing.
|
|
42872
|
-
onToolResult: ({ toolUseId, text }) => {
|
|
42873
|
-
const pending = pendingCards.get(toolUseId);
|
|
42874
|
-
if (!pending) return;
|
|
42875
|
-
pendingCards.delete(toolUseId);
|
|
42876
|
-
const m = CARD_RESULT_RE.exec(text);
|
|
42877
|
-
if (!m) return;
|
|
42878
|
-
const outcome = m[1];
|
|
42879
|
-
const messageId = m[2];
|
|
42880
|
-
if (outcome !== "sent" && outcome !== "edited" || messageId === "none") return;
|
|
42881
|
-
noteCardSent(input.sessionId);
|
|
42882
|
-
const destBot = m[3];
|
|
42883
|
-
const destChat = m[4];
|
|
42884
|
-
const follower = parseTelegramChannelKey(channelKey);
|
|
42885
|
-
let destKey = channelKey;
|
|
42886
|
-
let rowChat = input.chatId;
|
|
42887
|
-
let rowSender = numericSenderId;
|
|
42888
|
-
if (destBot === void 0 || destChat === void 0) {
|
|
42889
|
-
console.error(
|
|
42890
|
-
`[telegram-adaptor] op=card-destination-absent sessionId=${input.sessionId.slice(0, 8)} toolUseId=${toolUseId} follower=${channelKey}`
|
|
42891
|
-
);
|
|
42892
|
-
} else if (follower?.business === true && follower.botId === destBot && follower.senderId === destChat) {
|
|
42893
|
-
rowChat = destChat;
|
|
42894
|
-
rowSender = destChat;
|
|
42895
|
-
} else {
|
|
42896
|
-
destKey = `${destBot}:${destChat}`;
|
|
42897
|
-
rowChat = destChat;
|
|
42898
|
-
rowSender = destChat;
|
|
42899
|
-
}
|
|
42900
|
-
if (destKey !== channelKey) noteCardCrossChat(input.sessionId);
|
|
42901
|
-
const at = (/* @__PURE__ */ new Date()).toISOString();
|
|
42902
|
-
const rowId = `telegram:${input.accountId}:${destKey}:card:${messageId}`;
|
|
42903
|
-
let created;
|
|
42904
|
-
if (outcome === "sent") {
|
|
42905
|
-
created = appendMessage2(input.accountId, {
|
|
42906
|
-
messageId: rowId,
|
|
42907
|
-
sessionId: input.sessionId,
|
|
42908
|
-
dateSent: at,
|
|
42909
|
-
body: pending.text,
|
|
42910
|
-
fromMe: true,
|
|
42911
|
-
senderId: rowSender,
|
|
42912
|
-
senderName: null,
|
|
42913
|
-
chatId: rowChat,
|
|
42914
|
-
channelKey: destKey,
|
|
42915
|
-
// Telegram row scope is not consumed for rendering or routing (only
|
|
42916
|
-
// WhatsApp rows feed the operator-conversations scope counter); 'admin'
|
|
42917
|
-
// matches the operator-surface intent of the card row.
|
|
42918
|
-
scope: "admin",
|
|
42919
|
-
origin: "agent",
|
|
42920
|
-
...pending.buttons.length > 0 ? { buttons: pending.buttons } : {},
|
|
42921
|
-
createdAt: at
|
|
42922
|
-
}).created;
|
|
42923
|
-
} else {
|
|
42924
|
-
created = appendUpdate(input.accountId, destKey, {
|
|
42925
|
-
kind: "update",
|
|
42926
|
-
targetMessageId: rowId,
|
|
42927
|
-
body: pending.text,
|
|
42928
|
-
...pending.buttons.length > 0 ? { buttons: pending.buttons } : {},
|
|
42929
|
-
createdAt: at
|
|
42930
|
-
}).created;
|
|
42931
|
-
}
|
|
42932
|
-
if (created) noteCardPersisted(input.sessionId);
|
|
42933
|
-
console.error(
|
|
42934
|
-
`[telegram-adaptor] op=${created ? "card-persisted" : "card-persist-refused"} sessionId=${input.sessionId.slice(0, 8)} messageId=${messageId} outcome=${outcome} buttons=${pending.buttons.length} channelKey=${destKey} follower=${channelKey}`
|
|
42935
|
-
);
|
|
42936
|
-
},
|
|
42937
42946
|
// Task 2521 — the answer reaches every bound door through the one fan-out.
|
|
42938
42947
|
// Ungated by design: whatever woke the turn, the reader and the chats show
|
|
42939
42948
|
// the same thing. Task 2666 adds the one exception above.
|
|
@@ -42973,15 +42982,15 @@ function startTelegramNativeFileFollower(input) {
|
|
|
42973
42982
|
}
|
|
42974
42983
|
|
|
42975
42984
|
// server/telegram-background-active.ts
|
|
42976
|
-
import { join as
|
|
42977
|
-
import { readdirSync as
|
|
42985
|
+
import { join as join73, resolve as resolve52 } from "path";
|
|
42986
|
+
import { readdirSync as readdirSync36, statSync as statSync31 } from "fs";
|
|
42978
42987
|
var SUBAGENT_STALE_WINDOW_MS = 6e4;
|
|
42979
42988
|
var AGENT_JSONL_RE2 = /^agent-([0-9a-f]+)\.jsonl$/;
|
|
42980
42989
|
function makeBackgroundActive(sessionId, deps = {}) {
|
|
42981
42990
|
const findProjectDir = deps.findProjectDir ?? findSessionProjectDir;
|
|
42982
|
-
const readDir = deps.readDir ?? ((d) =>
|
|
42991
|
+
const readDir = deps.readDir ?? ((d) => readdirSync36(d));
|
|
42983
42992
|
const statFile = deps.statFile ?? ((p) => {
|
|
42984
|
-
const st =
|
|
42993
|
+
const st = statSync31(p);
|
|
42985
42994
|
return { size: st.size, mtimeMs: st.mtimeMs };
|
|
42986
42995
|
});
|
|
42987
42996
|
const now = deps.now ?? (() => Date.now());
|
|
@@ -42992,7 +43001,7 @@ function makeBackgroundActive(sessionId, deps = {}) {
|
|
|
42992
43001
|
if (subagentsDir === null) {
|
|
42993
43002
|
const projectDir = findProjectDir(sessionId);
|
|
42994
43003
|
if (projectDir === null) return false;
|
|
42995
|
-
subagentsDir = resolve52(
|
|
43004
|
+
subagentsDir = resolve52(join73(projectDir, sessionId, "subagents"));
|
|
42996
43005
|
}
|
|
42997
43006
|
let names;
|
|
42998
43007
|
try {
|
|
@@ -43006,7 +43015,7 @@ function makeBackgroundActive(sessionId, deps = {}) {
|
|
|
43006
43015
|
let size;
|
|
43007
43016
|
let mtimeMs;
|
|
43008
43017
|
try {
|
|
43009
|
-
const st = statFile(
|
|
43018
|
+
const st = statFile(join73(subagentsDir, name));
|
|
43010
43019
|
size = st.size;
|
|
43011
43020
|
mtimeMs = st.mtimeMs;
|
|
43012
43021
|
} catch {
|
|
@@ -43326,9 +43335,9 @@ function warnOnChannelAdminBindingDrift() {
|
|
|
43326
43335
|
);
|
|
43327
43336
|
}
|
|
43328
43337
|
for (const d of drift) {
|
|
43329
|
-
const
|
|
43338
|
+
const tail2 = d.reason === "userid-not-admin" ? ` userId=${d.userId}` : "";
|
|
43330
43339
|
console.error(
|
|
43331
|
-
`[admin-identity] binding-drift accountId=${acct.accountId} phone=${d.phone} reason=${d.reason}${
|
|
43340
|
+
`[admin-identity] binding-drift accountId=${acct.accountId} phone=${d.phone} reason=${d.reason}${tail2}`
|
|
43332
43341
|
);
|
|
43333
43342
|
}
|
|
43334
43343
|
const managerDrift = findAccountManagerDrift(readAccountManagers(acct.accountDir), validAccountIds);
|
|
@@ -43372,8 +43381,8 @@ function runPublicAddressCollisionAudit(deps) {
|
|
|
43372
43381
|
}
|
|
43373
43382
|
|
|
43374
43383
|
// server/telegram-audit.ts
|
|
43375
|
-
import { statSync as
|
|
43376
|
-
import { join as
|
|
43384
|
+
import { statSync as statSync32 } from "fs";
|
|
43385
|
+
import { join as join74 } from "path";
|
|
43377
43386
|
function buildTelegramAuditLines(input) {
|
|
43378
43387
|
const lines = [];
|
|
43379
43388
|
const entries2 = input.accounts.flatMap(
|
|
@@ -43481,19 +43490,19 @@ function countTelegramSessionsForAccount(accountId) {
|
|
|
43481
43490
|
function* walkTelegramSidecars() {
|
|
43482
43491
|
const cfg = claudeConfigDir();
|
|
43483
43492
|
if (!cfg) return;
|
|
43484
|
-
const projectsRoot =
|
|
43493
|
+
const projectsRoot = join74(cfg, "projects");
|
|
43485
43494
|
for (const { path } of enumerateSessionSidecars(projectsRoot)) {
|
|
43486
43495
|
const meta = readSidecarMeta(path);
|
|
43487
43496
|
if (meta.channel !== "telegram" || !meta.accountId) continue;
|
|
43488
43497
|
let spawnMs;
|
|
43489
43498
|
try {
|
|
43490
|
-
spawnMs =
|
|
43499
|
+
spawnMs = statSync32(path).mtimeMs;
|
|
43491
43500
|
} catch {
|
|
43492
43501
|
continue;
|
|
43493
43502
|
}
|
|
43494
43503
|
let turnMs;
|
|
43495
43504
|
try {
|
|
43496
|
-
turnMs =
|
|
43505
|
+
turnMs = statSync32(path.replace(/\.meta\.json$/, ".jsonl")).mtimeMs;
|
|
43497
43506
|
} catch {
|
|
43498
43507
|
turnMs = null;
|
|
43499
43508
|
}
|
|
@@ -43693,8 +43702,8 @@ function businessConnectionCensusLine(c) {
|
|
|
43693
43702
|
}
|
|
43694
43703
|
|
|
43695
43704
|
// app/lib/telegram/business-window-census.ts
|
|
43696
|
-
import { readdirSync as
|
|
43697
|
-
import { join as
|
|
43705
|
+
import { readdirSync as readdirSync37, existsSync as existsSync59 } from "fs";
|
|
43706
|
+
import { join as join75 } from "path";
|
|
43698
43707
|
var BUSINESS_WINDOW_CENSUS_TAG = "[telegram-audit]";
|
|
43699
43708
|
var EXPIRING_SOON_S = 3600;
|
|
43700
43709
|
function collectBusinessWindowCensus(input) {
|
|
@@ -43722,11 +43731,11 @@ function businessWindowCensusLine(c) {
|
|
|
43722
43731
|
function readBusinessChatClocks(accountIds) {
|
|
43723
43732
|
const out = [];
|
|
43724
43733
|
for (const accountId of accountIds) {
|
|
43725
|
-
const dir =
|
|
43734
|
+
const dir = join75(STORE_ROOT2(), accountId);
|
|
43726
43735
|
if (!existsSync59(dir)) continue;
|
|
43727
43736
|
let names;
|
|
43728
43737
|
try {
|
|
43729
|
-
names =
|
|
43738
|
+
names = readdirSync37(dir);
|
|
43730
43739
|
} catch {
|
|
43731
43740
|
continue;
|
|
43732
43741
|
}
|
|
@@ -43784,15 +43793,15 @@ async function getTelegramBusinessConnection(botToken, connectionId, opts = {})
|
|
|
43784
43793
|
}
|
|
43785
43794
|
|
|
43786
43795
|
// server/telegram-migrate.ts
|
|
43787
|
-
import { readFileSync as
|
|
43788
|
-
import { dirname as dirname19, join as
|
|
43796
|
+
import { readFileSync as readFileSync60, writeFileSync as writeFileSync23, existsSync as existsSync60, renameSync as renameSync11, mkdirSync as mkdirSync14 } from "fs";
|
|
43797
|
+
import { dirname as dirname19, join as join76 } from "path";
|
|
43789
43798
|
function migrateTelegramTwoSlot(input) {
|
|
43790
43799
|
const out = [];
|
|
43791
43800
|
for (const account of input.accounts) {
|
|
43792
|
-
const configPath3 =
|
|
43801
|
+
const configPath3 = join76(account.accountDir, "account.json");
|
|
43793
43802
|
let config;
|
|
43794
43803
|
try {
|
|
43795
|
-
config = JSON.parse(
|
|
43804
|
+
config = JSON.parse(readFileSync60(configPath3, "utf-8"));
|
|
43796
43805
|
} catch {
|
|
43797
43806
|
console.error(`[telegram-audit] op=migrate-unreadable accountId=${account.accountId}`);
|
|
43798
43807
|
continue;
|
|
@@ -43851,16 +43860,16 @@ function moveSecret(from, to) {
|
|
|
43851
43860
|
}
|
|
43852
43861
|
|
|
43853
43862
|
// server/telegram-unadopt.ts
|
|
43854
|
-
import { readFileSync as
|
|
43855
|
-
import { join as
|
|
43863
|
+
import { readFileSync as readFileSync61, writeFileSync as writeFileSync24, renameSync as renameSync12 } from "fs";
|
|
43864
|
+
import { join as join77 } from "path";
|
|
43856
43865
|
var FILE3 = "channel-session-override.json";
|
|
43857
43866
|
function unadoptTelegramPointers(input) {
|
|
43858
43867
|
return input.accounts.map(({ accountId, accountDir }) => {
|
|
43859
43868
|
const out = { accountId, dropped: [], kept: 0, unknown: 0 };
|
|
43860
|
-
const path =
|
|
43869
|
+
const path = join77(accountDir, FILE3);
|
|
43861
43870
|
const bySender = {};
|
|
43862
43871
|
try {
|
|
43863
|
-
const raw = JSON.parse(
|
|
43872
|
+
const raw = JSON.parse(readFileSync61(path, "utf8"));
|
|
43864
43873
|
if (!raw.bySender || typeof raw.bySender !== "object") return out;
|
|
43865
43874
|
for (const [k, v] of Object.entries(raw.bySender)) if (typeof v === "string") bySender[k] = v;
|
|
43866
43875
|
} catch {
|
|
@@ -43931,14 +43940,14 @@ function backfillMisfiledRecords(params) {
|
|
|
43931
43940
|
}
|
|
43932
43941
|
|
|
43933
43942
|
// server/lib/booking-site-accounts.ts
|
|
43934
|
-
import { existsSync as existsSync61, readFileSync as
|
|
43943
|
+
import { existsSync as existsSync61, readFileSync as readFileSync62 } from "fs";
|
|
43935
43944
|
import { resolve as resolve53 } from "path";
|
|
43936
43945
|
function listBookingSiteAccounts(accounts) {
|
|
43937
43946
|
return accounts.filter((a) => {
|
|
43938
43947
|
const availPath = resolve53(a.accountDir, "calendar-availability.json");
|
|
43939
43948
|
if (!existsSync61(availPath)) return false;
|
|
43940
43949
|
try {
|
|
43941
|
-
const cfg = JSON.parse(
|
|
43950
|
+
const cfg = JSON.parse(readFileSync62(availPath, "utf-8"));
|
|
43942
43951
|
return typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
43943
43952
|
} catch {
|
|
43944
43953
|
return false;
|
|
@@ -43976,7 +43985,7 @@ function broadcastAdminShutdown(reason) {
|
|
|
43976
43985
|
|
|
43977
43986
|
// ../lib/entitlement/src/index.ts
|
|
43978
43987
|
import { createPublicKey, createHash as createHash7, verify as cryptoVerify } from "crypto";
|
|
43979
|
-
import { existsSync as existsSync62, readFileSync as
|
|
43988
|
+
import { existsSync as existsSync62, readFileSync as readFileSync63, statSync as statSync33 } from "fs";
|
|
43980
43989
|
import { resolve as resolve54 } from "path";
|
|
43981
43990
|
|
|
43982
43991
|
// ../lib/entitlement/src/canonicalize.ts
|
|
@@ -44028,7 +44037,7 @@ function resolveEntitlement(brand, account) {
|
|
|
44028
44037
|
if (!existsSync62(entitlementPath)) {
|
|
44029
44038
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
44030
44039
|
}
|
|
44031
|
-
const stat11 =
|
|
44040
|
+
const stat11 = statSync33(entitlementPath);
|
|
44032
44041
|
const key2 = memoKey(stat11.mtimeMs, account);
|
|
44033
44042
|
if (memo && memo.key === key2) {
|
|
44034
44043
|
return memo.result;
|
|
@@ -44040,7 +44049,7 @@ function resolveEntitlement(brand, account) {
|
|
|
44040
44049
|
function verifyAndResolve(brand, entitlementPath, account) {
|
|
44041
44050
|
let pubkeyPem;
|
|
44042
44051
|
try {
|
|
44043
|
-
pubkeyPem =
|
|
44052
|
+
pubkeyPem = readFileSync63(pubkeyPath(brand), "utf-8");
|
|
44044
44053
|
} catch (err) {
|
|
44045
44054
|
return logResolved(anonymousFallback("pubkey-missing"), {
|
|
44046
44055
|
reason: "pubkey-missing"
|
|
@@ -44054,7 +44063,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
|
|
|
44054
44063
|
}
|
|
44055
44064
|
let envelope;
|
|
44056
44065
|
try {
|
|
44057
|
-
envelope = JSON.parse(
|
|
44066
|
+
envelope = JSON.parse(readFileSync63(entitlementPath, "utf-8"));
|
|
44058
44067
|
} catch {
|
|
44059
44068
|
return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
|
|
44060
44069
|
}
|
|
@@ -44216,14 +44225,14 @@ function clientFrom(c) {
|
|
|
44216
44225
|
}
|
|
44217
44226
|
installMediaDownloadGuard();
|
|
44218
44227
|
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
44219
|
-
var BRAND_JSON_PATH = PLATFORM_ROOT6 ?
|
|
44228
|
+
var BRAND_JSON_PATH = PLATFORM_ROOT6 ? join78(PLATFORM_ROOT6, "config", "brand.json") : "";
|
|
44220
44229
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
44221
44230
|
if (BRAND_JSON_PATH && !existsSync63(BRAND_JSON_PATH)) {
|
|
44222
44231
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
44223
44232
|
}
|
|
44224
44233
|
if (BRAND_JSON_PATH && existsSync63(BRAND_JSON_PATH)) {
|
|
44225
44234
|
try {
|
|
44226
|
-
const parsed = JSON.parse(
|
|
44235
|
+
const parsed = JSON.parse(readFileSync64(BRAND_JSON_PATH, "utf-8"));
|
|
44227
44236
|
BRAND = { ...BRAND, ...parsed };
|
|
44228
44237
|
} catch (err) {
|
|
44229
44238
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -44255,11 +44264,11 @@ var brandLoginOpts = {
|
|
|
44255
44264
|
appleTouchIconPath: brandAppIcon512Path,
|
|
44256
44265
|
themeColor: BRAND.defaultColors?.primary
|
|
44257
44266
|
};
|
|
44258
|
-
var ALIAS_DOMAINS_PATH =
|
|
44267
|
+
var ALIAS_DOMAINS_PATH = join78(homedir5(), BRAND.configDir, "alias-domains.json");
|
|
44259
44268
|
function loadAliasDomains() {
|
|
44260
44269
|
try {
|
|
44261
44270
|
if (!existsSync63(ALIAS_DOMAINS_PATH)) return null;
|
|
44262
|
-
const parsed = JSON.parse(
|
|
44271
|
+
const parsed = JSON.parse(readFileSync64(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
44263
44272
|
if (!Array.isArray(parsed)) {
|
|
44264
44273
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
44265
44274
|
return null;
|
|
@@ -44401,7 +44410,7 @@ var waGateway = new WaGateway({
|
|
|
44401
44410
|
// resolver and `fanTargetsFor` is a constructor dep, not a callable method.
|
|
44402
44411
|
fanTargetsFor: whatsappFanTargets,
|
|
44403
44412
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
44404
|
-
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve55(process.env.MAXY_PLATFORM_ROOT ??
|
|
44413
|
+
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve55(process.env.MAXY_PLATFORM_ROOT ?? join78(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
44405
44414
|
// Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
|
|
44406
44415
|
// path-validation scope) is the sender's effective SESSION account, resolved
|
|
44407
44416
|
// once at the inbound gate and threaded here via the gateway's per-sender doc
|
|
@@ -44416,7 +44425,7 @@ var waGateway = new WaGateway({
|
|
|
44416
44425
|
caption,
|
|
44417
44426
|
accountId,
|
|
44418
44427
|
maxyAccountId,
|
|
44419
|
-
platformRoot: resolve55(process.env.MAXY_PLATFORM_ROOT ??
|
|
44428
|
+
platformRoot: resolve55(process.env.MAXY_PLATFORM_ROOT ?? join78(__dirname, ".."))
|
|
44420
44429
|
});
|
|
44421
44430
|
return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
|
|
44422
44431
|
},
|
|
@@ -44591,7 +44600,7 @@ function runDuplicateSenderAudit() {
|
|
|
44591
44600
|
try {
|
|
44592
44601
|
const configDir = process.env.CLAUDE_CONFIG_DIR;
|
|
44593
44602
|
if (!configDir) return;
|
|
44594
|
-
const projectsRoot =
|
|
44603
|
+
const projectsRoot = join78(configDir, "projects");
|
|
44595
44604
|
const records5 = [];
|
|
44596
44605
|
for (const { path: jsonlPath, isSubagent, archived } of enumerateJsonls(projectsRoot)) {
|
|
44597
44606
|
if (isSubagent || archived) continue;
|
|
@@ -44643,7 +44652,7 @@ var webchatGateway = new WebchatGateway({
|
|
|
44643
44652
|
// rather than hanging the POST.
|
|
44644
44653
|
publicProjectsRoot: () => {
|
|
44645
44654
|
const cfg = claudeConfigDir();
|
|
44646
|
-
return cfg ?
|
|
44655
|
+
return cfg ? join78(cfg, "projects") : "";
|
|
44647
44656
|
},
|
|
44648
44657
|
gatewayUrl: webchatGatewayUrl(),
|
|
44649
44658
|
serverPath: webchatServerPath(),
|
|
@@ -44913,6 +44922,32 @@ var scheduleInjectRoutes = createScheduleInjectRoutes({
|
|
|
44913
44922
|
if (hits.length === 0) return { kind: "none" };
|
|
44914
44923
|
if (hits.length > 1) return { kind: "ambiguous", claimants: hits };
|
|
44915
44924
|
return { kind: "one", ...hits[0] };
|
|
44925
|
+
},
|
|
44926
|
+
// Task 2776 — the carrier a routine NAMED, resolved against that account's own
|
|
44927
|
+
// bots and never install-wide. The verdict comes from `carrierVerdict`, the
|
|
44928
|
+
// same function `validateAgentDispatch` calls at write time, so a bot that
|
|
44929
|
+
// saved cannot be refused here for a reason the save would not have given.
|
|
44930
|
+
//
|
|
44931
|
+
// The token and allowlists are read off the entry this lookup just chose, for
|
|
44932
|
+
// the reason the resolver above states about its own: a second read of the
|
|
44933
|
+
// registry could disagree with the entry chosen.
|
|
44934
|
+
//
|
|
44935
|
+
// `absent` covers the two ways an entry can be missing — no such account, and
|
|
44936
|
+
// no such bot on it — because both mean the same thing to the operator: the id
|
|
44937
|
+
// this routine names is not a bot they can dispatch on.
|
|
44938
|
+
carrierFor: (accountId, botId, destination) => {
|
|
44939
|
+
const account = listValidAccounts().find((a) => a.accountId === accountId);
|
|
44940
|
+
if (!account) return { error: "absent" };
|
|
44941
|
+
const verdict = carrierVerdict(account.accountDir, botId, destination);
|
|
44942
|
+
if (!verdict.ok) return { error: verdict.reason };
|
|
44943
|
+
const entry3 = listBotEntries(account.config.telegram).find((e) => e.id === botId);
|
|
44944
|
+
if (!entry3) return { error: "absent" };
|
|
44945
|
+
return {
|
|
44946
|
+
accountId: account.accountId,
|
|
44947
|
+
botId,
|
|
44948
|
+
botToken: entry3.token,
|
|
44949
|
+
...chatSendAllowlists(entry3)
|
|
44950
|
+
};
|
|
44916
44951
|
}
|
|
44917
44952
|
// Task 2078 — the same binding the live inbound resolves. Without it a
|
|
44918
44953
|
// scheduled dispatch to a BOUND admin would derive the legacy per-chat id and
|
|
@@ -45317,7 +45352,7 @@ app80.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
45317
45352
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
45318
45353
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
45319
45354
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
45320
|
-
const body =
|
|
45355
|
+
const body = readFileSync64(filePath);
|
|
45321
45356
|
return c.body(body, 200, {
|
|
45322
45357
|
"Content-Type": contentType,
|
|
45323
45358
|
"Cache-Control": "public, max-age=3600"
|
|
@@ -45347,7 +45382,7 @@ app80.get("/generated/:filename", (c) => {
|
|
|
45347
45382
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
45348
45383
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
45349
45384
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
45350
|
-
const body =
|
|
45385
|
+
const body = readFileSync64(filePath);
|
|
45351
45386
|
return c.body(body, 200, {
|
|
45352
45387
|
"Content-Type": contentType,
|
|
45353
45388
|
"Cache-Control": "public, max-age=86400"
|
|
@@ -45362,7 +45397,7 @@ var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
|
45362
45397
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
45363
45398
|
if (BRAND_JSON_PATH && existsSync63(BRAND_JSON_PATH)) {
|
|
45364
45399
|
try {
|
|
45365
|
-
const fullBrand = JSON.parse(
|
|
45400
|
+
const fullBrand = JSON.parse(readFileSync64(BRAND_JSON_PATH, "utf-8"));
|
|
45366
45401
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
45367
45402
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
45368
45403
|
} catch {
|
|
@@ -45393,7 +45428,7 @@ var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskabl
|
|
|
45393
45428
|
);
|
|
45394
45429
|
var SW_SOURCE = (() => {
|
|
45395
45430
|
try {
|
|
45396
|
-
return
|
|
45431
|
+
return readFileSync64(resolve55(process.cwd(), "public", "sw.js"), "utf-8");
|
|
45397
45432
|
} catch {
|
|
45398
45433
|
return null;
|
|
45399
45434
|
}
|
|
@@ -45401,9 +45436,9 @@ var SW_SOURCE = (() => {
|
|
|
45401
45436
|
function readInstalledVersion() {
|
|
45402
45437
|
try {
|
|
45403
45438
|
if (!PLATFORM_ROOT6) return "unknown";
|
|
45404
|
-
const versionFile =
|
|
45439
|
+
const versionFile = join78(PLATFORM_ROOT6, "config", `.${BRAND.hostname}-version`);
|
|
45405
45440
|
if (!existsSync63(versionFile)) return "unknown";
|
|
45406
|
-
const content =
|
|
45441
|
+
const content = readFileSync64(versionFile, "utf-8").trim();
|
|
45407
45442
|
return content || "unknown";
|
|
45408
45443
|
} catch {
|
|
45409
45444
|
return "unknown";
|
|
@@ -45414,7 +45449,7 @@ var versionScript = `<script>window.__MAXY_VERSION__=${JSON.stringify(INSTALLED_
|
|
|
45414
45449
|
function cachedHtml(file) {
|
|
45415
45450
|
let html = htmlCache.get(file);
|
|
45416
45451
|
if (!html) {
|
|
45417
|
-
html =
|
|
45452
|
+
html = readFileSync64(resolve55(process.cwd(), "public", file), "utf-8");
|
|
45418
45453
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
45419
45454
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
45420
45455
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -45431,14 +45466,14 @@ ${clientErrorReporterScript}
|
|
|
45431
45466
|
return html;
|
|
45432
45467
|
}
|
|
45433
45468
|
function loadBrandingCache(agentSlug) {
|
|
45434
|
-
const configDir =
|
|
45469
|
+
const configDir = join78(homedir5(), BRAND.configDir);
|
|
45435
45470
|
try {
|
|
45436
45471
|
const verdict = resolvePublicAddressFromDisk(agentSlug);
|
|
45437
45472
|
const accountId = verdict.kind === "served" ? verdict.owner.accountId : getDefaultAccountId();
|
|
45438
45473
|
if (!accountId) return null;
|
|
45439
|
-
const cachePath =
|
|
45474
|
+
const cachePath = join78(configDir, "branding-cache", accountId, `${agentSlug}.json`);
|
|
45440
45475
|
if (!existsSync63(cachePath)) return null;
|
|
45441
|
-
return JSON.parse(
|
|
45476
|
+
return JSON.parse(readFileSync64(cachePath, "utf-8"));
|
|
45442
45477
|
} catch {
|
|
45443
45478
|
return null;
|
|
45444
45479
|
}
|
|
@@ -45533,7 +45568,7 @@ app80.use("/vnc-popout.html", logViewerFetch);
|
|
|
45533
45568
|
app80.get("/vnc-popout.html", (c) => {
|
|
45534
45569
|
let html = htmlCache.get("vnc-popout.html");
|
|
45535
45570
|
if (!html) {
|
|
45536
|
-
html =
|
|
45571
|
+
html = readFileSync64(resolve55(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
45537
45572
|
const name = escapeHtml(BRAND.productName);
|
|
45538
45573
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
45539
45574
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -45687,7 +45722,7 @@ var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
|
45687
45722
|
var httpServer = serve({ fetch: app80.fetch, port, hostname });
|
|
45688
45723
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
45689
45724
|
{
|
|
45690
|
-
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
45725
|
+
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join78(__dirname, "..");
|
|
45691
45726
|
const reconcileScript = resolve55(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
|
|
45692
45727
|
const runReconcile = (ctx) => {
|
|
45693
45728
|
if (!existsSync63(reconcileScript)) return;
|
|
@@ -45710,7 +45745,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
45710
45745
|
detached: true,
|
|
45711
45746
|
run: runReconcile
|
|
45712
45747
|
});
|
|
45713
|
-
const reconcileStatePath =
|
|
45748
|
+
const reconcileStatePath = join78(MAXY_DIR, "booking-reconcile-state.json");
|
|
45714
45749
|
registerLoop({
|
|
45715
45750
|
name: "calendar-reconcile-liveness",
|
|
45716
45751
|
intervalMs: 6e5,
|
|
@@ -45728,7 +45763,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
45728
45763
|
}
|
|
45729
45764
|
{
|
|
45730
45765
|
const DREAM_CYCLE_SWEEP_INTERVAL_MS = 36e5;
|
|
45731
|
-
const dreamPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
45766
|
+
const dreamPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join78(__dirname, "..");
|
|
45732
45767
|
const dreamSweepScript = resolve55(dreamPlatformRoot, "plugins/memory/mcp/dist/scripts/dream-cycle-sweep.js");
|
|
45733
45768
|
registerLoop({
|
|
45734
45769
|
name: "dream-cycle-sweep",
|
|
@@ -45752,7 +45787,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
45752
45787
|
});
|
|
45753
45788
|
}
|
|
45754
45789
|
{
|
|
45755
|
-
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
45790
|
+
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join78(__dirname, "..");
|
|
45756
45791
|
const outlookScript = resolve55(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
|
|
45757
45792
|
const OUTLOOK_COMPLETE_INTERVAL_MS = 3e4;
|
|
45758
45793
|
const runOutlookComplete = (ctx) => {
|
|
@@ -45778,7 +45813,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
45778
45813
|
});
|
|
45779
45814
|
}
|
|
45780
45815
|
{
|
|
45781
|
-
const auditRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
45816
|
+
const auditRoot = process.env.MAXY_PLATFORM_ROOT ?? join78(__dirname, "..");
|
|
45782
45817
|
const strandedAccountsDir = resolve55(auditRoot, "..", "data/accounts");
|
|
45783
45818
|
const STRANDED_AUDIT_INTERVAL_MS = 3e5;
|
|
45784
45819
|
const STRANDED_AGE_MS = 16 * 6e4;
|
|
@@ -45787,11 +45822,11 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
45787
45822
|
try {
|
|
45788
45823
|
if (!existsSync63(strandedAccountsDir)) return;
|
|
45789
45824
|
const now = Date.now();
|
|
45790
|
-
for (const name of
|
|
45825
|
+
for (const name of readdirSync38(strandedAccountsDir)) {
|
|
45791
45826
|
if (!STRANDED_UUID_RE.test(name)) continue;
|
|
45792
45827
|
const pendingPath2 = resolve55(strandedAccountsDir, name, "secrets/outlook/pending-devicecode.enc");
|
|
45793
45828
|
if (!existsSync63(pendingPath2)) continue;
|
|
45794
|
-
const ageMs2 = now -
|
|
45829
|
+
const ageMs2 = now - statSync34(pendingPath2).mtimeMs;
|
|
45795
45830
|
if (ageMs2 > STRANDED_AGE_MS) {
|
|
45796
45831
|
console.error(`[outlook-mcp] devicecode-stranded account=${name} ageSec=${Math.floor(ageMs2 / 1e3)}`);
|
|
45797
45832
|
}
|
|
@@ -45808,7 +45843,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
45808
45843
|
});
|
|
45809
45844
|
}
|
|
45810
45845
|
{
|
|
45811
|
-
const googleRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
45846
|
+
const googleRoot = process.env.MAXY_PLATFORM_ROOT ?? join78(__dirname, "..");
|
|
45812
45847
|
const googleAccountsDir = resolve55(googleRoot, "..", "data/accounts");
|
|
45813
45848
|
const GOOGLE_PENDING_AUDIT_INTERVAL_MS = 3e5;
|
|
45814
45849
|
const runGooglePendingAuditSafe = () => {
|
|
@@ -45864,7 +45899,7 @@ registerLoop({
|
|
|
45864
45899
|
}
|
|
45865
45900
|
});
|
|
45866
45901
|
{
|
|
45867
|
-
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
45902
|
+
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join78(__dirname, "..");
|
|
45868
45903
|
const STORAGE_AUDIT_INTERVAL_MS = 3e5;
|
|
45869
45904
|
const runStorageAuditSafe = () => runStorageAudit(auditPlatformRoot).catch((err) => {
|
|
45870
45905
|
console.error(`[storage-audit] error="${err.message}"`);
|
|
@@ -45931,7 +45966,7 @@ registerLoop({
|
|
|
45931
45966
|
const lastByBot = newestTelegramSessionByBot();
|
|
45932
45967
|
let secretFilesOnDisk = [];
|
|
45933
45968
|
try {
|
|
45934
|
-
secretFilesOnDisk =
|
|
45969
|
+
secretFilesOnDisk = readdirSync38(telegramSecretsDir());
|
|
45935
45970
|
} catch {
|
|
45936
45971
|
}
|
|
45937
45972
|
const lines = buildTelegramAuditLines({
|
|
@@ -45939,7 +45974,7 @@ registerLoop({
|
|
|
45939
45974
|
secretFileExists: (botId) => existsSync63(secretPath(botId)),
|
|
45940
45975
|
agentActive: isActiveAgentSlug,
|
|
45941
45976
|
// Task 2619 — the card set a specialist binding is reconciled against.
|
|
45942
|
-
specialistCards: (accountDir) => listSpecialistCardNames(
|
|
45977
|
+
specialistCards: (accountDir) => listSpecialistCardNames(join78(accountDir, "specialists", "agents")),
|
|
45943
45978
|
// Task 2619 — the doors that can be sent to right now. The same accessor
|
|
45944
45979
|
// the follower census reads (:1185), so "should have a reader" and "can be
|
|
45945
45980
|
// sent to" stay one fact.
|
|
@@ -46025,6 +46060,14 @@ registerLoop({
|
|
|
46025
46060
|
runTelegramMediaCensus();
|
|
46026
46061
|
}
|
|
46027
46062
|
});
|
|
46063
|
+
registerLoop({
|
|
46064
|
+
name: "telegram-card-row-census",
|
|
46065
|
+
intervalMs: STORAGE_AUDIT_INTERVAL_MS,
|
|
46066
|
+
firstRunDelayMs: 11e4,
|
|
46067
|
+
run: async () => {
|
|
46068
|
+
runTelegramCardRowCensus(process.env.LOG_DIR ?? LOG_DIR);
|
|
46069
|
+
}
|
|
46070
|
+
});
|
|
46028
46071
|
registerLoop({
|
|
46029
46072
|
name: "telegram-checkout-census",
|
|
46030
46073
|
intervalMs: STORAGE_AUDIT_INTERVAL_MS,
|
|
@@ -46340,7 +46383,7 @@ registerLoop({
|
|
|
46340
46383
|
});
|
|
46341
46384
|
}
|
|
46342
46385
|
{
|
|
46343
|
-
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
46386
|
+
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join78(__dirname, "..");
|
|
46344
46387
|
const publishScript = resolve55(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
|
|
46345
46388
|
const PUBLISH_INTERVAL_MS = 3e5;
|
|
46346
46389
|
const bookingAccounts = () => {
|
|
@@ -46375,7 +46418,7 @@ registerLoop({
|
|
|
46375
46418
|
let hasBookingSite = false;
|
|
46376
46419
|
try {
|
|
46377
46420
|
if (existsSync63(availPath)) {
|
|
46378
|
-
const cfg = JSON.parse(
|
|
46421
|
+
const cfg = JSON.parse(readFileSync64(availPath, "utf-8"));
|
|
46379
46422
|
hasBookingSite = typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
46380
46423
|
}
|
|
46381
46424
|
} catch {
|
|
@@ -46385,7 +46428,7 @@ registerLoop({
|
|
|
46385
46428
|
let lastSuccessAt = null;
|
|
46386
46429
|
if (existsSync63(statePath)) {
|
|
46387
46430
|
try {
|
|
46388
|
-
const rec = JSON.parse(
|
|
46431
|
+
const rec = JSON.parse(readFileSync64(statePath, "utf-8"));
|
|
46389
46432
|
lastSuccessAt = rec.lastSuccessAt ?? null;
|
|
46390
46433
|
} catch {
|
|
46391
46434
|
console.error(`[calendar-availability] op=audit accountId=${account.accountId} snapshotAgeMs=na reason=bad-state-file`);
|
|
@@ -46420,7 +46463,7 @@ startDispatchCensus(() => getSession());
|
|
|
46420
46463
|
startDispatchFieldCensus(() => getSession());
|
|
46421
46464
|
startDispatchTgCensus(() => getSession());
|
|
46422
46465
|
{
|
|
46423
|
-
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
46466
|
+
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join78(__dirname, "..");
|
|
46424
46467
|
const auditScript = resolve55(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
|
|
46425
46468
|
const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
|
|
46426
46469
|
const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
|
|
@@ -46551,7 +46594,7 @@ async function runAdminUserReconcileTick() {
|
|
|
46551
46594
|
console.error("[adminuser-self-heal] skip reason=no-users-file");
|
|
46552
46595
|
return;
|
|
46553
46596
|
}
|
|
46554
|
-
const usersRaw =
|
|
46597
|
+
const usersRaw = readFileSync64(USERS_FILE, "utf-8").trim();
|
|
46555
46598
|
if (!usersRaw) {
|
|
46556
46599
|
console.error("[adminuser-self-heal] skip reason=empty-users-file");
|
|
46557
46600
|
return;
|
|
@@ -46633,8 +46676,8 @@ var runIngestAuditTick = () => {
|
|
|
46633
46676
|
},
|
|
46634
46677
|
agentExists: (accountId, slug) => {
|
|
46635
46678
|
if (!house) return false;
|
|
46636
|
-
const dir = isHouseAccountKey(house.accountId, accountId) ? house.accountDir :
|
|
46637
|
-
return existsSync63(
|
|
46679
|
+
const dir = isHouseAccountKey(house.accountId, accountId) ? house.accountDir : join78(ACCOUNTS_DIR, accountId);
|
|
46680
|
+
return existsSync63(join78(dir, "agents", slug, "config.json"));
|
|
46638
46681
|
}
|
|
46639
46682
|
});
|
|
46640
46683
|
} catch (err) {
|
|
@@ -46682,9 +46725,9 @@ registerLoop({
|
|
|
46682
46725
|
runPublicAddressCollisionAudit({
|
|
46683
46726
|
houseAccountId: () => resolveAccount()?.accountId ?? null,
|
|
46684
46727
|
activeSlugs: () => listValidAccounts().map((a) => {
|
|
46685
|
-
const agentsRoot =
|
|
46728
|
+
const agentsRoot = join78(a.accountDir, "agents");
|
|
46686
46729
|
if (!existsSync63(agentsRoot)) return { accountId: a.accountId, slugs: [] };
|
|
46687
|
-
const slugs =
|
|
46730
|
+
const slugs = readdirSync38(agentsRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).filter((slug) => isActiveAgentSlug(a.accountDir, slug));
|
|
46688
46731
|
return { accountId: a.accountId, slugs };
|
|
46689
46732
|
})
|
|
46690
46733
|
});
|
|
@@ -46698,7 +46741,7 @@ registerLoop({
|
|
|
46698
46741
|
var USERS_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
46699
46742
|
function countUsersRows() {
|
|
46700
46743
|
if (!existsSync63(USERS_FILE)) return 0;
|
|
46701
|
-
const raw =
|
|
46744
|
+
const raw = readFileSync64(USERS_FILE, "utf-8").trim();
|
|
46702
46745
|
if (!raw) return 0;
|
|
46703
46746
|
const users = JSON.parse(raw);
|
|
46704
46747
|
return users.filter((u) => typeof u.userId === "string").length;
|
|
@@ -46801,7 +46844,7 @@ function sessionChannelResolver() {
|
|
|
46801
46844
|
byId = /* @__PURE__ */ new Map();
|
|
46802
46845
|
const cfg = claudeConfigDir();
|
|
46803
46846
|
if (cfg) {
|
|
46804
|
-
for (const { path } of enumerateSessionSidecars(
|
|
46847
|
+
for (const { path } of enumerateSessionSidecars(join78(cfg, "projects"))) {
|
|
46805
46848
|
const channel = readSidecarMeta(path).channel;
|
|
46806
46849
|
if (channel) byId.set(basename19(path).replace(/\.meta\.json$/, ""), channel);
|
|
46807
46850
|
}
|
|
@@ -46876,7 +46919,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
46876
46919
|
}
|
|
46877
46920
|
init({
|
|
46878
46921
|
configDir: configDirForWhatsApp,
|
|
46879
|
-
platformRoot: resolve55(process.env.MAXY_PLATFORM_ROOT ??
|
|
46922
|
+
platformRoot: resolve55(process.env.MAXY_PLATFORM_ROOT ?? join78(__dirname, "..")),
|
|
46880
46923
|
accountConfig: bootAccountConfig,
|
|
46881
46924
|
// Task 2074 — enrich with the sub-account name and fan out to every open
|
|
46882
46925
|
// admin SSE stream. Fire-and-forget: the manager's persist path must not
|