@rubytech/create-maxy-code 0.1.140 → 0.1.142
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/config/brand.json +1 -1
- package/payload/platform/neo4j/schema.cypher +42 -67
- package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -0
- 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 +14 -8
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.d.ts +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.d.ts.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.js +10 -7
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.js.map +1 -1
- package/payload/platform/plugins/docs/references/internals.md +1 -1
- package/payload/platform/plugins/docs/references/neo4j.md +3 -3
- package/payload/platform/plugins/docs/references/plugins-guide.md +1 -0
- package/payload/platform/plugins/email/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/email/PLUGIN.md +3 -7
- package/payload/platform/plugins/email/mcp/dist/index.js +7 -46
- package/payload/platform/plugins/email/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/credentials.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/credentials.js +4 -15
- package/payload/platform/plugins/email/mcp/dist/lib/credentials.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/graph.d.ts +51 -43
- package/payload/platform/plugins/email/mcp/dist/lib/graph.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/graph.js +223 -229
- package/payload/platform/plugins/email/mcp/dist/lib/graph.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.js +7 -4
- package/payload/platform/plugins/email/mcp/dist/scripts/email-fetch.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-graph-query.d.ts +14 -4
- package/payload/platform/plugins/email/mcp/dist/tools/email-graph-query.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-graph-query.js +69 -84
- package/payload/platform/plugins/email/mcp/dist/tools/email-graph-query.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-reply.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-reply.js +49 -64
- package/payload/platform/plugins/email/mcp/dist/tools/email-reply.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-setup.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js +1 -2
- package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.d.ts +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.js +3 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.js +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.d.ts +3 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.js +101 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js +7 -4
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts +59 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js +322 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
- package/payload/platform/plugins/memory/references/schema-base.md +4 -4
- package/payload/platform/plugins/memory/skills/conversation-archive/SKILL.md +2 -1
- package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +1 -0
- package/payload/platform/plugins/notion-import/skills/notion-import/SKILL.md +13 -9
- package/payload/platform/plugins/notion-import/skills/notion-import/references/databases.md +11 -9
- package/payload/platform/plugins/notion-import/skills/notion-import/references/page-tree.md +12 -12
- package/payload/platform/plugins/scheduling/PLUGIN.md +18 -0
- package/payload/platform/plugins/scheduling/mcp/dist/index.js +93 -0
- package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.d.ts +80 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.js +395 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics-graph-ingest.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics.d.ts +16 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics.js +111 -2
- package/payload/platform/plugins/scheduling/mcp/dist/lib/ics.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-archive-ics.d.ts +20 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-archive-ics.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-archive-ics.js +63 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-archive-ics.js.map +1 -0
- package/payload/platform/plugins/x-import/.claude-plugin/plugin.json +8 -0
- package/payload/platform/plugins/x-import/PLUGIN.md +33 -0
- package/payload/platform/plugins/x-import/references/archive-shape.md +124 -0
- package/payload/platform/plugins/x-import/references/transcript-shape.md +121 -0
- package/payload/platform/plugins/x-import/skills/x-import/SKILL.md +123 -0
- package/payload/platform/templates/specialists/agents/database-operator.md +6 -2
package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/conversation-normalisers/types.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,oBAAoB,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/conversation-normalisers/types.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,oBAAoB,8IAWvB,CAAC;AAEX,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvE,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,kBAAkB,CAExE;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,gFAAgF;IAChF,QAAQ,EAAE,MAAM,CAAC;IACjB,qFAAqF;IACrF,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B;qDACiD;IACjD,aAAa,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,kBAAkB,CAAC;CAC9B;AAED,MAAM,MAAM,sBAAsB,GAAG,CACnC,KAAK,EAAE,eAAe,KACnB,OAAO,CAAC,gBAAgB,CAAC,GAAG,gBAAgB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/lib/conversation-normalisers/types.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,uEAAuE;AACvE,2EAA2E;AAC3E,EAAE;AACF,yDAAyD;AACzD,uEAAuE;AACvE,wEAAwE;AACxE,0EAA0E;AAC1E,qEAAqE;AACrE,8EAA8E;AAC9E,4CAA4C;AAC5C,EAAE;AACF,gFAAgF;AAChF,uEAAuE;AACvE,0EAA0E;AAE1E,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,UAAU;IACV,UAAU;IACV,QAAQ;IACR,mBAAmB;IACnB,iBAAiB;IACjB,iBAAiB;IACjB,UAAU;IACV,OAAO;IACP,OAAO;CACC,CAAC;AAIX,MAAM,UAAU,oBAAoB,CAAC,CAAU;IAC7C,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAK,oBAA0C,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC1F,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/lib/conversation-normalisers/types.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,uEAAuE;AACvE,2EAA2E;AAC3E,EAAE;AACF,yDAAyD;AACzD,uEAAuE;AACvE,wEAAwE;AACxE,0EAA0E;AAC1E,qEAAqE;AACrE,8EAA8E;AAC9E,4CAA4C;AAC5C,EAAE;AACF,gFAAgF;AAChF,uEAAuE;AACvE,0EAA0E;AAE1E,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,UAAU;IACV,UAAU;IACV,QAAQ;IACR,mBAAmB;IACnB,iBAAiB;IACjB,iBAAiB;IACjB,UAAU;IACV,OAAO;IACP,MAAM;IACN,OAAO;CACC,CAAC;AAIX,MAAM,UAAU,oBAAoB,CAAC,CAAU;IAC7C,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAK,oBAA0C,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC1F,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"x-dm.d.ts","sourceRoot":"","sources":["../../../src/lib/conversation-normalisers/x-dm.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAc,MAAM,YAAY,CAAC;AAqDhF,wBAAgB,aAAa,CAAC,KAAK,EAAE,eAAe,GAAG,gBAAgB,CA0EtE"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { basename } from "node:path";
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// x-dm — X (Twitter) Direct Message normaliser.
|
|
6
|
+
//
|
|
7
|
+
// Reads a single-conversation slice of an X archive's direct-messages export.
|
|
8
|
+
// The X archive ships DMs as a `.js` file with a JSONP-style assignment
|
|
9
|
+
// wrapper:
|
|
10
|
+
//
|
|
11
|
+
// window.YTD.direct_messages.part0 = [
|
|
12
|
+
// { dmConversation: { conversationId, messages: [ { messageCreate: …} ] } },
|
|
13
|
+
// ...
|
|
14
|
+
// ]
|
|
15
|
+
//
|
|
16
|
+
// Multi-conversation files are split by the x-import skill before invocation,
|
|
17
|
+
// one slice per conversationId — each slice is a per-conversation archive in
|
|
18
|
+
// the conversation-archive sense (one `:ConversationArchive` per participant
|
|
19
|
+
// set). The skill writes each slice as either a wrapper-preserving `.js` shim
|
|
20
|
+
// containing a single-element array, or a wrapper-stripped JSON array; this
|
|
21
|
+
// normaliser accepts both shapes.
|
|
22
|
+
//
|
|
23
|
+
// Output bodies are `<senderId>: <text>` — senderId is the X numeric user id,
|
|
24
|
+
// which the x-import skill maps to a confirmed `:Person` / `:AdminUser`
|
|
25
|
+
// elementId before invoking the bash. The bash's `parser-miss` validation
|
|
26
|
+
// reads the senderId prefix and checks membership in the confirmed set.
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
const WRAPPER_PREFIX_RE = /^\s*window\.YTD\.direct_messages(?:_group)?\.part\d+\s*=\s*/;
|
|
29
|
+
export function xDmNormaliser(input) {
|
|
30
|
+
const { filePath, accountId } = input;
|
|
31
|
+
if (!accountId || !accountId.trim()) {
|
|
32
|
+
throw new Error("x-dm: accountId is required.");
|
|
33
|
+
}
|
|
34
|
+
const rawBytes = readFileSync(filePath);
|
|
35
|
+
const archiveSha256 = createHash("sha256").update(rawBytes).digest("hex");
|
|
36
|
+
const text = decodeText(rawBytes, filePath);
|
|
37
|
+
const stripped = text.replace(WRAPPER_PREFIX_RE, "");
|
|
38
|
+
let parsed;
|
|
39
|
+
try {
|
|
40
|
+
parsed = JSON.parse(stripped);
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
throw new Error(`x-dm: JSON parse failed after wrapper strip — ${err instanceof Error ? err.message : String(err)}. The file must be either a wrapper-stripped JSON array or a window.YTD.direct_messages.part0 = […] shim. file=${filePath}`);
|
|
44
|
+
}
|
|
45
|
+
if (!Array.isArray(parsed)) {
|
|
46
|
+
throw new Error(`x-dm: expected top-level array (post-wrapper-strip), got ${typeof parsed}. file=${filePath}`);
|
|
47
|
+
}
|
|
48
|
+
if (parsed.length !== 1) {
|
|
49
|
+
throw new Error(`x-dm: expected exactly one dmConversation entry in slice, got ${parsed.length}. Multi-conversation archives must be split by the x-import skill before ingest. file=${filePath}`);
|
|
50
|
+
}
|
|
51
|
+
const entry = parsed[0];
|
|
52
|
+
const convo = entry?.dmConversation;
|
|
53
|
+
if (!convo || !Array.isArray(convo.messages)) {
|
|
54
|
+
throw new Error(`x-dm: slice entry missing dmConversation.messages array. file=${filePath}`);
|
|
55
|
+
}
|
|
56
|
+
const messageCreates = [];
|
|
57
|
+
for (const env of convo.messages) {
|
|
58
|
+
const mc = env?.messageCreate;
|
|
59
|
+
if (!mc)
|
|
60
|
+
continue; // skip non-messageCreate envelopes (reactions, system joins)
|
|
61
|
+
const senderId = mc.senderId;
|
|
62
|
+
const createdAt = mc.createdAt;
|
|
63
|
+
if (!senderId || !createdAt)
|
|
64
|
+
continue;
|
|
65
|
+
const body = typeof mc.text === "string" ? mc.text : "";
|
|
66
|
+
messageCreates.push({ senderId, text: body, createdAt });
|
|
67
|
+
}
|
|
68
|
+
// X serialises createdAt as ISO-8601 (e.g. "2024-09-12T14:32:01.000Z").
|
|
69
|
+
// Sort chronologically — X archives are usually in order, but the contract
|
|
70
|
+
// doesn't guarantee it, so re-sorting is the deterministic primitive.
|
|
71
|
+
messageCreates.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
72
|
+
const parsedLines = messageCreates.map((m, idx) => ({
|
|
73
|
+
dateSent: m.createdAt,
|
|
74
|
+
body: `${m.senderId}: ${m.text}`,
|
|
75
|
+
sequenceIndex: idx,
|
|
76
|
+
}));
|
|
77
|
+
return {
|
|
78
|
+
parsedLines,
|
|
79
|
+
archiveSha256,
|
|
80
|
+
archiveSourceFile: basename(filePath),
|
|
81
|
+
counters: {
|
|
82
|
+
parsed: parsedLines.length,
|
|
83
|
+
systemSkipped: convo.messages.length - parsedLines.length,
|
|
84
|
+
mediaSkipped: 0,
|
|
85
|
+
parseErrors: 0,
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function decodeText(bytes, filePath) {
|
|
90
|
+
let decoded;
|
|
91
|
+
try {
|
|
92
|
+
decoded = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
throw new Error(`x-dm: UTF-8 decode failed — ${err instanceof Error ? err.message : String(err)}. file=${filePath}`);
|
|
96
|
+
}
|
|
97
|
+
if (decoded.charCodeAt(0) === 0xfeff)
|
|
98
|
+
decoded = decoded.slice(1);
|
|
99
|
+
return decoded;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=x-dm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"x-dm.js","sourceRoot":"","sources":["../../../src/lib/conversation-normalisers/x-dm.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typed-edge-schema.d.ts","sourceRoot":"","sources":["../../src/lib/typed-edge-schema.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,EAAE,aAAa,CAAC,aAAa,
|
|
1
|
+
{"version":3,"file":"typed-edge-schema.d.ts","sourceRoot":"","sources":["../../src/lib/typed-edge-schema.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,EAAE,aAAa,CAAC,aAAa,CAgE7D,CAAC;AAUF,uEAAuE;AACvE,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAET;AAED,gEAAgE;AAChE,eAAO,MAAM,gBAAgB,EAAE,aAAa,CAAC,MAAM,CAE3C,CAAC;AAET,mGAAmG;AACnG,eAAO,MAAM,oBAAoB,EAAE,aAAa,CAAC,MAAM,CAStD,CAAC"}
|
|
@@ -56,8 +56,11 @@ export const TYPED_EDGE_ALLOWLIST = [
|
|
|
56
56
|
{ sourceLabel: "Page", edgeType: "MENTIONS", targetLabel: "Event" },
|
|
57
57
|
{ sourceLabel: "Meeting", edgeType: "MENTIONS", targetLabel: "Person" },
|
|
58
58
|
{ sourceLabel: "Meeting", edgeType: "MENTIONS", targetLabel: "Organization" },
|
|
59
|
-
|
|
60
|
-
{
|
|
59
|
+
// Task 321 retired :Email; email threads land as :KnowledgeDocument
|
|
60
|
+
// {source:'email'} and the typed-edge pass picks them up via the
|
|
61
|
+
// KnowledgeDocument tuples below.
|
|
62
|
+
{ sourceLabel: "KnowledgeDocument", edgeType: "MENTIONS", targetLabel: "Person" },
|
|
63
|
+
{ sourceLabel: "KnowledgeDocument", edgeType: "MENTIONS", targetLabel: "Organization" },
|
|
61
64
|
{ sourceLabel: "Note", edgeType: "MENTIONS", targetLabel: "Person" },
|
|
62
65
|
{ sourceLabel: "Note", edgeType: "MENTIONS", targetLabel: "Organization" },
|
|
63
66
|
{ sourceLabel: "Idea", edgeType: "MENTIONS", targetLabel: "Person" },
|
|
@@ -72,7 +75,7 @@ export const TYPED_EDGE_ALLOWLIST = [
|
|
|
72
75
|
{ sourceLabel: "Person", edgeType: "AUTHORED", targetLabel: "Page" },
|
|
73
76
|
{ sourceLabel: "Person", edgeType: "AUTHORED", targetLabel: "Note" },
|
|
74
77
|
// ATTACHED_TO — document or media attached to a higher-level entity.
|
|
75
|
-
{ sourceLabel: "
|
|
78
|
+
{ sourceLabel: "KnowledgeDocument", edgeType: "ATTACHED_TO", targetLabel: "Meeting" },
|
|
76
79
|
{ sourceLabel: "Page", edgeType: "ATTACHED_TO", targetLabel: "Project" },
|
|
77
80
|
{ sourceLabel: "Note", edgeType: "ATTACHED_TO", targetLabel: "Project" },
|
|
78
81
|
// REFERENCES — one prose-bearing node references another.
|
|
@@ -93,7 +96,7 @@ export const PROSE_BEARING_LABELS = [
|
|
|
93
96
|
"Message",
|
|
94
97
|
"Page",
|
|
95
98
|
"Meeting",
|
|
96
|
-
"
|
|
99
|
+
"KnowledgeDocument",
|
|
97
100
|
"Idea",
|
|
98
101
|
"Note",
|
|
99
102
|
"Post",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typed-edge-schema.js","sourceRoot":"","sources":["../../src/lib/typed-edge-schema.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,wEAAwE;AACxE,oEAAoE;AACpE,mDAAmD;AACnD,EAAE;AACF,wBAAwB;AACxB,sEAAsE;AACtE,kDAAkD;AAClD,wEAAwE;AACxE,yEAAyE;AACzE,uCAAuC;AACvC,8DAA8D;AAC9D,qFAAqF;AACrF,EAAE;AACF,oEAAoE;AACpE,oEAAoE;AACpE,iBAAiB;AACjB,EAAE;AACF,uEAAuE;AACvE,mEAAmE;AACnE,sEAAsE;AACtE,sBAAsB;AAQtB;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAiC;IAChE,uCAAuC;IACvC,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE;IACrE,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE;IAEvE,wDAAwD;IACxD,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE;IAC5E,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE;IAE7E,oEAAoE;IACpE,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE;IAC/E,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,eAAe,EAAE;IAChF,EAAE,WAAW,EAAE,cAAc,EAAE,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE;IACrF,EAAE,WAAW,EAAE,cAAc,EAAE,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,eAAe,EAAE;IAEtF,4CAA4C;IAC5C,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,cAAc,EAAE;IAC3E,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE;IAE5E,8DAA8D;IAC9D,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,cAAc,EAAE;IAC3E,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE;IAC5E,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE;IAErE,qDAAqD;IACrD,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE;IACvE,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE;IAC7E,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE;IAC9E,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE;IACtE,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE;IACpE,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE;IAC1E,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE;IAC3E,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE;IACnE,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE;IACvE,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE;IAC7E,EAAE,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"typed-edge-schema.js","sourceRoot":"","sources":["../../src/lib/typed-edge-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -65,13 +65,69 @@ export interface ResolvedAttachment {
|
|
|
65
65
|
/** Display alt text or null. */
|
|
66
66
|
alt: string | null;
|
|
67
67
|
}
|
|
68
|
-
|
|
68
|
+
/**
|
|
69
|
+
* One Notion page in a `notion-pages` archive call. The notion-import skill
|
|
70
|
+
* parses page markdown and front-matter, then submits batches of these rows.
|
|
71
|
+
*
|
|
72
|
+
* Parent semantics: `parentNotionId === null` means "top-level page" — the
|
|
73
|
+
* handler writes (:NotionWorkspace)-[:HAS_SECTION]->(:KnowledgeDocument) at
|
|
74
|
+
* insert time. Non-null parents are NOT written here; the skill submits them
|
|
75
|
+
* to `notion-relations-pass-2` with `edgeType: 'HAS_SECTION'` so cross-batch
|
|
76
|
+
* forward references resolve correctly after every page is MERGEd.
|
|
77
|
+
*/
|
|
78
|
+
export interface NotionPageRow {
|
|
79
|
+
/** 32-hex Notion UUID. Natural key with accountId. */
|
|
80
|
+
notionId: string;
|
|
81
|
+
/** Human title from the basename. */
|
|
82
|
+
title: string;
|
|
83
|
+
/** Full markdown body, front-matter already stripped. */
|
|
84
|
+
text: string;
|
|
85
|
+
/** Null when this page is a workspace-root page. */
|
|
86
|
+
parentNotionId: string | null;
|
|
87
|
+
/** ISO 8601 datetime from front-matter `Created`, or null. */
|
|
88
|
+
notionCreatedAt: string | null;
|
|
89
|
+
/** ISO 8601 datetime from front-matter `Last edited`, or null. */
|
|
90
|
+
notionLastEditedAt: string | null;
|
|
91
|
+
/** elementId of an in-account :Person resolved by the skill, or null. */
|
|
92
|
+
authorPersonNodeId: string | null;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* One row from a Notion database in a `notion-database-rows` archive call.
|
|
96
|
+
* The per-call `label` (one of Person, Organization, Project, Task, Event,
|
|
97
|
+
* KnowledgeDocument) and `databaseNotionId` live on the params, not the row.
|
|
98
|
+
*/
|
|
99
|
+
export interface NotionDatabaseRowRow {
|
|
100
|
+
/** 32-hex Notion UUID. Natural key with accountId. */
|
|
101
|
+
notionId: string;
|
|
102
|
+
/** Mapped properties (canonical camelCase where mapped, original col names otherwise). */
|
|
103
|
+
properties: Record<string, string | number | boolean | null>;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* One pass-2 relation. Source and target must already exist (MERGEd by a
|
|
107
|
+
* prior `notion-pages` or `notion-database-rows` call); rows whose endpoints
|
|
108
|
+
* are missing are counted as `skippedUnknownTarget`, not errors.
|
|
109
|
+
*/
|
|
110
|
+
export interface NotionRelationRow {
|
|
111
|
+
sourceNotionId: string;
|
|
112
|
+
targetNotionId: string;
|
|
113
|
+
/** One of NOTION_RELATION_EDGE_TYPES. Unknown types are counted, not thrown. */
|
|
114
|
+
edgeType: string;
|
|
115
|
+
/** Edge properties (e.g. `mentionContext` for unmapped Notion relations). */
|
|
116
|
+
properties?: Record<string, string | number | boolean | null>;
|
|
117
|
+
}
|
|
118
|
+
export type ArchiveRow = LinkedInConnectionRow | ObsidianPageRow | NotionPageRow | NotionDatabaseRowRow | NotionRelationRow;
|
|
69
119
|
export interface ArchiveWriteParams {
|
|
70
120
|
archiveType: string;
|
|
71
121
|
ownerNodeId: string;
|
|
72
122
|
accountId: string;
|
|
73
123
|
rows: ArchiveRow[];
|
|
74
124
|
sessionId?: string;
|
|
125
|
+
/** notion-pages: UUID per import run, stamped on every created node as `importId`. */
|
|
126
|
+
importId?: string;
|
|
127
|
+
/** notion-database-rows: 32-hex Notion ID of the parent database (the `:KnowledgeDocument {kind:'notion-database'}`). */
|
|
128
|
+
databaseNotionId?: string;
|
|
129
|
+
/** notion-database-rows: one of Person|Organization|Project|Task|Event|KnowledgeDocument. */
|
|
130
|
+
label?: string;
|
|
75
131
|
}
|
|
76
132
|
export interface ArchiveWriteResult {
|
|
77
133
|
archiveType: string;
|
|
@@ -114,4 +170,6 @@ export declare const OBSIDIAN_WIKILINK_PAGE_CYPHER = "\nUNWIND $pageLinks AS wl\
|
|
|
114
170
|
export declare const OBSIDIAN_WIKILINK_ENTITY_CYPHER = "\nUNWIND $entityLinks AS wl\nMATCH (src:KnowledgeDocument {accountId: $accountId, obsidianPath: wl.fromPath})\nMATCH (dst) WHERE elementId(dst) = wl.toNodeId AND dst.accountId = $accountId\nMERGE (src)-[r:MENTIONS]->(dst)\n ON CREATE SET\n r.linkText = wl.linkText,\n r.alias = wl.alias,\n r.source = 'obsidian',\n r.createdAt = datetime()\nRETURN count(*) AS processed\n";
|
|
115
171
|
export declare const OBSIDIAN_WIKILINK_STUB_CYPHER = "\nUNWIND $stubLinks AS wl\nMATCH (src:KnowledgeDocument {accountId: $accountId, obsidianPath: wl.fromPath})\nMERGE (c:Concept {accountId: $accountId, name: wl.stubName, source: 'obsidian-stub'})\n ON CREATE SET\n c.createdByAgent = 'obsidian-import',\n c.createdBySource = 'obsidian-import',\n c.createdBySession = $sessionId,\n c.createdAt = datetime(),\n c.scope = 'admin'\nMERGE (src)-[r:MENTIONS]->(c)\n ON CREATE SET\n r.linkText = wl.linkText,\n r.alias = wl.alias,\n r.source = 'obsidian',\n r.createdAt = datetime()\nRETURN count(*) AS processed\n";
|
|
116
172
|
export declare const OBSIDIAN_ATTACHMENT_CYPHER = "\nUNWIND $rows AS row\nWITH row WHERE size(row.attachments) > 0\nMATCH (k:KnowledgeDocument {accountId: $accountId, obsidianPath: row.obsidianPath})\nUNWIND row.attachments AS att\nMERGE (d:DigitalDocument {accountId: $accountId, attachmentPath: att.archivePath})\n ON CREATE SET\n d.digitalDocumentId = randomUUID(),\n d.source = 'obsidian',\n d.encodingFormat = att.encodingFormat,\n d.alt = att.alt,\n d.createdByAgent = 'obsidian-import',\n d.createdBySource = 'obsidian-import',\n d.createdBySession = $sessionId,\n d.createdAt = datetime(),\n d.scope = 'admin'\nMERGE (d)-[e:EMBEDDED_IN]->(k)\n ON CREATE SET\n e.source = 'obsidian',\n e.createdAt = datetime()\nRETURN count(*) AS processed\n";
|
|
173
|
+
export declare const NOTION_PAGE_CYPHER = "\nMATCH (workspace:NotionWorkspace) WHERE elementId(workspace) = $ownerNodeId\nWITH workspace, $rows AS rows\nUNWIND rows AS row\nMERGE (k:KnowledgeDocument {accountId: $accountId, notionId: row.notionId})\n ON CREATE SET\n k.knowledgeDocId = randomUUID(),\n k.kind = 'notion-page',\n k.source = 'notion',\n k.createdByAgent = 'notion-import',\n k.createdBySource = 'notion-import',\n k.createdBySession = $sessionId,\n k.createdAt = datetime(),\n k.scope = 'admin',\n k.importId = $importId\nSET\n k.title = row.title,\n k.text = row.text,\n k.updatedAt = datetime()\nFOREACH (_ IN CASE WHEN row.notionCreatedAt IS NOT NULL THEN [1] ELSE [] END |\n SET k.notionCreatedAt = datetime(row.notionCreatedAt)\n)\nFOREACH (_ IN CASE WHEN row.notionLastEditedAt IS NOT NULL THEN [1] ELSE [] END |\n SET k.notionLastEditedAt = datetime(row.notionLastEditedAt)\n)\nFOREACH (_ IN CASE WHEN row.parentNotionId IS NULL THEN [1] ELSE [] END |\n MERGE (workspace)-[r:HAS_SECTION]->(k)\n ON CREATE SET r.source = 'notion', r.createdAt = datetime()\n)\nRETURN count(*) AS processed\n";
|
|
174
|
+
export declare const NOTION_PAGE_AUTHOR_CYPHER = "\nUNWIND $rows AS row\nWITH row WHERE row.authorPersonNodeId IS NOT NULL\nMATCH (page:KnowledgeDocument {accountId: $accountId, notionId: row.notionId})\nMATCH (author) WHERE elementId(author) = row.authorPersonNodeId AND author.accountId = $accountId\nMERGE (author)-[r:AUTHORED]->(page)\n ON CREATE SET r.source = 'notion', r.createdAt = datetime()\nRETURN count(*) AS processed\n";
|
|
117
175
|
//# sourceMappingURL=memory-archive-write.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-archive-write.d.ts","sourceRoot":"","sources":["../../src/tools/memory-archive-write.ts"],"names":[],"mappings":"AA+BA,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,4EAA4E;IAC5E,YAAY,EAAE,MAAM,CAAC;IACrB,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,0EAA0E;IAC1E,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,kFAAkF;IAClF,WAAW,EAAE,kBAAkB,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,gBAAgB;IAC/B,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,yCAAyC;IACzC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,iCAAiC;IACjC,MAAM,EACF;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,GACtC;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GACrD;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACpC;AAED,MAAM,WAAW,kBAAkB;IACjC,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,WAAW,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,cAAc,EAAE,MAAM,CAAC;IACvB,gCAAgC;IAChC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB;AAED,MAAM,MAAM,UAAU,GAAG,
|
|
1
|
+
{"version":3,"file":"memory-archive-write.d.ts","sourceRoot":"","sources":["../../src/tools/memory-archive-write.ts"],"names":[],"mappings":"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"}
|
|
@@ -24,6 +24,9 @@ const BATCH_SIZE = 500;
|
|
|
24
24
|
const HANDLERS = {
|
|
25
25
|
"linkedin-connections": linkedinConnectionsHandler(),
|
|
26
26
|
"obsidian-vault": obsidianVaultHandler(),
|
|
27
|
+
"notion-pages": notionPagesHandler(),
|
|
28
|
+
"notion-database-rows": notionDatabaseRowsHandler(),
|
|
29
|
+
"notion-relations-pass-2": notionRelationsPass2Handler(),
|
|
27
30
|
};
|
|
28
31
|
// ---------------------------------------------------------------------------
|
|
29
32
|
// Entry point
|
|
@@ -473,6 +476,325 @@ function normaliseObsidianRow(row) {
|
|
|
473
476
|
attachments: Array.isArray(row.attachments) ? row.attachments : [],
|
|
474
477
|
};
|
|
475
478
|
}
|
|
479
|
+
// ---------------------------------------------------------------------------
|
|
480
|
+
// notion-pages / notion-database-rows / notion-relations-pass-2 handlers
|
|
481
|
+
// ---------------------------------------------------------------------------
|
|
482
|
+
//
|
|
483
|
+
// Notion's export shape (page tree + DB schemas + typed relations + mentions)
|
|
484
|
+
// does not fit the linkedin flat-row model, so the import skill splits the
|
|
485
|
+
// write into three archiveType calls:
|
|
486
|
+
//
|
|
487
|
+
// 1. notion-pages — MERGE every :KnowledgeDocument page,
|
|
488
|
+
// stamp provenance, attach workspace-root
|
|
489
|
+
// HAS_SECTION at insert time, optional
|
|
490
|
+
// AUTHORED edge. Page-to-page HAS_SECTION
|
|
491
|
+
// is deferred to pass-2 so cross-batch
|
|
492
|
+
// forward references resolve cleanly.
|
|
493
|
+
// 2. notion-database-rows — MERGE typed-label nodes (Person, Org,
|
|
494
|
+
// Project, Task, Event, KnowledgeDocument
|
|
495
|
+
// fallback) and the
|
|
496
|
+
// (:notion-database)-[:HAS_SECTION]->(row)
|
|
497
|
+
// edge. Per-call `label` decides which
|
|
498
|
+
// Cypher template runs.
|
|
499
|
+
// 3. notion-relations-pass-2 — MERGE all deferred relations
|
|
500
|
+
// (page-to-page HAS_SECTION, MENTIONS,
|
|
501
|
+
// WORKS_FOR, OWNS, ASSIGNED_TO, PART_OF,
|
|
502
|
+
// ATTENDED, AUTHORED) once every node
|
|
503
|
+
// exists. Source/target located by
|
|
504
|
+
// (accountId, notionId); missing endpoints
|
|
505
|
+
// count as skippedUnknownTarget.
|
|
506
|
+
const NOTION_RELATION_EDGE_TYPES = new Set([
|
|
507
|
+
"MENTIONS",
|
|
508
|
+
"WORKS_FOR",
|
|
509
|
+
"OWNS",
|
|
510
|
+
"ASSIGNED_TO",
|
|
511
|
+
"PART_OF",
|
|
512
|
+
"ATTENDED",
|
|
513
|
+
"HAS_SECTION",
|
|
514
|
+
"AUTHORED",
|
|
515
|
+
]);
|
|
516
|
+
const NOTION_ROW_LABELS = new Set([
|
|
517
|
+
"Person",
|
|
518
|
+
"Organization",
|
|
519
|
+
"Project",
|
|
520
|
+
"Task",
|
|
521
|
+
"Event",
|
|
522
|
+
"KnowledgeDocument",
|
|
523
|
+
]);
|
|
524
|
+
const NOTION_ID_RE = /^[0-9a-f]{32}$/i;
|
|
525
|
+
async function verifyNotionWorkspaceOwner(session, params) {
|
|
526
|
+
const { ownerNodeId, accountId } = params;
|
|
527
|
+
const result = await session.run(`MATCH (n) WHERE elementId(n) = $ownerNodeId
|
|
528
|
+
RETURN labels(n) AS labels, n.accountId AS accountId LIMIT 1`, { ownerNodeId });
|
|
529
|
+
if (result.records.length === 0) {
|
|
530
|
+
throw new Error(`ownerNodeId ${ownerNodeId} not found. Confirm the :NotionWorkspace node before invoking memory-archive-write.`);
|
|
531
|
+
}
|
|
532
|
+
const labels = result.records[0].get("labels") ?? [];
|
|
533
|
+
if (!labels.includes("NotionWorkspace")) {
|
|
534
|
+
throw new Error(`ownerNodeId ${ownerNodeId} has labels [${labels.join(", ")}]; expected :NotionWorkspace.`);
|
|
535
|
+
}
|
|
536
|
+
const ownerAccountId = result.records[0].get("accountId");
|
|
537
|
+
if (ownerAccountId && ownerAccountId !== accountId) {
|
|
538
|
+
throw new Error(`ownerNodeId ${ownerNodeId} belongs to account ${ownerAccountId}, not ${accountId}. Cross-account Notion ingest refused.`);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
// ---- notion-pages ---------------------------------------------------------
|
|
542
|
+
export const NOTION_PAGE_CYPHER = `
|
|
543
|
+
MATCH (workspace:NotionWorkspace) WHERE elementId(workspace) = $ownerNodeId
|
|
544
|
+
WITH workspace, $rows AS rows
|
|
545
|
+
UNWIND rows AS row
|
|
546
|
+
MERGE (k:KnowledgeDocument {accountId: $accountId, notionId: row.notionId})
|
|
547
|
+
ON CREATE SET
|
|
548
|
+
k.knowledgeDocId = randomUUID(),
|
|
549
|
+
k.kind = 'notion-page',
|
|
550
|
+
k.source = 'notion',
|
|
551
|
+
k.createdByAgent = 'notion-import',
|
|
552
|
+
k.createdBySource = 'notion-import',
|
|
553
|
+
k.createdBySession = $sessionId,
|
|
554
|
+
k.createdAt = datetime(),
|
|
555
|
+
k.scope = 'admin',
|
|
556
|
+
k.importId = $importId
|
|
557
|
+
SET
|
|
558
|
+
k.title = row.title,
|
|
559
|
+
k.text = row.text,
|
|
560
|
+
k.updatedAt = datetime()
|
|
561
|
+
FOREACH (_ IN CASE WHEN row.notionCreatedAt IS NOT NULL THEN [1] ELSE [] END |
|
|
562
|
+
SET k.notionCreatedAt = datetime(row.notionCreatedAt)
|
|
563
|
+
)
|
|
564
|
+
FOREACH (_ IN CASE WHEN row.notionLastEditedAt IS NOT NULL THEN [1] ELSE [] END |
|
|
565
|
+
SET k.notionLastEditedAt = datetime(row.notionLastEditedAt)
|
|
566
|
+
)
|
|
567
|
+
FOREACH (_ IN CASE WHEN row.parentNotionId IS NULL THEN [1] ELSE [] END |
|
|
568
|
+
MERGE (workspace)-[r:HAS_SECTION]->(k)
|
|
569
|
+
ON CREATE SET r.source = 'notion', r.createdAt = datetime()
|
|
570
|
+
)
|
|
571
|
+
RETURN count(*) AS processed
|
|
572
|
+
`;
|
|
573
|
+
export const NOTION_PAGE_AUTHOR_CYPHER = `
|
|
574
|
+
UNWIND $rows AS row
|
|
575
|
+
WITH row WHERE row.authorPersonNodeId IS NOT NULL
|
|
576
|
+
MATCH (page:KnowledgeDocument {accountId: $accountId, notionId: row.notionId})
|
|
577
|
+
MATCH (author) WHERE elementId(author) = row.authorPersonNodeId AND author.accountId = $accountId
|
|
578
|
+
MERGE (author)-[r:AUTHORED]->(page)
|
|
579
|
+
ON CREATE SET r.source = 'notion', r.createdAt = datetime()
|
|
580
|
+
RETURN count(*) AS processed
|
|
581
|
+
`;
|
|
582
|
+
function notionPagesHandler() {
|
|
583
|
+
return {
|
|
584
|
+
async verifyArchive(session, params) {
|
|
585
|
+
if (!params.importId || !params.importId.trim()) {
|
|
586
|
+
throw new Error("notion-pages: params.importId is required (UUID per import run).");
|
|
587
|
+
}
|
|
588
|
+
await verifyNotionWorkspaceOwner(session, params);
|
|
589
|
+
},
|
|
590
|
+
async writeBatch(session, ctx) {
|
|
591
|
+
const { params, batchRows, sessionId } = ctx;
|
|
592
|
+
const rows = batchRows.map(normaliseNotionPageRow);
|
|
593
|
+
const queryParams = {
|
|
594
|
+
ownerNodeId: params.ownerNodeId,
|
|
595
|
+
accountId: params.accountId,
|
|
596
|
+
sessionId,
|
|
597
|
+
importId: params.importId,
|
|
598
|
+
rows,
|
|
599
|
+
};
|
|
600
|
+
return await session.executeWrite(async (tx) => {
|
|
601
|
+
const pageRes = await tx.run(NOTION_PAGE_CYPHER, queryParams);
|
|
602
|
+
const pageCounters = pageRes.summary.counters.updates();
|
|
603
|
+
const authorRes = await tx.run(NOTION_PAGE_AUTHOR_CYPHER, queryParams);
|
|
604
|
+
const authorCounters = authorRes.summary.counters.updates();
|
|
605
|
+
return {
|
|
606
|
+
createdPages: pageCounters.nodesCreated,
|
|
607
|
+
mergedPages: rows.length - pageCounters.nodesCreated,
|
|
608
|
+
workspaceEdgesCreated: pageCounters.relationshipsCreated,
|
|
609
|
+
authoredEdgesCreated: authorCounters.relationshipsCreated,
|
|
610
|
+
};
|
|
611
|
+
});
|
|
612
|
+
},
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
function normaliseNotionPageRow(row) {
|
|
616
|
+
if (!row.notionId || !NOTION_ID_RE.test(row.notionId)) {
|
|
617
|
+
throw new Error(`notion-pages row notionId="${row.notionId}" is not a 32-hex Notion UUID.`);
|
|
618
|
+
}
|
|
619
|
+
if (row.parentNotionId !== null && !NOTION_ID_RE.test(row.parentNotionId)) {
|
|
620
|
+
throw new Error(`notion-pages row parentNotionId="${row.parentNotionId}" is not a 32-hex Notion UUID (use null for workspace-root pages).`);
|
|
621
|
+
}
|
|
622
|
+
return {
|
|
623
|
+
notionId: row.notionId.toLowerCase(),
|
|
624
|
+
title: (row.title ?? "").trim(),
|
|
625
|
+
text: row.text ?? "",
|
|
626
|
+
parentNotionId: row.parentNotionId ? row.parentNotionId.toLowerCase() : null,
|
|
627
|
+
notionCreatedAt: row.notionCreatedAt ?? null,
|
|
628
|
+
notionLastEditedAt: row.notionLastEditedAt ?? null,
|
|
629
|
+
authorPersonNodeId: row.authorPersonNodeId && row.authorPersonNodeId.trim()
|
|
630
|
+
? row.authorPersonNodeId.trim()
|
|
631
|
+
: null,
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
// ---- notion-database-rows -------------------------------------------------
|
|
635
|
+
function notionRowCypher(label) {
|
|
636
|
+
// The label is dispatched at handler call time from the closed NOTION_ROW_LABELS
|
|
637
|
+
// allowlist; string interpolation here is safe because the value is validated
|
|
638
|
+
// in verifyArchive before this template is built.
|
|
639
|
+
const docIdStamp = label === "KnowledgeDocument"
|
|
640
|
+
? "n.knowledgeDocId = randomUUID(),\n n.kind = 'notion-row',"
|
|
641
|
+
: "";
|
|
642
|
+
return `
|
|
643
|
+
MATCH (db:KnowledgeDocument {accountId: $accountId, notionId: $databaseNotionId, kind: 'notion-database'})
|
|
644
|
+
WITH db, $rows AS rows
|
|
645
|
+
UNWIND rows AS row
|
|
646
|
+
MERGE (n:${label} {accountId: $accountId, notionId: row.notionId})
|
|
647
|
+
ON CREATE SET
|
|
648
|
+
${docIdStamp}
|
|
649
|
+
n.source = 'notion',
|
|
650
|
+
n.createdByAgent = 'notion-import',
|
|
651
|
+
n.createdBySource = 'notion-import',
|
|
652
|
+
n.createdBySession = $sessionId,
|
|
653
|
+
n.createdAt = datetime(),
|
|
654
|
+
n.scope = 'admin',
|
|
655
|
+
n.importId = $importId
|
|
656
|
+
SET n += row.properties, n.updatedAt = datetime()
|
|
657
|
+
MERGE (db)-[r:HAS_SECTION]->(n)
|
|
658
|
+
ON CREATE SET r.source = 'notion', r.createdAt = datetime()
|
|
659
|
+
RETURN count(*) AS processed
|
|
660
|
+
`;
|
|
661
|
+
}
|
|
662
|
+
function notionDatabaseRowsHandler() {
|
|
663
|
+
return {
|
|
664
|
+
async verifyArchive(session, params) {
|
|
665
|
+
if (!params.importId || !params.importId.trim()) {
|
|
666
|
+
throw new Error("notion-database-rows: params.importId is required (UUID per import run).");
|
|
667
|
+
}
|
|
668
|
+
if (!params.databaseNotionId || !NOTION_ID_RE.test(params.databaseNotionId)) {
|
|
669
|
+
throw new Error(`notion-database-rows: params.databaseNotionId="${params.databaseNotionId}" is not a 32-hex Notion UUID.`);
|
|
670
|
+
}
|
|
671
|
+
if (!params.label || !NOTION_ROW_LABELS.has(params.label)) {
|
|
672
|
+
throw new Error(`notion-database-rows: params.label="${params.label}" is not in the allowlist (${Array.from(NOTION_ROW_LABELS).join(", ")}).`);
|
|
673
|
+
}
|
|
674
|
+
await verifyNotionWorkspaceOwner(session, params);
|
|
675
|
+
// The parent database (:KnowledgeDocument {kind:'notion-database'}) must
|
|
676
|
+
// already exist — the skill MERGEs it before calling notion-database-rows.
|
|
677
|
+
const dbRes = await session.run(`MATCH (db:KnowledgeDocument {accountId: $accountId, notionId: $databaseNotionId, kind: 'notion-database'})
|
|
678
|
+
RETURN count(db) AS n LIMIT 1`, { accountId: params.accountId, databaseNotionId: params.databaseNotionId });
|
|
679
|
+
const n = dbRes.records[0]?.get("n");
|
|
680
|
+
const nNum = typeof n === "number" ? n : n?.toNumber?.() ?? 0;
|
|
681
|
+
if (nNum === 0) {
|
|
682
|
+
throw new Error(`notion-database-rows: parent database :KnowledgeDocument {kind:'notion-database', notionId:'${params.databaseNotionId}'} not found for account ${params.accountId}. MERGE the database node before calling notion-database-rows.`);
|
|
683
|
+
}
|
|
684
|
+
},
|
|
685
|
+
async writeBatch(session, ctx) {
|
|
686
|
+
const { params, batchRows, sessionId } = ctx;
|
|
687
|
+
const label = params.label;
|
|
688
|
+
const rows = batchRows.map(normaliseNotionDatabaseRow);
|
|
689
|
+
const queryParams = {
|
|
690
|
+
accountId: params.accountId,
|
|
691
|
+
sessionId,
|
|
692
|
+
importId: params.importId,
|
|
693
|
+
databaseNotionId: params.databaseNotionId,
|
|
694
|
+
rows,
|
|
695
|
+
};
|
|
696
|
+
return await session.executeWrite(async (tx) => {
|
|
697
|
+
const res = await tx.run(notionRowCypher(label), queryParams);
|
|
698
|
+
const counters = res.summary.counters.updates();
|
|
699
|
+
return {
|
|
700
|
+
createdRows: counters.nodesCreated,
|
|
701
|
+
mergedRows: rows.length - counters.nodesCreated,
|
|
702
|
+
createdHasSectionEdges: counters.relationshipsCreated,
|
|
703
|
+
};
|
|
704
|
+
});
|
|
705
|
+
},
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
function normaliseNotionDatabaseRow(row) {
|
|
709
|
+
if (!row.notionId || !NOTION_ID_RE.test(row.notionId)) {
|
|
710
|
+
throw new Error(`notion-database-rows row notionId="${row.notionId}" is not a 32-hex Notion UUID.`);
|
|
711
|
+
}
|
|
712
|
+
const properties = {};
|
|
713
|
+
for (const [k, v] of Object.entries(row.properties ?? {})) {
|
|
714
|
+
if (v === undefined)
|
|
715
|
+
continue;
|
|
716
|
+
properties[k] = v;
|
|
717
|
+
}
|
|
718
|
+
return {
|
|
719
|
+
notionId: row.notionId.toLowerCase(),
|
|
720
|
+
properties,
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
// ---- notion-relations-pass-2 ----------------------------------------------
|
|
724
|
+
function notionRelationsPass2Handler() {
|
|
725
|
+
return {
|
|
726
|
+
async verifyArchive(session, params) {
|
|
727
|
+
await verifyNotionWorkspaceOwner(session, params);
|
|
728
|
+
},
|
|
729
|
+
async writeBatch(session, ctx) {
|
|
730
|
+
const { params, batchRows } = ctx;
|
|
731
|
+
const relations = batchRows.map(normaliseNotionRelationRow);
|
|
732
|
+
const byType = {};
|
|
733
|
+
let skippedUnknownEdgeType = 0;
|
|
734
|
+
for (const r of relations) {
|
|
735
|
+
if (!NOTION_RELATION_EDGE_TYPES.has(r.edgeType)) {
|
|
736
|
+
skippedUnknownEdgeType += 1;
|
|
737
|
+
continue;
|
|
738
|
+
}
|
|
739
|
+
(byType[r.edgeType] ??= []).push(r);
|
|
740
|
+
}
|
|
741
|
+
return await session.executeWrite(async (tx) => {
|
|
742
|
+
let relationsCreated = 0;
|
|
743
|
+
let relationsMatched = 0;
|
|
744
|
+
let skippedUnknownTarget = 0;
|
|
745
|
+
for (const [edgeType, rels] of Object.entries(byType)) {
|
|
746
|
+
// edgeType is validated against NOTION_RELATION_EDGE_TYPES above, so
|
|
747
|
+
// interpolating it into the MERGE pattern is safe.
|
|
748
|
+
const cypher = `
|
|
749
|
+
UNWIND $relations AS rel
|
|
750
|
+
MATCH (src {accountId: $accountId, notionId: rel.sourceNotionId})
|
|
751
|
+
MATCH (tgt {accountId: $accountId, notionId: rel.targetNotionId})
|
|
752
|
+
MERGE (src)-[r:${edgeType}]->(tgt)
|
|
753
|
+
ON CREATE SET r.source = 'notion', r.createdAt = datetime()
|
|
754
|
+
SET r += coalesce(rel.properties, {})
|
|
755
|
+
RETURN count(*) AS matched
|
|
756
|
+
`;
|
|
757
|
+
const res = await tx.run(cypher, {
|
|
758
|
+
accountId: params.accountId,
|
|
759
|
+
relations: rels,
|
|
760
|
+
});
|
|
761
|
+
const matchedRaw = res.records[0]?.get("matched");
|
|
762
|
+
const matched = typeof matchedRaw === "number"
|
|
763
|
+
? matchedRaw
|
|
764
|
+
: matchedRaw?.toNumber?.() ?? 0;
|
|
765
|
+
const created = res.summary.counters.updates().relationshipsCreated;
|
|
766
|
+
relationsCreated += created;
|
|
767
|
+
relationsMatched += matched - created;
|
|
768
|
+
skippedUnknownTarget += rels.length - matched;
|
|
769
|
+
}
|
|
770
|
+
return {
|
|
771
|
+
relationsCreated,
|
|
772
|
+
relationsMatched,
|
|
773
|
+
skippedUnknownTarget,
|
|
774
|
+
skippedUnknownEdgeType,
|
|
775
|
+
};
|
|
776
|
+
});
|
|
777
|
+
},
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
function normaliseNotionRelationRow(row) {
|
|
781
|
+
if (!row.sourceNotionId || !NOTION_ID_RE.test(row.sourceNotionId)) {
|
|
782
|
+
throw new Error(`notion-relations-pass-2 row sourceNotionId="${row.sourceNotionId}" is not a 32-hex Notion UUID.`);
|
|
783
|
+
}
|
|
784
|
+
if (!row.targetNotionId || !NOTION_ID_RE.test(row.targetNotionId)) {
|
|
785
|
+
throw new Error(`notion-relations-pass-2 row targetNotionId="${row.targetNotionId}" is not a 32-hex Notion UUID.`);
|
|
786
|
+
}
|
|
787
|
+
if (!row.edgeType || !row.edgeType.trim()) {
|
|
788
|
+
throw new Error(`notion-relations-pass-2 row edgeType is required (one of ${Array.from(NOTION_RELATION_EDGE_TYPES).join(", ")} — unknown values are counted, not thrown).`);
|
|
789
|
+
}
|
|
790
|
+
return {
|
|
791
|
+
sourceNotionId: row.sourceNotionId.toLowerCase(),
|
|
792
|
+
targetNotionId: row.targetNotionId.toLowerCase(),
|
|
793
|
+
edgeType: row.edgeType,
|
|
794
|
+
properties: row.properties,
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
// ---------------------------------------------------------------------------
|
|
476
798
|
function normaliseLinkedinRow(row) {
|
|
477
799
|
if (!row.linkedinUrl || !row.linkedinUrl.trim()) {
|
|
478
800
|
throw new Error("linkedin-connections row missing linkedinUrl (natural key).");
|