@rubytech/create-realagent 1.0.658 → 1.0.660
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/payload/platform/plugins/cloudflare/scripts/list-cf-domains.ts +115 -61
- package/payload/platform/plugins/contacts/mcp/dist/lib/resolve-person.d.ts +13 -1
- package/payload/platform/plugins/contacts/mcp/dist/lib/resolve-person.d.ts.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/lib/resolve-person.js +20 -5
- package/payload/platform/plugins/contacts/mcp/dist/lib/resolve-person.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.d.ts.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js +6 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-delete.d.ts.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-delete.js +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-delete.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.d.ts.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.js +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.d.ts.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.js +8 -3
- package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/group-manage.d.ts.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/group-manage.js +14 -6
- package/payload/platform/plugins/contacts/mcp/dist/tools/group-manage.js.map +1 -1
- package/payload/platform/plugins/docs/references/memory-guide.md +2 -0
- package/payload/platform/plugins/email/mcp/dist/lib/credentials.d.ts +7 -0
- package/payload/platform/plugins/email/mcp/dist/lib/credentials.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/credentials.js +7 -0
- package/payload/platform/plugins/email/mcp/dist/lib/credentials.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/index.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/document-hierarchy.d.ts +0 -16
- package/payload/platform/plugins/memory/mcp/dist/lib/document-hierarchy.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/document-hierarchy.js +0 -39
- package/payload/platform/plugins/memory/mcp/dist/lib/document-hierarchy.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-delete.d.ts +10 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-delete.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-delete.js +20 -7
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-delete.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js +4 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js +24 -5
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/index.js +6 -3
- package/payload/platform/plugins/workflows/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/lib/active-runs.d.ts.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/lib/active-runs.js +2 -1
- package/payload/platform/plugins/workflows/mcp/dist/lib/active-runs.js.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-delete.d.ts +25 -3
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-delete.d.ts.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-delete.js +44 -12
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-delete.js.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.d.ts.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.js +19 -3
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.js.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-get.d.ts.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-get.js +3 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-get.js.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-list.d.ts.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-list.js +3 -2
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-list.js.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-runs.d.ts.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-runs.js +7 -2
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-runs.js.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-update.d.ts.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-update.js +5 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-update.js.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-validate.d.ts.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-validate.js +3 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-validate.js.map +1 -1
- package/payload/server/public/assets/{admin-Czc-XCGo.js → admin-BFIYSS4u.js} +1 -1
- package/payload/server/public/assets/{data-CrSbmVOi.js → data-BmeeI1Ix.js} +1 -1
- package/payload/server/public/assets/{file-DJN8iDYd.js → file-D4Qulqz_.js} +1 -1
- package/payload/server/public/assets/graph-MoIys9Ub.js +49 -0
- package/payload/server/public/assets/{house-0e8rAfIV.js → house-B0Hukxjp.js} +1 -1
- package/payload/server/public/assets/{jsx-runtime-c8K7DPME.css → jsx-runtime-C6owBiFB.css} +1 -1
- package/payload/server/public/assets/{public-CWJExYI2.js → public-LvjJTLGn.js} +1 -1
- package/payload/server/public/assets/{share-2-DZ7p8QqC.js → share-2-BafZBLp9.js} +1 -1
- package/payload/server/public/assets/{useVoiceRecorder-BgiIIuSz.js → useVoiceRecorder-dLOpmcYJ.js} +1 -1
- package/payload/server/public/assets/{x-CknuyFAk.js → x-BOZIeV0f.js} +1 -1
- package/payload/server/public/data.html +6 -6
- package/payload/server/public/graph.html +6 -6
- package/payload/server/public/index.html +7 -7
- package/payload/server/public/public.html +4 -4
- package/payload/server/server.js +262 -160
- package/payload/server/public/assets/graph-BtnUfXRD.js +0 -49
- /package/payload/server/public/assets/{jsx-runtime-DHkQ2la3.js → jsx-runtime-CmCvZzVE.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./jsx-runtime-
|
|
1
|
+
import{r as e}from"./jsx-runtime-CmCvZzVE.js";var t=e(`rotate-ccw`,[[`path`,{d:`M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8`,key:`1357e3`}],[`path`,{d:`M3 3v5h5`,key:`1xhq8a`}]]),n=e(`x`,[[`path`,{d:`M18 6 6 18`,key:`1bl5f8`}],[`path`,{d:`m6 6 12 12`,key:`d8bk6v`}]]);export{t as n,n as t};
|
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Data — Maxy</title>
|
|
7
7
|
<link rel="icon" href="/favicon.ico">
|
|
8
|
-
<script type="module" crossorigin src="/assets/data-
|
|
8
|
+
<script type="module" crossorigin src="/assets/data-BmeeI1Ix.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/chunk-DD-I1_y5.js">
|
|
10
|
-
<link rel="modulepreload" crossorigin href="/assets/jsx-runtime-
|
|
11
|
-
<link rel="modulepreload" crossorigin href="/assets/share-2-
|
|
12
|
-
<link rel="modulepreload" crossorigin href="/assets/file-
|
|
13
|
-
<link rel="modulepreload" crossorigin href="/assets/house-
|
|
14
|
-
<link rel="stylesheet" crossorigin href="/assets/jsx-runtime-
|
|
10
|
+
<link rel="modulepreload" crossorigin href="/assets/jsx-runtime-CmCvZzVE.js">
|
|
11
|
+
<link rel="modulepreload" crossorigin href="/assets/share-2-BafZBLp9.js">
|
|
12
|
+
<link rel="modulepreload" crossorigin href="/assets/file-D4Qulqz_.js">
|
|
13
|
+
<link rel="modulepreload" crossorigin href="/assets/house-B0Hukxjp.js">
|
|
14
|
+
<link rel="stylesheet" crossorigin href="/assets/jsx-runtime-C6owBiFB.css">
|
|
15
15
|
</head>
|
|
16
16
|
<body>
|
|
17
17
|
<div id="root"></div>
|
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Graph — Maxy</title>
|
|
7
7
|
<link rel="icon" href="/favicon.ico">
|
|
8
|
-
<script type="module" crossorigin src="/assets/graph-
|
|
8
|
+
<script type="module" crossorigin src="/assets/graph-MoIys9Ub.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/chunk-DD-I1_y5.js">
|
|
10
|
-
<link rel="modulepreload" crossorigin href="/assets/jsx-runtime-
|
|
11
|
-
<link rel="modulepreload" crossorigin href="/assets/share-2-
|
|
12
|
-
<link rel="modulepreload" crossorigin href="/assets/house-
|
|
13
|
-
<link rel="modulepreload" crossorigin href="/assets/x-
|
|
14
|
-
<link rel="stylesheet" crossorigin href="/assets/jsx-runtime-
|
|
10
|
+
<link rel="modulepreload" crossorigin href="/assets/jsx-runtime-CmCvZzVE.js">
|
|
11
|
+
<link rel="modulepreload" crossorigin href="/assets/share-2-BafZBLp9.js">
|
|
12
|
+
<link rel="modulepreload" crossorigin href="/assets/house-B0Hukxjp.js">
|
|
13
|
+
<link rel="modulepreload" crossorigin href="/assets/x-BOZIeV0f.js">
|
|
14
|
+
<link rel="stylesheet" crossorigin href="/assets/jsx-runtime-C6owBiFB.css">
|
|
15
15
|
</head>
|
|
16
16
|
<body>
|
|
17
17
|
<div id="root"></div>
|
|
@@ -5,15 +5,15 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Real Agent</title>
|
|
7
7
|
<link rel="icon" href="/favicon.ico">
|
|
8
|
-
<script type="module" crossorigin src="/assets/admin-
|
|
8
|
+
<script type="module" crossorigin src="/assets/admin-BFIYSS4u.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/chunk-DD-I1_y5.js">
|
|
10
|
-
<link rel="modulepreload" crossorigin href="/assets/jsx-runtime-
|
|
10
|
+
<link rel="modulepreload" crossorigin href="/assets/jsx-runtime-CmCvZzVE.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/preload-helper-qlgyTAkD.js">
|
|
12
|
-
<link rel="modulepreload" crossorigin href="/assets/useVoiceRecorder-
|
|
13
|
-
<link rel="modulepreload" crossorigin href="/assets/share-2-
|
|
14
|
-
<link rel="modulepreload" crossorigin href="/assets/file-
|
|
15
|
-
<link rel="modulepreload" crossorigin href="/assets/x-
|
|
16
|
-
<link rel="stylesheet" crossorigin href="/assets/jsx-runtime-
|
|
12
|
+
<link rel="modulepreload" crossorigin href="/assets/useVoiceRecorder-dLOpmcYJ.js">
|
|
13
|
+
<link rel="modulepreload" crossorigin href="/assets/share-2-BafZBLp9.js">
|
|
14
|
+
<link rel="modulepreload" crossorigin href="/assets/file-D4Qulqz_.js">
|
|
15
|
+
<link rel="modulepreload" crossorigin href="/assets/x-BOZIeV0f.js">
|
|
16
|
+
<link rel="stylesheet" crossorigin href="/assets/jsx-runtime-C6owBiFB.css">
|
|
17
17
|
<link rel="stylesheet" crossorigin href="/assets/admin-kHJ-D0s7.css">
|
|
18
18
|
<link rel="stylesheet" href="/brand-defaults.css">
|
|
19
19
|
</head>
|
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Real Agent</title>
|
|
7
7
|
<link rel="icon" href="/favicon.ico">
|
|
8
|
-
<script type="module" crossorigin src="/assets/public-
|
|
8
|
+
<script type="module" crossorigin src="/assets/public-LvjJTLGn.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/chunk-DD-I1_y5.js">
|
|
10
|
-
<link rel="modulepreload" crossorigin href="/assets/jsx-runtime-
|
|
10
|
+
<link rel="modulepreload" crossorigin href="/assets/jsx-runtime-CmCvZzVE.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/preload-helper-qlgyTAkD.js">
|
|
12
|
-
<link rel="modulepreload" crossorigin href="/assets/useVoiceRecorder-
|
|
13
|
-
<link rel="stylesheet" crossorigin href="/assets/jsx-runtime-
|
|
12
|
+
<link rel="modulepreload" crossorigin href="/assets/useVoiceRecorder-dLOpmcYJ.js">
|
|
13
|
+
<link rel="stylesheet" crossorigin href="/assets/jsx-runtime-C6owBiFB.css">
|
|
14
14
|
<link rel="stylesheet" href="/brand-defaults.css">
|
|
15
15
|
</head>
|
|
16
16
|
<body>
|
package/payload/server/server.js
CHANGED
|
@@ -20254,8 +20254,236 @@ function resolveDataPath(raw2) {
|
|
|
20254
20254
|
return { ok: true, absolute: resolvedReal, dataRootReal, relative: relPath };
|
|
20255
20255
|
}
|
|
20256
20256
|
|
|
20257
|
-
//
|
|
20257
|
+
// ../lib/graph-trash/src/index.ts
|
|
20258
|
+
var UNIQUE_KEYS_BY_LABEL = {
|
|
20259
|
+
Person: ["email", "telephone"],
|
|
20260
|
+
Service: ["serviceId"],
|
|
20261
|
+
LocalBusiness: ["accountId"],
|
|
20262
|
+
Task: ["taskId"],
|
|
20263
|
+
Event: ["eventId"],
|
|
20264
|
+
KnowledgeDocument: ["attachmentId"],
|
|
20265
|
+
DigitalDocument: ["attachmentId"],
|
|
20266
|
+
Conversation: ["conversationId", "sessionKey"],
|
|
20267
|
+
Message: ["messageId"],
|
|
20268
|
+
OnboardingState: ["accountId"],
|
|
20269
|
+
Workflow: ["workflowId"],
|
|
20270
|
+
WorkflowStep: ["stepId"],
|
|
20271
|
+
WorkflowRun: ["runId"],
|
|
20272
|
+
Preference: ["preferenceId"],
|
|
20273
|
+
Email: ["emailId", "messageId"],
|
|
20274
|
+
AdminUser: ["userId"],
|
|
20275
|
+
ToolCall: ["callId"],
|
|
20276
|
+
// Composite component nulls — frees the composite constraint:
|
|
20277
|
+
AccessGrant: ["contactValue"],
|
|
20278
|
+
// composite (contactValue, agentSlug, accountId)
|
|
20279
|
+
UserProfile: ["userId"]
|
|
20280
|
+
// composite (accountId, userId)
|
|
20281
|
+
};
|
|
20282
|
+
async function trashNode(params) {
|
|
20283
|
+
const { session, accountId, elementId, by, reason } = params;
|
|
20284
|
+
const lookup = await session.run(
|
|
20285
|
+
`MATCH (n) WHERE elementId(n) = $eid AND n.accountId = $accountId
|
|
20286
|
+
RETURN labels(n) AS labels, properties(n) AS props`,
|
|
20287
|
+
{ eid: elementId, accountId }
|
|
20288
|
+
);
|
|
20289
|
+
if (lookup.records.length === 0) {
|
|
20290
|
+
throw new Error(
|
|
20291
|
+
`trashNode: node not found (elementId=${elementId} accountId=${accountId.slice(0, 8)}\u2026)`
|
|
20292
|
+
);
|
|
20293
|
+
}
|
|
20294
|
+
const allLabels = lookup.records[0].get("labels");
|
|
20295
|
+
const props = lookup.records[0].get("props");
|
|
20296
|
+
const baseLabels = allLabels.filter((l) => l !== "Trashed");
|
|
20297
|
+
if (allLabels.includes("Trashed")) {
|
|
20298
|
+
return {
|
|
20299
|
+
trashed: false,
|
|
20300
|
+
alreadyTrashed: true,
|
|
20301
|
+
nodeId: elementId,
|
|
20302
|
+
labels: baseLabels,
|
|
20303
|
+
trashedAt: String(props.trashedAt ?? ""),
|
|
20304
|
+
originalKeys: {}
|
|
20305
|
+
};
|
|
20306
|
+
}
|
|
20307
|
+
const uniqueKeys = /* @__PURE__ */ new Set();
|
|
20308
|
+
for (const label of baseLabels) {
|
|
20309
|
+
for (const key of UNIQUE_KEYS_BY_LABEL[label] ?? []) uniqueKeys.add(key);
|
|
20310
|
+
}
|
|
20311
|
+
const originalKeys = {};
|
|
20312
|
+
for (const k of uniqueKeys) {
|
|
20313
|
+
if (props[k] !== void 0 && props[k] !== null) originalKeys[k] = props[k];
|
|
20314
|
+
}
|
|
20315
|
+
const setNullClauses = Object.keys(originalKeys).map((k) => `n.\`${k}\` = null`).join(", ");
|
|
20316
|
+
const setNullSuffix = setNullClauses ? `, ${setNullClauses}` : "";
|
|
20317
|
+
const trashedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
20318
|
+
await session.run(
|
|
20319
|
+
`MATCH (n) WHERE elementId(n) = $eid
|
|
20320
|
+
SET n:Trashed,
|
|
20321
|
+
n.trashedAt = datetime($trashedAt),
|
|
20322
|
+
n.trashedBy = $by,
|
|
20323
|
+
n.trashReason = $reason,
|
|
20324
|
+
n._trashedKeys = $trashedKeysJson${setNullSuffix}`,
|
|
20325
|
+
{
|
|
20326
|
+
eid: elementId,
|
|
20327
|
+
trashedAt,
|
|
20328
|
+
by,
|
|
20329
|
+
reason: reason ?? null,
|
|
20330
|
+
trashedKeysJson: JSON.stringify(originalKeys)
|
|
20331
|
+
}
|
|
20332
|
+
);
|
|
20333
|
+
process.stderr.write(
|
|
20334
|
+
`[trash:marked] accountId=${accountId} elementId=${elementId} labels=${baseLabels.join(",")} by=${by} reason=${reason ?? "null"}
|
|
20335
|
+
`
|
|
20336
|
+
);
|
|
20337
|
+
return {
|
|
20338
|
+
trashed: true,
|
|
20339
|
+
alreadyTrashed: false,
|
|
20340
|
+
nodeId: elementId,
|
|
20341
|
+
labels: baseLabels,
|
|
20342
|
+
trashedAt,
|
|
20343
|
+
originalKeys
|
|
20344
|
+
};
|
|
20345
|
+
}
|
|
20346
|
+
async function restoreNode(params) {
|
|
20347
|
+
const { session, accountId, elementId } = params;
|
|
20348
|
+
const lookup = await session.run(
|
|
20349
|
+
`MATCH (n:Trashed) WHERE elementId(n) = $eid
|
|
20350
|
+
RETURN labels(n) AS labels, n._trashedKeys AS keysJson`,
|
|
20351
|
+
{ eid: elementId }
|
|
20352
|
+
);
|
|
20353
|
+
if (lookup.records.length === 0) {
|
|
20354
|
+
throw new Error(
|
|
20355
|
+
`restoreNode: trashed node not found (elementId=${elementId})`
|
|
20356
|
+
);
|
|
20357
|
+
}
|
|
20358
|
+
const allLabels = lookup.records[0].get("labels");
|
|
20359
|
+
const baseLabels = allLabels.filter((l) => l !== "Trashed");
|
|
20360
|
+
const keysJson = lookup.records[0].get("keysJson");
|
|
20361
|
+
const originalKeys = keysJson ? JSON.parse(keysJson) : {};
|
|
20362
|
+
for (const label of baseLabels) {
|
|
20363
|
+
const uniqueKeys = UNIQUE_KEYS_BY_LABEL[label] ?? [];
|
|
20364
|
+
for (const k of uniqueKeys) {
|
|
20365
|
+
const v = originalKeys[k];
|
|
20366
|
+
if (v === void 0 || v === null) continue;
|
|
20367
|
+
const conflict = await session.run(
|
|
20368
|
+
`MATCH (other:\`${label}\`)
|
|
20369
|
+
WHERE elementId(other) <> $eid
|
|
20370
|
+
AND NOT other:Trashed
|
|
20371
|
+
AND other.\`${k}\` = $val
|
|
20372
|
+
RETURN elementId(other) AS otherId LIMIT 1`,
|
|
20373
|
+
{ eid: elementId, val: v }
|
|
20374
|
+
);
|
|
20375
|
+
if (conflict.records.length > 0) {
|
|
20376
|
+
const otherId = conflict.records[0].get("otherId");
|
|
20377
|
+
throw new Error(
|
|
20378
|
+
`restoreNode: cannot restore ${label} elementId=${elementId} \u2014 active node elementId=${otherId} already holds ${k}=${JSON.stringify(v)}`
|
|
20379
|
+
);
|
|
20380
|
+
}
|
|
20381
|
+
}
|
|
20382
|
+
}
|
|
20383
|
+
const setClauses = Object.keys(originalKeys).map((k) => `n.\`${k}\` = $val_${k}`).join(", ");
|
|
20384
|
+
const setSuffix = setClauses ? `, ${setClauses}` : "";
|
|
20385
|
+
const setParams = { eid: elementId };
|
|
20386
|
+
for (const [k, v] of Object.entries(originalKeys)) setParams[`val_${k}`] = v;
|
|
20387
|
+
await session.run(
|
|
20388
|
+
`MATCH (n:Trashed) WHERE elementId(n) = $eid
|
|
20389
|
+
REMOVE n:Trashed, n.trashedAt, n.trashedBy, n.trashReason, n._trashedKeys
|
|
20390
|
+
SET n.restoredAt = datetime()${setSuffix}`,
|
|
20391
|
+
setParams
|
|
20392
|
+
);
|
|
20393
|
+
process.stderr.write(
|
|
20394
|
+
`[trash:restored] accountId=${accountId} elementId=${elementId} labels=${baseLabels.join(",")}
|
|
20395
|
+
`
|
|
20396
|
+
);
|
|
20397
|
+
return {
|
|
20398
|
+
restored: true,
|
|
20399
|
+
nodeId: elementId,
|
|
20400
|
+
labels: baseLabels,
|
|
20401
|
+
restoredKeys: originalKeys
|
|
20402
|
+
};
|
|
20403
|
+
}
|
|
20404
|
+
|
|
20405
|
+
// app/lib/file-delete-cascade.ts
|
|
20258
20406
|
var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
20407
|
+
function parseAttachmentPath(relPath) {
|
|
20408
|
+
const segments = relPath.split("/").filter(Boolean);
|
|
20409
|
+
if (segments.length !== 4) return null;
|
|
20410
|
+
if (segments[0] !== "uploads") return null;
|
|
20411
|
+
const accountId = segments[1];
|
|
20412
|
+
const attachmentId = segments[2];
|
|
20413
|
+
const filename = segments[3];
|
|
20414
|
+
if (!UUID_RE2.test(accountId) || !UUID_RE2.test(attachmentId)) return null;
|
|
20415
|
+
const dot = filename.lastIndexOf(".");
|
|
20416
|
+
if (dot === -1) return null;
|
|
20417
|
+
const stem = filename.slice(0, dot);
|
|
20418
|
+
const ext = filename.slice(dot + 1);
|
|
20419
|
+
if (stem !== attachmentId) return null;
|
|
20420
|
+
if (ext === "meta" || filename.endsWith(".meta.json")) return null;
|
|
20421
|
+
return { accountId, attachmentId };
|
|
20422
|
+
}
|
|
20423
|
+
async function cascadeDeleteDocument(params) {
|
|
20424
|
+
const { accountId, attachmentId } = params;
|
|
20425
|
+
const session = getSession();
|
|
20426
|
+
try {
|
|
20427
|
+
const lookup = await session.run(
|
|
20428
|
+
`MATCH (d:KnowledgeDocument { accountId: $accountId, attachmentId: $attachmentId })
|
|
20429
|
+
WHERE NOT d:Trashed
|
|
20430
|
+
RETURN elementId(d) AS eid LIMIT 1`,
|
|
20431
|
+
{ accountId, attachmentId }
|
|
20432
|
+
);
|
|
20433
|
+
if (lookup.records.length === 0) return { nodes: 0 };
|
|
20434
|
+
const docElementId = lookup.records[0].get("eid");
|
|
20435
|
+
const childResult = await session.run(
|
|
20436
|
+
`MATCH (d) WHERE elementId(d) = $eid
|
|
20437
|
+
OPTIONAL MATCH (d)-[:HAS_SECTION]->(s:Section)
|
|
20438
|
+
OPTIONAL MATCH (s)-[:HAS_CHUNK]->(c:Chunk)
|
|
20439
|
+
WITH collect(DISTINCT s) AS sections, collect(DISTINCT c) AS chunks
|
|
20440
|
+
RETURN [s IN sections WHERE s IS NOT NULL | elementId(s)] AS sectionIds,
|
|
20441
|
+
[c IN chunks WHERE c IS NOT NULL | elementId(c)] AS chunkIds`,
|
|
20442
|
+
{ eid: docElementId }
|
|
20443
|
+
);
|
|
20444
|
+
if (childResult.records.length === 0) {
|
|
20445
|
+
throw new Error(
|
|
20446
|
+
`cascadeDeleteDocument: child lookup returned zero rows for elementId=${docElementId} \u2014 concurrent trash or connection drop`
|
|
20447
|
+
);
|
|
20448
|
+
}
|
|
20449
|
+
const sectionIds = childResult.records[0].get("sectionIds") ?? [];
|
|
20450
|
+
const chunkIds = childResult.records[0].get("chunkIds") ?? [];
|
|
20451
|
+
await trashNode({
|
|
20452
|
+
session,
|
|
20453
|
+
accountId,
|
|
20454
|
+
elementId: docElementId,
|
|
20455
|
+
by: "file-delete-cascade",
|
|
20456
|
+
reason: "file deleted via /data"
|
|
20457
|
+
});
|
|
20458
|
+
for (const sid of sectionIds) {
|
|
20459
|
+
await trashNode({
|
|
20460
|
+
session,
|
|
20461
|
+
accountId,
|
|
20462
|
+
elementId: sid,
|
|
20463
|
+
by: `file-delete-cascade:from-${docElementId}`,
|
|
20464
|
+
reason: `cascade from KnowledgeDocument ${docElementId}`
|
|
20465
|
+
});
|
|
20466
|
+
}
|
|
20467
|
+
for (const cid of chunkIds) {
|
|
20468
|
+
await trashNode({
|
|
20469
|
+
session,
|
|
20470
|
+
accountId,
|
|
20471
|
+
elementId: cid,
|
|
20472
|
+
by: `file-delete-cascade:from-${docElementId}`,
|
|
20473
|
+
reason: `cascade from KnowledgeDocument ${docElementId}`
|
|
20474
|
+
});
|
|
20475
|
+
}
|
|
20476
|
+
return { nodes: 1 };
|
|
20477
|
+
} finally {
|
|
20478
|
+
try {
|
|
20479
|
+
await session.close();
|
|
20480
|
+
} catch {
|
|
20481
|
+
}
|
|
20482
|
+
}
|
|
20483
|
+
}
|
|
20484
|
+
|
|
20485
|
+
// server/routes/admin/files.ts
|
|
20486
|
+
var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
20259
20487
|
async function readMeta(absDir, baseName) {
|
|
20260
20488
|
try {
|
|
20261
20489
|
const raw2 = await readFile4(join12(absDir, `${baseName}.meta.json`), "utf8");
|
|
@@ -20277,7 +20505,7 @@ async function readAccountNames() {
|
|
|
20277
20505
|
return map;
|
|
20278
20506
|
}
|
|
20279
20507
|
for (const name of names) {
|
|
20280
|
-
if (!
|
|
20508
|
+
if (!UUID_RE3.test(name)) continue;
|
|
20281
20509
|
const configPath2 = resolve29(accountsDir, name, "account.json");
|
|
20282
20510
|
try {
|
|
20283
20511
|
const raw2 = await readFile4(configPath2, "utf8");
|
|
@@ -20295,7 +20523,7 @@ async function readAccountNames() {
|
|
|
20295
20523
|
return map;
|
|
20296
20524
|
}
|
|
20297
20525
|
async function enrich(absolute, entry, accountNames) {
|
|
20298
|
-
if (entry.kind === "directory" &&
|
|
20526
|
+
if (entry.kind === "directory" && UUID_RE3.test(entry.name)) {
|
|
20299
20527
|
const meta = await readMeta(join12(absolute, entry.name), entry.name);
|
|
20300
20528
|
if (meta?.filename) {
|
|
20301
20529
|
entry.displayName = meta.filename;
|
|
@@ -20311,7 +20539,7 @@ async function enrich(absolute, entry, accountNames) {
|
|
|
20311
20539
|
if (entry.kind === "file") {
|
|
20312
20540
|
const dot = entry.name.lastIndexOf(".");
|
|
20313
20541
|
const base = dot === -1 ? entry.name : entry.name.slice(0, dot);
|
|
20314
|
-
if (
|
|
20542
|
+
if (UUID_RE3.test(base)) {
|
|
20315
20543
|
const meta = await readMeta(absolute, base);
|
|
20316
20544
|
if (meta?.filename) {
|
|
20317
20545
|
entry.displayName = meta.filename;
|
|
@@ -20323,7 +20551,7 @@ async function enrich(absolute, entry, accountNames) {
|
|
|
20323
20551
|
function buildDisplayPath(relPath, accountNames) {
|
|
20324
20552
|
if (relPath === "." || relPath === "") return [];
|
|
20325
20553
|
return relPath.split("/").filter(Boolean).map((seg) => {
|
|
20326
|
-
const dn =
|
|
20554
|
+
const dn = UUID_RE3.test(seg) ? accountNames.get(seg) : void 0;
|
|
20327
20555
|
return dn ? { name: seg, displayName: dn } : { name: seg };
|
|
20328
20556
|
});
|
|
20329
20557
|
}
|
|
@@ -20351,7 +20579,7 @@ app24.get("/", requireAdminSession, async (c) => {
|
|
|
20351
20579
|
const names = await readdir2(absolute);
|
|
20352
20580
|
const entries = [];
|
|
20353
20581
|
for (const name of names) {
|
|
20354
|
-
if (
|
|
20582
|
+
if (UUID_RE3.test(name.replace(/\.meta\.json$/, "")) && name.endsWith(".meta.json")) {
|
|
20355
20583
|
continue;
|
|
20356
20584
|
}
|
|
20357
20585
|
try {
|
|
@@ -20497,7 +20725,8 @@ app24.post("/upload", requireAdminSession, async (c) => {
|
|
|
20497
20725
|
});
|
|
20498
20726
|
app24.delete("/", requireAdminSession, async (c) => {
|
|
20499
20727
|
const sessionKey = c.var.sessionKey;
|
|
20500
|
-
|
|
20728
|
+
const accountId = getAccountIdForSession(sessionKey);
|
|
20729
|
+
if (!accountId) {
|
|
20501
20730
|
console.error(`[data] auth-rejected endpoint="DELETE /api/admin/files" reason="no account for session"`);
|
|
20502
20731
|
return c.json({ error: "Account not found for session" }, 401);
|
|
20503
20732
|
}
|
|
@@ -20527,7 +20756,7 @@ app24.delete("/", requireAdminSession, async (c) => {
|
|
|
20527
20756
|
}
|
|
20528
20757
|
const dot = base.lastIndexOf(".");
|
|
20529
20758
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
20530
|
-
const sidecarPath =
|
|
20759
|
+
const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join12(dirname10(absolute), `${stem}.meta.json`) : null;
|
|
20531
20760
|
await unlink2(absolute);
|
|
20532
20761
|
if (sidecarPath) {
|
|
20533
20762
|
try {
|
|
@@ -20536,6 +20765,19 @@ app24.delete("/", requireAdminSession, async (c) => {
|
|
|
20536
20765
|
}
|
|
20537
20766
|
}
|
|
20538
20767
|
console.error(`[data] file-delete path="${relPath}" bytes=${info.size}`);
|
|
20768
|
+
const parsed = parseAttachmentPath(relPath);
|
|
20769
|
+
if (parsed) {
|
|
20770
|
+
try {
|
|
20771
|
+
const { nodes } = await cascadeDeleteDocument({
|
|
20772
|
+
accountId,
|
|
20773
|
+
attachmentId: parsed.attachmentId
|
|
20774
|
+
});
|
|
20775
|
+
console.error(`[data] file-delete graph-cascade path="${relPath}" nodes=${nodes}`);
|
|
20776
|
+
} catch (err) {
|
|
20777
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
20778
|
+
console.error(`[data] file-delete graph-cascade-failed path="${relPath}" err="${message}"`);
|
|
20779
|
+
}
|
|
20780
|
+
}
|
|
20539
20781
|
return c.json({ ok: true });
|
|
20540
20782
|
} catch (err) {
|
|
20541
20783
|
const code = err.code;
|
|
@@ -20884,155 +21126,8 @@ function pruneNode(node) {
|
|
|
20884
21126
|
}
|
|
20885
21127
|
var graph_subgraph_default = app26;
|
|
20886
21128
|
|
|
20887
|
-
// ../lib/graph-trash/src/index.ts
|
|
20888
|
-
var UNIQUE_KEYS_BY_LABEL = {
|
|
20889
|
-
Person: ["email", "telephone"],
|
|
20890
|
-
Service: ["serviceId"],
|
|
20891
|
-
LocalBusiness: ["accountId"],
|
|
20892
|
-
Task: ["taskId"],
|
|
20893
|
-
Event: ["eventId"],
|
|
20894
|
-
KnowledgeDocument: ["attachmentId"],
|
|
20895
|
-
DigitalDocument: ["attachmentId"],
|
|
20896
|
-
Conversation: ["conversationId", "sessionKey"],
|
|
20897
|
-
Message: ["messageId"],
|
|
20898
|
-
OnboardingState: ["accountId"],
|
|
20899
|
-
Workflow: ["workflowId"],
|
|
20900
|
-
WorkflowStep: ["stepId"],
|
|
20901
|
-
WorkflowRun: ["runId"],
|
|
20902
|
-
Preference: ["preferenceId"],
|
|
20903
|
-
Email: ["emailId", "messageId"],
|
|
20904
|
-
AdminUser: ["userId"],
|
|
20905
|
-
ToolCall: ["callId"],
|
|
20906
|
-
// Composite component nulls — frees the composite constraint:
|
|
20907
|
-
AccessGrant: ["contactValue"],
|
|
20908
|
-
// composite (contactValue, agentSlug, accountId)
|
|
20909
|
-
UserProfile: ["userId"]
|
|
20910
|
-
// composite (accountId, userId)
|
|
20911
|
-
};
|
|
20912
|
-
async function trashNode(params) {
|
|
20913
|
-
const { session, accountId, elementId, by, reason } = params;
|
|
20914
|
-
const lookup = await session.run(
|
|
20915
|
-
`MATCH (n) WHERE elementId(n) = $eid AND n.accountId = $accountId
|
|
20916
|
-
RETURN labels(n) AS labels, properties(n) AS props`,
|
|
20917
|
-
{ eid: elementId, accountId }
|
|
20918
|
-
);
|
|
20919
|
-
if (lookup.records.length === 0) {
|
|
20920
|
-
throw new Error(
|
|
20921
|
-
`trashNode: node not found (elementId=${elementId} accountId=${accountId.slice(0, 8)}\u2026)`
|
|
20922
|
-
);
|
|
20923
|
-
}
|
|
20924
|
-
const allLabels = lookup.records[0].get("labels");
|
|
20925
|
-
const props = lookup.records[0].get("props");
|
|
20926
|
-
const baseLabels = allLabels.filter((l) => l !== "Trashed");
|
|
20927
|
-
if (allLabels.includes("Trashed")) {
|
|
20928
|
-
return {
|
|
20929
|
-
trashed: false,
|
|
20930
|
-
alreadyTrashed: true,
|
|
20931
|
-
nodeId: elementId,
|
|
20932
|
-
labels: baseLabels,
|
|
20933
|
-
trashedAt: String(props.trashedAt ?? ""),
|
|
20934
|
-
originalKeys: {}
|
|
20935
|
-
};
|
|
20936
|
-
}
|
|
20937
|
-
const uniqueKeys = /* @__PURE__ */ new Set();
|
|
20938
|
-
for (const label of baseLabels) {
|
|
20939
|
-
for (const key of UNIQUE_KEYS_BY_LABEL[label] ?? []) uniqueKeys.add(key);
|
|
20940
|
-
}
|
|
20941
|
-
const originalKeys = {};
|
|
20942
|
-
for (const k of uniqueKeys) {
|
|
20943
|
-
if (props[k] !== void 0 && props[k] !== null) originalKeys[k] = props[k];
|
|
20944
|
-
}
|
|
20945
|
-
const setNullClauses = Object.keys(originalKeys).map((k) => `n.\`${k}\` = null`).join(", ");
|
|
20946
|
-
const setNullSuffix = setNullClauses ? `, ${setNullClauses}` : "";
|
|
20947
|
-
const trashedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
20948
|
-
await session.run(
|
|
20949
|
-
`MATCH (n) WHERE elementId(n) = $eid
|
|
20950
|
-
SET n:Trashed,
|
|
20951
|
-
n.trashedAt = datetime($trashedAt),
|
|
20952
|
-
n.trashedBy = $by,
|
|
20953
|
-
n.trashReason = $reason,
|
|
20954
|
-
n._trashedKeys = $trashedKeysJson${setNullSuffix}`,
|
|
20955
|
-
{
|
|
20956
|
-
eid: elementId,
|
|
20957
|
-
trashedAt,
|
|
20958
|
-
by,
|
|
20959
|
-
reason: reason ?? null,
|
|
20960
|
-
trashedKeysJson: JSON.stringify(originalKeys)
|
|
20961
|
-
}
|
|
20962
|
-
);
|
|
20963
|
-
process.stderr.write(
|
|
20964
|
-
`[trash:marked] accountId=${accountId} elementId=${elementId} labels=${baseLabels.join(",")} by=${by} reason=${reason ?? "null"}
|
|
20965
|
-
`
|
|
20966
|
-
);
|
|
20967
|
-
return {
|
|
20968
|
-
trashed: true,
|
|
20969
|
-
alreadyTrashed: false,
|
|
20970
|
-
nodeId: elementId,
|
|
20971
|
-
labels: baseLabels,
|
|
20972
|
-
trashedAt,
|
|
20973
|
-
originalKeys
|
|
20974
|
-
};
|
|
20975
|
-
}
|
|
20976
|
-
async function restoreNode(params) {
|
|
20977
|
-
const { session, accountId, elementId } = params;
|
|
20978
|
-
const lookup = await session.run(
|
|
20979
|
-
`MATCH (n:Trashed) WHERE elementId(n) = $eid
|
|
20980
|
-
RETURN labels(n) AS labels, n._trashedKeys AS keysJson`,
|
|
20981
|
-
{ eid: elementId }
|
|
20982
|
-
);
|
|
20983
|
-
if (lookup.records.length === 0) {
|
|
20984
|
-
throw new Error(
|
|
20985
|
-
`restoreNode: trashed node not found (elementId=${elementId})`
|
|
20986
|
-
);
|
|
20987
|
-
}
|
|
20988
|
-
const allLabels = lookup.records[0].get("labels");
|
|
20989
|
-
const baseLabels = allLabels.filter((l) => l !== "Trashed");
|
|
20990
|
-
const keysJson = lookup.records[0].get("keysJson");
|
|
20991
|
-
const originalKeys = keysJson ? JSON.parse(keysJson) : {};
|
|
20992
|
-
for (const label of baseLabels) {
|
|
20993
|
-
const uniqueKeys = UNIQUE_KEYS_BY_LABEL[label] ?? [];
|
|
20994
|
-
for (const k of uniqueKeys) {
|
|
20995
|
-
const v = originalKeys[k];
|
|
20996
|
-
if (v === void 0 || v === null) continue;
|
|
20997
|
-
const conflict = await session.run(
|
|
20998
|
-
`MATCH (other:\`${label}\`)
|
|
20999
|
-
WHERE elementId(other) <> $eid
|
|
21000
|
-
AND NOT other:Trashed
|
|
21001
|
-
AND other.\`${k}\` = $val
|
|
21002
|
-
RETURN elementId(other) AS otherId LIMIT 1`,
|
|
21003
|
-
{ eid: elementId, val: v }
|
|
21004
|
-
);
|
|
21005
|
-
if (conflict.records.length > 0) {
|
|
21006
|
-
const otherId = conflict.records[0].get("otherId");
|
|
21007
|
-
throw new Error(
|
|
21008
|
-
`restoreNode: cannot restore ${label} elementId=${elementId} \u2014 active node elementId=${otherId} already holds ${k}=${JSON.stringify(v)}`
|
|
21009
|
-
);
|
|
21010
|
-
}
|
|
21011
|
-
}
|
|
21012
|
-
}
|
|
21013
|
-
const setClauses = Object.keys(originalKeys).map((k) => `n.\`${k}\` = $val_${k}`).join(", ");
|
|
21014
|
-
const setSuffix = setClauses ? `, ${setClauses}` : "";
|
|
21015
|
-
const setParams = { eid: elementId };
|
|
21016
|
-
for (const [k, v] of Object.entries(originalKeys)) setParams[`val_${k}`] = v;
|
|
21017
|
-
await session.run(
|
|
21018
|
-
`MATCH (n:Trashed) WHERE elementId(n) = $eid
|
|
21019
|
-
REMOVE n:Trashed, n.trashedAt, n.trashedBy, n.trashReason, n._trashedKeys
|
|
21020
|
-
SET n.restoredAt = datetime()${setSuffix}`,
|
|
21021
|
-
setParams
|
|
21022
|
-
);
|
|
21023
|
-
process.stderr.write(
|
|
21024
|
-
`[trash:restored] accountId=${accountId} elementId=${elementId} labels=${baseLabels.join(",")}
|
|
21025
|
-
`
|
|
21026
|
-
);
|
|
21027
|
-
return {
|
|
21028
|
-
restored: true,
|
|
21029
|
-
nodeId: elementId,
|
|
21030
|
-
labels: baseLabels,
|
|
21031
|
-
restoredKeys: originalKeys
|
|
21032
|
-
};
|
|
21033
|
-
}
|
|
21034
|
-
|
|
21035
21129
|
// server/routes/admin/graph-delete.ts
|
|
21130
|
+
var ALLOWED_BY = ["graph-page", "graph-drag-trash"];
|
|
21036
21131
|
var app27 = new Hono2();
|
|
21037
21132
|
app27.post("/", requireAdminSession, async (c) => {
|
|
21038
21133
|
const sessionKey = c.var.sessionKey;
|
|
@@ -21049,6 +21144,13 @@ app27.post("/", requireAdminSession, async (c) => {
|
|
|
21049
21144
|
if (!elementId) {
|
|
21050
21145
|
return c.json({ error: "elementId required" }, 400);
|
|
21051
21146
|
}
|
|
21147
|
+
let by = "graph-page";
|
|
21148
|
+
if (body.by !== void 0) {
|
|
21149
|
+
if (typeof body.by !== "string" || !ALLOWED_BY.includes(body.by)) {
|
|
21150
|
+
return c.json({ error: `by must be one of: ${ALLOWED_BY.join(", ")}` }, 400);
|
|
21151
|
+
}
|
|
21152
|
+
by = body.by;
|
|
21153
|
+
}
|
|
21052
21154
|
const started = Date.now();
|
|
21053
21155
|
const session = getSession();
|
|
21054
21156
|
try {
|
|
@@ -21061,7 +21163,7 @@ app27.post("/", requireAdminSession, async (c) => {
|
|
|
21061
21163
|
if (lookup.records.length === 0) {
|
|
21062
21164
|
const elapsed2 = Date.now() - started;
|
|
21063
21165
|
console.error(
|
|
21064
|
-
`[graph-page] delete account=${accountId} elementId=${elementId} labels= result=not-found ms=${elapsed2}`
|
|
21166
|
+
`[graph-page] delete account=${accountId} elementId=${elementId} by=${by} labels= result=not-found ms=${elapsed2}`
|
|
21065
21167
|
);
|
|
21066
21168
|
return c.json({ error: "Node not found" }, 404);
|
|
21067
21169
|
}
|
|
@@ -21070,12 +21172,12 @@ app27.post("/", requireAdminSession, async (c) => {
|
|
|
21070
21172
|
session,
|
|
21071
21173
|
accountId,
|
|
21072
21174
|
elementId,
|
|
21073
|
-
by
|
|
21175
|
+
by
|
|
21074
21176
|
});
|
|
21075
21177
|
const elapsed = Date.now() - started;
|
|
21076
21178
|
const labelSummary = (result.labels.length > 0 ? result.labels : preflightLabels).join(",");
|
|
21077
21179
|
console.error(
|
|
21078
|
-
`[graph-page] delete account=${accountId} elementId=${elementId} labels=${labelSummary} result=ok ms=${elapsed}`
|
|
21180
|
+
`[graph-page] delete account=${accountId} elementId=${elementId} by=${by} labels=${labelSummary} result=ok ms=${elapsed}`
|
|
21079
21181
|
);
|
|
21080
21182
|
const response = {
|
|
21081
21183
|
elementId: result.nodeId,
|
|
@@ -21088,7 +21190,7 @@ app27.post("/", requireAdminSession, async (c) => {
|
|
|
21088
21190
|
const elapsed = Date.now() - started;
|
|
21089
21191
|
const message = err instanceof Error ? err.message : String(err);
|
|
21090
21192
|
console.error(
|
|
21091
|
-
`[graph-page] delete account=${accountId} elementId=${elementId} labels= result=error ms=${elapsed} err="${message}"`
|
|
21193
|
+
`[graph-page] delete account=${accountId} elementId=${elementId} by=${by} labels= result=error ms=${elapsed} err="${message}"`
|
|
21092
21194
|
);
|
|
21093
21195
|
return c.json({ error: `Delete failed: ${message}` }, 503);
|
|
21094
21196
|
} finally {
|