@rubytech/create-maxy 1.0.651 → 1.0.653
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/dist/index.js +115 -6
- package/dist/pinned-binaries.js +43 -0
- package/package.json +1 -1
- package/payload/platform/lib/graph-trash/dist/index.d.ts +91 -0
- package/payload/platform/lib/graph-trash/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/graph-trash/dist/index.js +238 -0
- package/payload/platform/lib/graph-trash/dist/index.js.map +1 -0
- package/payload/platform/lib/graph-trash/src/index.ts +360 -0
- package/payload/platform/lib/graph-trash/tsconfig.json +8 -0
- package/payload/platform/neo4j/schema.cypher +19 -0
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/cloudflare/scripts/_stream-log.sh +19 -4
- package/payload/platform/plugins/cloudflare/scripts/list-cf-domains.ts +162 -63
- package/payload/platform/plugins/contacts/mcp/dist/index.js +9 -4
- package/payload/platform/plugins/contacts/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-delete.d.ts +16 -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 +23 -10
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-delete.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.d.ts.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.js +2 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.d.ts.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js +8 -4
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js.map +1 -1
- package/payload/platform/plugins/docs/references/deployment.md +1 -1
- package/payload/platform/plugins/docs/references/platform.md +3 -1
- package/payload/platform/plugins/docs/references/plugins-guide.md +1 -1
- package/payload/platform/plugins/docs/references/troubleshooting.md +43 -0
- package/payload/platform/plugins/memory/PLUGIN.md +4 -2
- package/payload/platform/plugins/memory/mcp/dist/index.js +92 -28
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.d.ts +30 -15
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js +46 -84
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.d.ts +22 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.js +36 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +16 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-list-attachments.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-list-attachments.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-list-attachments.js +42 -3
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-list-attachments.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-restore.d.ts +24 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-restore.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-restore.js +40 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-restore.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js +35 -10
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js.map +1 -1
- package/payload/platform/plugins/memory/references/graph-primitives.md +49 -3
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +4 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
- package/payload/platform/scripts/lib/resolve-account-dir.sh +166 -0
- package/payload/platform/scripts/seed-neo4j.sh +7 -11
- package/payload/platform/templates/systemd/maxy-ttyd.service +6 -1
- package/payload/server/public/assets/{admin-S2KHPNe4.js → admin-DLp3geZN.js} +4 -4
- package/payload/server/public/assets/data-DPqrIvgB.js +1 -0
- package/payload/server/public/assets/{file-CRrDfnO1.js → file-Buaz89w8.js} +1 -1
- package/payload/server/public/assets/{graph-CSBMZGGe.js → graph-B_TxtKJP.js} +2 -2
- package/payload/server/public/assets/{house-D1CBraxB.js → house-B5wS-2kc.js} +1 -1
- package/payload/server/public/assets/jsx-runtime-ChVPhhAG.css +1 -0
- package/payload/server/public/assets/{public-ukz9-gSe.js → public-BNEciseE.js} +1 -1
- package/payload/server/public/assets/{share-2-DkF8neDM.js → share-2-Z5v9aWZ2.js} +1 -1
- package/payload/server/public/assets/{trash-2-Dde58AAR.js → trash-2-BaLFnigq.js} +1 -1
- package/payload/server/public/assets/{useVoiceRecorder-Hz9X6luB.js → useVoiceRecorder-CgMo3FDt.js} +1 -1
- package/payload/server/public/assets/x-DYxtrMFK.js +1 -0
- package/payload/server/public/data.html +7 -7
- package/payload/server/public/graph.html +6 -6
- package/payload/server/public/index.html +8 -8
- package/payload/server/public/public.html +5 -5
- package/payload/server/server.js +33 -0
- package/payload/server/public/assets/data-BajF3t1i.js +0 -1
- package/payload/server/public/assets/jsx-runtime-CZtLX8NN.css +0 -1
- package/payload/server/public/assets/x-D52qhSya.js +0 -1
- /package/payload/server/public/assets/{jsx-runtime-Cb-WunFZ.js → jsx-runtime-WYScGBOd.js} +0 -0
|
@@ -1,98 +1,60 @@
|
|
|
1
1
|
import { getSession } from "../lib/neo4j.js";
|
|
2
|
-
import {
|
|
3
|
-
import { softDeleteDocument, deleteDocumentChildren, deleteDocumentNode, } from "../lib/document-hierarchy.js";
|
|
4
|
-
// ---------------------------------------------------------------------------
|
|
5
|
-
// memory-delete — remove a KnowledgeDocument from the knowledge graph.
|
|
6
|
-
//
|
|
7
|
-
// Two modes:
|
|
8
|
-
// soft (default) — sets deletedAt on the document and all children.
|
|
9
|
-
// Nodes remain in the graph but are excluded from
|
|
10
|
-
// memory-search. A future hard delete purges them.
|
|
11
|
-
// hard (force) — cascade-deletes all children, the document node,
|
|
12
|
-
// and the attachment directory from disk.
|
|
13
|
-
//
|
|
14
|
-
// FIND DOC --> SOFT? --> SET deletedAt (doc + children)
|
|
15
|
-
// │
|
|
16
|
-
// └── HARD? --> DELETE children --> DELETE doc --> DELETE disk
|
|
17
|
-
// ---------------------------------------------------------------------------
|
|
18
|
-
const GRACE_PERIOD_DAYS = 7;
|
|
2
|
+
import { trashNode } from "../../../../../lib/graph-trash/dist/index.js";
|
|
19
3
|
export async function memoryDelete(params) {
|
|
20
|
-
const { accountId,
|
|
21
|
-
assertUUID(attachmentId, "attachmentId");
|
|
22
|
-
const t0 = Date.now();
|
|
23
|
-
const tag = attachmentId.slice(0, 8);
|
|
24
|
-
const log = (stage, detail) => console.error(`[memory-delete] [${tag}] ${stage}${detail ? ` — ${detail}` : ""} (${Date.now() - t0}ms)`);
|
|
4
|
+
const { accountId, elementId, reason } = params;
|
|
25
5
|
const session = getSession();
|
|
26
6
|
try {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
7
|
+
const root = await trashNode({
|
|
8
|
+
session,
|
|
9
|
+
accountId,
|
|
10
|
+
elementId,
|
|
11
|
+
by: "memory-delete",
|
|
12
|
+
reason,
|
|
13
|
+
});
|
|
14
|
+
let sections = 0;
|
|
15
|
+
let chunks = 0;
|
|
16
|
+
if (root.labels.includes("KnowledgeDocument")) {
|
|
17
|
+
const childResult = await session.run(`MATCH (d) WHERE elementId(d) = $eid
|
|
18
|
+
OPTIONAL MATCH (d)-[:HAS_SECTION]->(s:Section)
|
|
19
|
+
OPTIONAL MATCH (s)-[:HAS_CHUNK]->(c:Chunk)
|
|
20
|
+
WITH collect(DISTINCT s) AS sections, collect(DISTINCT c) AS chunks
|
|
21
|
+
RETURN [s IN sections WHERE s IS NOT NULL | elementId(s)] AS sectionIds,
|
|
22
|
+
[c IN chunks WHERE c IS NOT NULL | elementId(c)] AS chunkIds`, { eid: elementId });
|
|
23
|
+
const sectionIds = childResult.records[0]?.get("sectionIds") ?? [];
|
|
24
|
+
const chunkIds = childResult.records[0]?.get("chunkIds") ?? [];
|
|
25
|
+
for (const sid of sectionIds) {
|
|
26
|
+
const r = await trashNode({
|
|
27
|
+
session,
|
|
28
|
+
accountId,
|
|
29
|
+
elementId: sid,
|
|
30
|
+
by: `memory-delete:cascade-from-${elementId}`,
|
|
31
|
+
reason: reason ?? `cascade from KnowledgeDocument ${elementId}`,
|
|
32
|
+
});
|
|
33
|
+
if (r.trashed)
|
|
34
|
+
sections++;
|
|
35
|
+
}
|
|
36
|
+
for (const cid of chunkIds) {
|
|
37
|
+
const r = await trashNode({
|
|
38
|
+
session,
|
|
39
|
+
accountId,
|
|
40
|
+
elementId: cid,
|
|
41
|
+
by: `memory-delete:cascade-from-${elementId}`,
|
|
42
|
+
reason: reason ?? `cascade from KnowledgeDocument ${elementId}`,
|
|
43
|
+
});
|
|
44
|
+
if (r.trashed)
|
|
45
|
+
chunks++;
|
|
49
46
|
}
|
|
50
|
-
const now = new Date();
|
|
51
|
-
const deletedAt = now.toISOString();
|
|
52
|
-
const purgeDate = new Date(now);
|
|
53
|
-
purgeDate.setDate(purgeDate.getDate() + GRACE_PERIOD_DAYS);
|
|
54
|
-
const purgeAfter = purgeDate.toISOString();
|
|
55
|
-
const result = await softDeleteDocument(attachmentId, deletedAt, session);
|
|
56
|
-
log("soft-deleted", `doc=${result.document} sections=${result.sections} chunks=${result.chunks} — grace period: ${GRACE_PERIOD_DAYS} days, purge after: ${purgeAfter.slice(0, 10)}`);
|
|
57
|
-
return {
|
|
58
|
-
mode: "soft",
|
|
59
|
-
attachmentId,
|
|
60
|
-
document: result.document,
|
|
61
|
-
sections: result.sections,
|
|
62
|
-
chunks: result.chunks,
|
|
63
|
-
references: 0,
|
|
64
|
-
diskRemoved: false,
|
|
65
|
-
deletedAt,
|
|
66
|
-
purgeAfter,
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
// Hard delete (force)
|
|
70
|
-
log("hard-delete", "starting cascade");
|
|
71
|
-
const cascade = await deleteDocumentChildren(attachmentId, session);
|
|
72
|
-
log("cascade", `sections=${cascade.sections} chunks=${cascade.chunks} references=${cascade.references}`);
|
|
73
|
-
const docDeleted = await deleteDocumentNode(attachmentId, session);
|
|
74
|
-
log("document-deleted", docDeleted ? "removed" : "already absent");
|
|
75
|
-
// Remove files from disk (no-op for web-ingested documents)
|
|
76
|
-
const diskRemoved = await removeAttachmentDir(accountId, attachmentId);
|
|
77
|
-
if (diskRemoved) {
|
|
78
|
-
log("disk-removed", `${accountId}/${attachmentId}/`);
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
log("disk-skipped", "no attachment directory on disk");
|
|
82
47
|
}
|
|
83
48
|
return {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
references: cascade.references,
|
|
90
|
-
diskRemoved,
|
|
49
|
+
elementId,
|
|
50
|
+
labels: root.labels,
|
|
51
|
+
trashedAt: root.trashedAt,
|
|
52
|
+
alreadyTrashed: root.alreadyTrashed,
|
|
53
|
+
cascade: { sections, chunks },
|
|
91
54
|
};
|
|
92
55
|
}
|
|
93
56
|
finally {
|
|
94
57
|
await session.close();
|
|
95
|
-
log("complete");
|
|
96
58
|
}
|
|
97
59
|
}
|
|
98
60
|
//# sourceMappingURL=memory-delete.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-delete.js","sourceRoot":"","sources":["../../src/tools/memory-delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,
|
|
1
|
+
{"version":3,"file":"memory-delete.js","sourceRoot":"","sources":["../../src/tools/memory-delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAoB,MAAM,8CAA8C,CAAC;AAkC3F,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAA0B;IAE1B,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAChD,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,MAAM,IAAI,GAAgB,MAAM,SAAS,CAAC;YACxC,OAAO;YACP,SAAS;YACT,SAAS;YACT,EAAE,EAAE,eAAe;YACnB,MAAM;SACP,CAAC,CAAC;QAEH,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,MAAM,GAAG,CAAC,CAAC;QAEf,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC9C,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,GAAG,CACnC;;;;;+EAKuE,EACvE,EAAE,GAAG,EAAE,SAAS,EAAE,CACnB,CAAC;YACF,MAAM,UAAU,GAAI,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,YAAY,CAAc,IAAI,EAAE,CAAC;YACjF,MAAM,QAAQ,GAAI,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,UAAU,CAAc,IAAI,EAAE,CAAC;YAE7E,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;gBAC7B,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC;oBACxB,OAAO;oBACP,SAAS;oBACT,SAAS,EAAE,GAAG;oBACd,EAAE,EAAE,8BAA8B,SAAS,EAAE;oBAC7C,MAAM,EAAE,MAAM,IAAI,kCAAkC,SAAS,EAAE;iBAChE,CAAC,CAAC;gBACH,IAAI,CAAC,CAAC,OAAO;oBAAE,QAAQ,EAAE,CAAC;YAC5B,CAAC;YACD,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;gBAC3B,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC;oBACxB,OAAO;oBACP,SAAS;oBACT,SAAS,EAAE,GAAG;oBACd,EAAE,EAAE,8BAA8B,SAAS,EAAE;oBAC7C,MAAM,EAAE,MAAM,IAAI,kCAAkC,SAAS,EAAE;iBAChE,CAAC,CAAC;gBACH,IAAI,CAAC,CAAC,OAAO;oBAAE,MAAM,EAAE,CAAC;YAC1B,CAAC;QACH,CAAC;QAED,OAAO;YACL,SAAS;YACT,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE;SAC9B,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type EmptyTrashResult } from "../../../../../lib/graph-trash/dist/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* memory-empty-trash — hard-delete trashed nodes whose `trashedAt` is older
|
|
4
|
+
* than the grace period. For `KnowledgeDocument` candidates, also removes the
|
|
5
|
+
* on-disk attachment directory (snapshotted `attachmentId` is read from
|
|
6
|
+
* `_trashedKeys`).
|
|
7
|
+
*
|
|
8
|
+
* Defaults: `graceDays=30`, `dryRun=false`, no label filter. `dryRun=true`
|
|
9
|
+
* lists candidates without mutating; the absence of `[trash:emptied]` lines
|
|
10
|
+
* after a `dryRun=true` `[trash:empty-run]` is the correct-behaviour signal.
|
|
11
|
+
*/
|
|
12
|
+
export interface MemoryEmptyTrashParams {
|
|
13
|
+
accountId: string;
|
|
14
|
+
graceDays?: number;
|
|
15
|
+
dryRun?: boolean;
|
|
16
|
+
labels?: string[];
|
|
17
|
+
}
|
|
18
|
+
export interface MemoryEmptyTrashResult extends EmptyTrashResult {
|
|
19
|
+
attachmentDirsRemoved: number;
|
|
20
|
+
}
|
|
21
|
+
export declare function memoryEmptyTrash(params: MemoryEmptyTrashParams): Promise<MemoryEmptyTrashResult>;
|
|
22
|
+
//# sourceMappingURL=memory-empty-trash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-empty-trash.d.ts","sourceRoot":"","sources":["../../src/tools/memory-empty-trash.ts"],"names":[],"mappings":"AACA,OAAO,EAAmC,KAAK,gBAAgB,EAAE,MAAM,8CAA8C,CAAC;AAGtH;;;;;;;;;GASG;AAEH,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;IAC9D,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAED,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,sBAAsB,GAC7B,OAAO,CAAC,sBAAsB,CAAC,CAgCjC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { getSession } from "../lib/neo4j.js";
|
|
2
|
+
import { emptyTrash } from "../../../../../lib/graph-trash/dist/index.js";
|
|
3
|
+
import { removeAttachmentDir } from "../lib/attachments.js";
|
|
4
|
+
export async function memoryEmptyTrash(params) {
|
|
5
|
+
const { accountId, graceDays, dryRun, labels } = params;
|
|
6
|
+
const session = getSession();
|
|
7
|
+
let attachmentDirsRemoved = 0;
|
|
8
|
+
try {
|
|
9
|
+
const result = await emptyTrash({
|
|
10
|
+
session,
|
|
11
|
+
accountId,
|
|
12
|
+
graceDays,
|
|
13
|
+
dryRun,
|
|
14
|
+
labels,
|
|
15
|
+
onEmpty: async (c) => {
|
|
16
|
+
if (!c.labels.includes("KnowledgeDocument"))
|
|
17
|
+
return;
|
|
18
|
+
const aid = typeof c.trashedKeys.attachmentId === "string"
|
|
19
|
+
? c.trashedKeys.attachmentId
|
|
20
|
+
: null;
|
|
21
|
+
if (!aid)
|
|
22
|
+
return;
|
|
23
|
+
const removed = await removeAttachmentDir(accountId, aid);
|
|
24
|
+
if (removed) {
|
|
25
|
+
attachmentDirsRemoved++;
|
|
26
|
+
process.stderr.write(`[trash:emptied:disk] accountId=${accountId} attachmentId=${aid}\n`);
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
return { ...result, attachmentDirsRemoved };
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
await session.close();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=memory-empty-trash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-empty-trash.js","sourceRoot":"","sources":["../../src/tools/memory-empty-trash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAA8C,MAAM,8CAA8C,CAAC;AACtH,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAwB5D,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAA8B;IAE9B,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IACxD,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,IAAI,qBAAqB,GAAG,CAAC,CAAC;IAE9B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;YAC9B,OAAO;YACP,SAAS;YACT,SAAS;YACT,MAAM;YACN,MAAM;YACN,OAAO,EAAE,KAAK,EAAE,CAAiB,EAAE,EAAE;gBACnC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC;oBAAE,OAAO;gBACpD,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,WAAW,CAAC,YAAY,KAAK,QAAQ;oBACxD,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,YAAY;oBAC5B,CAAC,CAAC,IAAI,CAAC;gBACT,IAAI,CAAC,GAAG;oBAAE,OAAO;gBACjB,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;gBAC1D,IAAI,OAAO,EAAE,CAAC;oBACZ,qBAAqB,EAAE,CAAC;oBACxB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,kCAAkC,SAAS,iBAAiB,GAAG,IAAI,CACpE,CAAC;gBACJ,CAAC;YACH,CAAC;SACF,CAAC,CAAC;QAEH,OAAO,EAAE,GAAG,MAAM,EAAE,qBAAqB,EAAE,CAAC;IAC9C,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-ingest.d.ts","sourceRoot":"","sources":["../../src/tools/memory-ingest.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"memory-ingest.d.ts","sourceRoot":"","sources":["../../src/tools/memory-ingest.ts"],"names":[],"mappings":"AAyBA,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,oBAAoB,EAAE,CAAC;IACjC,8EAA8E;IAC9E,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,KAAK,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;IACH,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kGAAkG;IAClG,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,uKAAuK;IACvK,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAwT9E"}
|
|
@@ -2,6 +2,7 @@ import { getSession } from "../lib/neo4j.js";
|
|
|
2
2
|
import { embedBatch } from "../lib/embeddings.js";
|
|
3
3
|
import { extractCache } from "./memory-ingest-extract.js";
|
|
4
4
|
import { deleteDocumentChildren } from "../lib/document-hierarchy.js";
|
|
5
|
+
import { restoreNode } from "../../../../../lib/graph-trash/dist/index.js";
|
|
5
6
|
export async function memoryIngest(params) {
|
|
6
7
|
const { accountId, attachmentId, documentSummary, sections, scope, entities, sourceUrl, sourceType, keywords: rawKeywords, userKeywords: rawUserKeywords, } = params;
|
|
7
8
|
if (!scope) {
|
|
@@ -101,6 +102,21 @@ export async function memoryIngest(params) {
|
|
|
101
102
|
const optionalSetClause = optionalSets.length > 0
|
|
102
103
|
? ", " + optionalSets.join(", ")
|
|
103
104
|
: "";
|
|
105
|
+
// Trash recovery: a prior memory-delete on this attachmentId nulls the
|
|
106
|
+
// live attachmentId (Task 576 unique-key handling). MERGE on
|
|
107
|
+
// attachmentId would then create a NEW node, orphaning the trashed copy
|
|
108
|
+
// — and 30 days later memory-empty-trash would purge the disk dir the
|
|
109
|
+
// new node depends on. Restore first so MERGE finds the existing node.
|
|
110
|
+
const trashedDoc = await session.run(`MATCH (d:KnowledgeDocument:Trashed)
|
|
111
|
+
WHERE d.accountId = $accountId
|
|
112
|
+
AND d._trashedKeys IS NOT NULL
|
|
113
|
+
AND d._trashedKeys CONTAINS $attachmentId
|
|
114
|
+
RETURN elementId(d) AS eid LIMIT 1`, { accountId, attachmentId });
|
|
115
|
+
if (trashedDoc.records.length > 0) {
|
|
116
|
+
const eid = trashedDoc.records[0].get("eid");
|
|
117
|
+
await restoreNode({ session, accountId, elementId: eid });
|
|
118
|
+
log("revived", `restored trashed KnowledgeDocument elementId=${eid}`);
|
|
119
|
+
}
|
|
104
120
|
const docResult = await session.run(`MERGE (d:KnowledgeDocument { attachmentId: $attachmentId })
|
|
105
121
|
SET d.accountId = $accountId,
|
|
106
122
|
d.name = $filename,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-ingest.js","sourceRoot":"","sources":["../../src/tools/memory-ingest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"memory-ingest.js","sourceRoot":"","sources":["../../src/tools/memory-ingest.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export interface AttachmentEntry {
|
|
2
2
|
attachmentId: string;
|
|
3
|
+
/** Neo4j elementId of the KnowledgeDocument node — pass to memory-delete / memory-restore. Null when not yet ingested. */
|
|
4
|
+
elementId: string | null;
|
|
3
5
|
filename: string;
|
|
4
6
|
mimeType: string;
|
|
5
7
|
sizeBytes: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-list-attachments.d.ts","sourceRoot":"","sources":["../../src/tools/memory-list-attachments.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,UAAU,CAAC,
|
|
1
|
+
{"version":3,"file":"memory-list-attachments.d.ts","sourceRoot":"","sources":["../../src/tools/memory-list-attachments.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,0HAA0H;IAC1H,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,UAAU,CAAC,CAkJrB"}
|
|
@@ -27,6 +27,7 @@ export async function memoryListAttachments(accountId) {
|
|
|
27
27
|
const meta = JSON.parse(raw);
|
|
28
28
|
entries.push({
|
|
29
29
|
attachmentId: meta.attachmentId,
|
|
30
|
+
elementId: null,
|
|
30
31
|
filename: meta.filename,
|
|
31
32
|
mimeType: meta.mimeType,
|
|
32
33
|
sizeBytes: meta.sizeBytes,
|
|
@@ -48,16 +49,53 @@ export async function memoryListAttachments(accountId) {
|
|
|
48
49
|
const session = getSession();
|
|
49
50
|
try {
|
|
50
51
|
const attachmentIds = entries.map((e) => e.attachmentId);
|
|
52
|
+
// Include trashed nodes — their attachmentId is nulled on trash, so match
|
|
53
|
+
// via _trashedKeys JSON snapshot too. softDeleted flag covers both legacy
|
|
54
|
+
// deletedAt and Task 576 :Trashed forms.
|
|
51
55
|
const result = await session.run(`MATCH (k:KnowledgeDocument { accountId: $accountId })
|
|
52
56
|
WHERE k.attachmentId IN $attachmentIds
|
|
53
|
-
RETURN k.attachmentId AS aid,
|
|
57
|
+
RETURN k.attachmentId AS aid,
|
|
58
|
+
elementId(k) AS elementId,
|
|
59
|
+
k.deletedAt AS deletedAt,
|
|
60
|
+
false AS trashed
|
|
61
|
+
UNION
|
|
62
|
+
MATCH (k:KnowledgeDocument:Trashed)
|
|
63
|
+
WHERE k._trashedKeys IS NOT NULL
|
|
64
|
+
AND ANY(aid IN $attachmentIds WHERE k._trashedKeys CONTAINS aid)
|
|
65
|
+
RETURN coalesce(k.attachmentId, '') AS aid,
|
|
66
|
+
elementId(k) AS elementId,
|
|
67
|
+
null AS deletedAt,
|
|
68
|
+
true AS trashed`, { accountId, attachmentIds });
|
|
69
|
+
// Build a lookup keyed by attachmentId. For trashed rows we recover the
|
|
70
|
+
// original attachmentId out of the JSON snapshot on the client — we don't
|
|
71
|
+
// parse JSON in Cypher for portability.
|
|
54
72
|
const ingestionMap = new Map();
|
|
55
73
|
for (const record of result.records) {
|
|
56
|
-
const
|
|
74
|
+
const elementId = record.get("elementId");
|
|
57
75
|
const deletedAt = record.get("deletedAt");
|
|
76
|
+
const trashed = record.get("trashed");
|
|
77
|
+
let aid = record.get("aid");
|
|
78
|
+
if (trashed) {
|
|
79
|
+
// Recover attachmentId from _trashedKeys — look it up via a targeted read.
|
|
80
|
+
const snap = await session.run(`MATCH (k) WHERE elementId(k) = $eid RETURN k._trashedKeys AS keysJson`, { eid: elementId });
|
|
81
|
+
const keysJson = snap.records[0]?.get("keysJson");
|
|
82
|
+
if (keysJson) {
|
|
83
|
+
try {
|
|
84
|
+
const parsed = JSON.parse(keysJson);
|
|
85
|
+
if (typeof parsed.attachmentId === "string")
|
|
86
|
+
aid = parsed.attachmentId;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// Malformed snapshot — skip.
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (!aid || !attachmentIds.includes(aid))
|
|
94
|
+
continue;
|
|
58
95
|
ingestionMap.set(aid, {
|
|
59
96
|
ingested: true,
|
|
60
|
-
softDeleted: deletedAt != null,
|
|
97
|
+
softDeleted: trashed || deletedAt != null,
|
|
98
|
+
elementId,
|
|
61
99
|
});
|
|
62
100
|
}
|
|
63
101
|
let ingestedCount = 0;
|
|
@@ -66,6 +104,7 @@ export async function memoryListAttachments(accountId) {
|
|
|
66
104
|
if (status) {
|
|
67
105
|
entry.ingested = status.ingested;
|
|
68
106
|
entry.softDeleted = status.softDeleted;
|
|
107
|
+
entry.elementId = status.elementId;
|
|
69
108
|
ingestedCount++;
|
|
70
109
|
}
|
|
71
110
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-list-attachments.js","sourceRoot":"","sources":["../../src/tools/memory-list-attachments.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EACL,gBAAgB,GAEjB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"memory-list-attachments.js","sourceRoot":"","sources":["../../src/tools/memory-list-attachments.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* memory-restore — undo a `memory-delete`. Removes the `:Trashed` label,
|
|
3
|
+
* restores snapshotted unique-key properties, and walks `HAS_SECTION` /
|
|
4
|
+
* `HAS_CHUNK` edges so a restored `KnowledgeDocument` brings its trashed
|
|
5
|
+
* `Section` and `Chunk` children back with it.
|
|
6
|
+
*
|
|
7
|
+
* Fails loudly when an active node already holds a unique slot the trashed
|
|
8
|
+
* node needs back (e.g. a fresh `OnboardingState` was MERGEd while the old
|
|
9
|
+
* one was in trash) — the helper names the conflicting elementId.
|
|
10
|
+
*/
|
|
11
|
+
export interface MemoryRestoreParams {
|
|
12
|
+
accountId: string;
|
|
13
|
+
elementId: string;
|
|
14
|
+
}
|
|
15
|
+
export interface MemoryRestoreResult {
|
|
16
|
+
elementId: string;
|
|
17
|
+
labels: string[];
|
|
18
|
+
cascade: {
|
|
19
|
+
sections: number;
|
|
20
|
+
chunks: number;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export declare function memoryRestore(params: MemoryRestoreParams): Promise<MemoryRestoreResult>;
|
|
24
|
+
//# sourceMappingURL=memory-restore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-restore.d.ts","sourceRoot":"","sources":["../../src/tools/memory-restore.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AAEH,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/C;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CA2C9B"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { getSession } from "../lib/neo4j.js";
|
|
2
|
+
import { restoreNode } from "../../../../../lib/graph-trash/dist/index.js";
|
|
3
|
+
export async function memoryRestore(params) {
|
|
4
|
+
const { accountId, elementId } = params;
|
|
5
|
+
const session = getSession();
|
|
6
|
+
try {
|
|
7
|
+
const root = await restoreNode({ session, accountId, elementId });
|
|
8
|
+
let sections = 0;
|
|
9
|
+
let chunks = 0;
|
|
10
|
+
if (root.labels.includes("KnowledgeDocument")) {
|
|
11
|
+
const childResult = await session.run(`MATCH (d) WHERE elementId(d) = $eid
|
|
12
|
+
OPTIONAL MATCH (d)-[:HAS_SECTION]->(s:Section)
|
|
13
|
+
WHERE s:Trashed
|
|
14
|
+
OPTIONAL MATCH (s)-[:HAS_CHUNK]->(c:Chunk)
|
|
15
|
+
WHERE c:Trashed
|
|
16
|
+
WITH collect(DISTINCT s) AS sections, collect(DISTINCT c) AS chunks
|
|
17
|
+
RETURN [s IN sections WHERE s IS NOT NULL | elementId(s)] AS sectionIds,
|
|
18
|
+
[c IN chunks WHERE c IS NOT NULL | elementId(c)] AS chunkIds`, { eid: elementId });
|
|
19
|
+
const sectionIds = childResult.records[0]?.get("sectionIds") ?? [];
|
|
20
|
+
const chunkIds = childResult.records[0]?.get("chunkIds") ?? [];
|
|
21
|
+
for (const sid of sectionIds) {
|
|
22
|
+
await restoreNode({ session, accountId, elementId: sid });
|
|
23
|
+
sections++;
|
|
24
|
+
}
|
|
25
|
+
for (const cid of chunkIds) {
|
|
26
|
+
await restoreNode({ session, accountId, elementId: cid });
|
|
27
|
+
chunks++;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
elementId,
|
|
32
|
+
labels: root.labels,
|
|
33
|
+
cascade: { sections, chunks },
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
finally {
|
|
37
|
+
await session.close();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=memory-restore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-restore.js","sourceRoot":"","sources":["../../src/tools/memory-restore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAsB,MAAM,8CAA8C,CAAC;AAwB/F,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAA2B;IAE3B,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IACxC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,MAAM,IAAI,GAAkB,MAAM,WAAW,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;QAEjF,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,MAAM,GAAG,CAAC,CAAC;QAEf,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC9C,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,GAAG,CACnC;;;;;;;+EAOuE,EACvE,EAAE,GAAG,EAAE,SAAS,EAAE,CACnB,CAAC;YACF,MAAM,UAAU,GAAI,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,YAAY,CAAc,IAAI,EAAE,CAAC;YACjF,MAAM,QAAQ,GAAI,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,UAAU,CAAc,IAAI,EAAE,CAAC;YAE7E,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;gBAC7B,MAAM,WAAW,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;gBAC1D,QAAQ,EAAE,CAAC;YACb,CAAC;YACD,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;gBAC3B,MAAM,WAAW,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;gBAC1D,MAAM,EAAE,CAAC;YACX,CAAC;QACH,CAAC;QAED,OAAO;YACL,SAAS;YACT,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE;SAC9B,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-search.d.ts","sourceRoot":"","sources":["../../src/tools/memory-search.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"memory-search.d.ts","sourceRoot":"","sources":["../../src/tools/memory-search.ts"],"names":[],"mappings":"AA6BA,UAAU,YAAY;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mHAAmH;IACnH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,uLAAuL;IACvL,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,6FAA6F;IAC7F,YAAY,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IAC7B,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2FAA2F;IAC3F,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED,UAAU,YAAY;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,KAAK,CAAC;QACb,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACrC,CAAC,CAAC;CACJ;AAiCD,yDAAyD;AACzD,wBAAgB,eAAe,IAAI,IAAI,CAEtC;AAsFD,wBAAsB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAgThF"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { int } from "neo4j-driver";
|
|
2
2
|
import { getSession } from "../lib/neo4j.js";
|
|
3
3
|
import { embed } from "../lib/embeddings.js";
|
|
4
|
+
import { notTrashed } from "../../../../../lib/graph-trash/dist/index.js";
|
|
4
5
|
// ---------------------------------------------------------------------------
|
|
5
6
|
// Hybrid search pipeline:
|
|
6
7
|
//
|
|
@@ -13,9 +14,12 @@ import { embed } from "../lib/embeddings.js";
|
|
|
13
14
|
// Deduplicate by nodeId, taking the higher combined score.
|
|
14
15
|
// Fall back to vector-only if the full-text index doesn't exist.
|
|
15
16
|
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
17
|
+
// Trashed nodes (Task 576 :Trashed label) and legacy soft-deleted nodes
|
|
18
|
+
// (pre-Task-576 deletedAt property) are excluded from ALL query paths via
|
|
19
|
+
// the shared notTrashed() helper: vector search, BM25, property keyword
|
|
20
|
+
// search, and graph expand. The filter is unconditional — no parameter
|
|
21
|
+
// controls it. When the filter drops results, [trash:read-filter-skipped]
|
|
22
|
+
// is emitted so silent over-filtering is observable.
|
|
19
23
|
// ---------------------------------------------------------------------------
|
|
20
24
|
const VECTOR_WEIGHT = 0.7;
|
|
21
25
|
const BM25_WEIGHT = 0.3;
|
|
@@ -63,7 +67,6 @@ async function bm25Search(queryText, accountId, limit, allowedScopes, keywordFil
|
|
|
63
67
|
const agentClause = agentSlug
|
|
64
68
|
? "AND node.agents IS NOT NULL AND $agentSlug IN node.agents"
|
|
65
69
|
: "";
|
|
66
|
-
const deletedAtClause = "AND node.deletedAt IS NULL";
|
|
67
70
|
const kwClause = keywordFilter?.clause ?? "";
|
|
68
71
|
// Escape Lucene special characters in the query
|
|
69
72
|
const escaped = queryText.replace(/[+\-&|!(){}[\]^"~*?:\\/]/g, "\\$&");
|
|
@@ -72,7 +75,7 @@ async function bm25Search(queryText, accountId, limit, allowedScopes, keywordFil
|
|
|
72
75
|
WHERE node.accountId = $accountId
|
|
73
76
|
${scopeClause}
|
|
74
77
|
${agentClause}
|
|
75
|
-
${
|
|
78
|
+
AND ${notTrashed("node")}
|
|
76
79
|
${kwClause}
|
|
77
80
|
RETURN node, score, labels(node) AS nodeLabels, elementId(node) AS nodeId
|
|
78
81
|
ORDER BY score DESC
|
|
@@ -160,8 +163,9 @@ export async function memorySearch(params) {
|
|
|
160
163
|
? "AND node.agents IS NOT NULL AND $agentSlug IN node.agents"
|
|
161
164
|
: "";
|
|
162
165
|
const agentParams = agentSlug ? { agentSlug } : {};
|
|
163
|
-
// Unconditional soft-delete filter — nodes
|
|
164
|
-
|
|
166
|
+
// Unconditional soft-delete filter — :Trashed nodes (Task 576) and legacy
|
|
167
|
+
// deletedAt-marked nodes are never returned. notTrashed() centralises the
|
|
168
|
+
// predicate so a future migration drops the legacy arm in one place.
|
|
165
169
|
for (const indexName of indexesToQuery) {
|
|
166
170
|
const vectorQuery = `
|
|
167
171
|
CALL db.index.vector.queryNodes($indexName, $limit, $embedding)
|
|
@@ -169,7 +173,7 @@ export async function memorySearch(params) {
|
|
|
169
173
|
WHERE node.accountId = $accountId
|
|
170
174
|
${scopeClause}
|
|
171
175
|
${agentClause}
|
|
172
|
-
${
|
|
176
|
+
AND ${notTrashed("node")}
|
|
173
177
|
${keywordClause}
|
|
174
178
|
RETURN node, score, labels(node) AS nodeLabels, elementId(node) AS nodeId
|
|
175
179
|
ORDER BY score DESC
|
|
@@ -274,7 +278,7 @@ export async function memorySearch(params) {
|
|
|
274
278
|
: "";
|
|
275
279
|
const propResult = await session.run(`MATCH (node)
|
|
276
280
|
WHERE node.accountId = $accountId
|
|
277
|
-
AND node
|
|
281
|
+
AND ${notTrashed("node")}
|
|
278
282
|
AND node.keywords IS NOT NULL
|
|
279
283
|
AND ANY(kw IN $kwSubs WHERE ANY(nk IN node.keywords WHERE toLower(nk) = kw))
|
|
280
284
|
${propScopeClause}
|
|
@@ -332,7 +336,7 @@ export async function memorySearch(params) {
|
|
|
332
336
|
const expandQuery = `
|
|
333
337
|
MATCH (n)-[r]-(related)
|
|
334
338
|
WHERE elementId(n) = $nodeId
|
|
335
|
-
AND related
|
|
339
|
+
AND ${notTrashed("related")}
|
|
336
340
|
${expandScopeClause}
|
|
337
341
|
${expandAgentClause}
|
|
338
342
|
RETURN type(r) AS relType,
|
|
@@ -357,6 +361,27 @@ export async function memorySearch(params) {
|
|
|
357
361
|
}
|
|
358
362
|
allResults.push(result);
|
|
359
363
|
}
|
|
364
|
+
// Trash filter visibility: emit when the account holds any :Trashed nodes,
|
|
365
|
+
// so silent over-filtering is observable. Cheap single-row aggregate;
|
|
366
|
+
// accountId-as-unique-key labels (LocalBusiness/OnboardingState) have
|
|
367
|
+
// their accountId nulled and are missed here — acceptable, those labels
|
|
368
|
+
// are 1-per-account and rare in trash.
|
|
369
|
+
try {
|
|
370
|
+
const trashCensus = await session.run(`MATCH (n:Trashed) WHERE n.accountId = $accountId RETURN count(n) AS c`, { accountId });
|
|
371
|
+
const skipped = trashCensus.records[0]?.get("c");
|
|
372
|
+
const skippedCount = typeof skipped === "number"
|
|
373
|
+
? skipped
|
|
374
|
+
: skipped?.toNumber?.() ?? 0;
|
|
375
|
+
if (skippedCount > 0) {
|
|
376
|
+
const fingerprint = (labels && labels.length > 0)
|
|
377
|
+
? `labels=${labels.join(",")}`
|
|
378
|
+
: `query=${queryText.slice(0, 40).replace(/\s+/g, " ")}`;
|
|
379
|
+
process.stderr.write(`[trash:read-filter-skipped] accountId=${accountId} ${fingerprint} skippedCount=${skippedCount}\n`);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
catch {
|
|
383
|
+
// Census is observability-only — never break a search on its failure.
|
|
384
|
+
}
|
|
360
385
|
return allResults;
|
|
361
386
|
}
|
|
362
387
|
finally {
|