@rubytech/create-realagent 1.0.828 → 1.0.830
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/lib/oauth-llm/dist/index.d.ts +1 -1
- package/payload/platform/lib/oauth-llm/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/oauth-llm/dist/index.js +21 -0
- package/payload/platform/lib/oauth-llm/dist/index.js.map +1 -1
- package/payload/platform/lib/oauth-llm/src/index.ts +24 -0
- package/payload/platform/neo4j/migrations/007-conversation-archive-source.ts +116 -0
- package/payload/platform/neo4j/schema.cypher +12 -2
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/admin/hooks/__tests__/archive-ingest-surface-gate.test.sh +6 -6
- package/payload/platform/plugins/admin/hooks/archive-ingest-surface-gate.sh +14 -8
- package/payload/platform/plugins/admin/skills/onboarding/SKILL.md +2 -2
- package/payload/platform/plugins/contacts/mcp/dist/index.js +5 -5
- package/payload/platform/plugins/contacts/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.d.ts +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 +29 -23
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js.map +1 -1
- package/payload/platform/plugins/docs/references/plugins-guide.md +1 -1
- package/payload/platform/plugins/memory/PLUGIN.md +6 -5
- package/payload/platform/plugins/{whatsapp-import/bin/ingest.mjs → memory/bin/conversation-archive-ingest.mjs} +136 -212
- package/payload/platform/plugins/{whatsapp-import/bin/whatsapp-ingest.sh → memory/bin/conversation-archive-ingest.sh} +27 -19
- package/payload/platform/plugins/memory/mcp/dist/index.js +26 -212
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/llm-classifier.test.js +4 -3
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/llm-classifier.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.js +11 -6
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js +103 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.d.ts +5 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.js +30 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.d.ts +48 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.js +23 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/whatsapp-text.d.ts +3 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/whatsapp-text.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/whatsapp-text.js +237 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/whatsapp-text.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/delta-cursor.d.ts +11 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/delta-cursor.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/delta-cursor.js +21 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/delta-cursor.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.d.ts +16 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.js +39 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sender-bind.d.ts +17 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sender-bind.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sender-bind.js +90 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sender-bind.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sessionize.d.ts +9 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sessionize.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sessionize.js +32 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/sessionize.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/to-turn-text.d.ts +3 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/to-turn-text.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/to-turn-text.js +27 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/to-turn-text.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/document-chunker.d.ts +45 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/document-chunker.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/document-chunker.js +125 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/document-chunker.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.d.ts +24 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.js +293 -33
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-ranker.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-ranker.js +9 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/llm-ranker.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.d.ts +16 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.js +12 -3
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-source-agnosticism.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-source-agnosticism.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-source-agnosticism.test.js +75 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-source-agnosticism.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-whatsapp-text.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-whatsapp-text.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-whatsapp-text.test.js +67 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-whatsapp-text.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js +2 -138
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.js +39 -3
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.js +148 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts +1 -47
- 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 +9 -318
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts +7 -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 +14 -8
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts +21 -17
- 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 +77 -37
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -1
- package/payload/platform/plugins/memory/references/schema-base.md +3 -1
- package/payload/platform/plugins/{whatsapp-import/skills/whatsapp-import → memory/skills/conversation-archive}/SKILL.md +45 -36
- package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +59 -6
- package/payload/platform/plugins/whatsapp/PLUGIN.md +1 -1
- package/payload/platform/scripts/seed-neo4j.sh +9 -8
- package/payload/platform/templates/specialists/agents/database-operator.md +7 -14
- package/payload/server/chunk-7BO5HDJC.js +10093 -0
- package/payload/server/chunk-CUSH3UXP.js +2305 -0
- package/payload/server/chunk-EL4DZ56X.js +1116 -0
- package/payload/server/chunk-IWNDVGKT.js +10077 -0
- package/payload/server/chunk-KC7NUABI.js +654 -0
- package/payload/server/chunk-QOJ2D26Z.js +654 -0
- package/payload/server/chunk-RC46ZYGT.js +2305 -0
- package/payload/server/chunk-WUVXPZIV.js +1116 -0
- package/payload/server/client-pool-3TM3SRIA.js +32 -0
- package/payload/server/client-pool-7NTEFNVQ.js +32 -0
- package/payload/server/cloudflare-task-tracker-4NIODMGL.js +19 -0
- package/payload/server/cloudflare-task-tracker-WE77WXSI.js +19 -0
- package/payload/server/maxy-edge.js +3 -3
- package/payload/server/neo4j-migrations-4XPNJNM6.js +490 -0
- package/payload/server/neo4j-migrations-XTQ4WEV6.js +428 -0
- package/payload/server/server.js +6 -6
- package/payload/platform/plugins/whatsapp-import/PLUGIN.md +0 -48
- package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/delta-append.test.ts +0 -163
- package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/parse-export-lrm.test.ts +0 -83
- package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/parse-export.test.ts +0 -678
- package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/sessionize.test.ts +0 -91
- package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/to-classifier-input.test.ts +0 -59
- package/payload/platform/plugins/whatsapp-import/lib/src/delta-cursor.ts +0 -54
- package/payload/platform/plugins/whatsapp-import/lib/src/derive-keys.ts +0 -82
- package/payload/platform/plugins/whatsapp-import/lib/src/index.ts +0 -22
- package/payload/platform/plugins/whatsapp-import/lib/src/parse-export.ts +0 -471
- package/payload/platform/plugins/whatsapp-import/lib/src/sessionize.ts +0 -81
- package/payload/platform/plugins/whatsapp-import/lib/src/to-classifier-input.ts +0 -48
- package/payload/platform/plugins/whatsapp-import/lib/tsconfig.json +0 -9
- package/payload/platform/plugins/whatsapp-import/lib/vitest.config.ts +0 -9
- package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import/references/conversation-archive-shape.md +0 -143
- package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import/references/export-parse.md +0 -109
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task 893 — `profile-update.personFields` is now an open `Record<string,
|
|
3
|
+
* unknown>` validated centrally by the schema-validator.
|
|
4
|
+
*
|
|
5
|
+
* These tests cover the wiring on `profileUpdate(...)` itself — proving
|
|
6
|
+
* that synonym + Forbidden Properties rejection fires at the tool surface,
|
|
7
|
+
* not just inside the validator unit. A future refactor that drops the
|
|
8
|
+
* `validateWrite(...)` call from `profile-update.ts` would silently bypass
|
|
9
|
+
* the central enforcement; these tests catch that.
|
|
10
|
+
*
|
|
11
|
+
* Validation runs in `mode: "update"` and throws BEFORE getSession() /
|
|
12
|
+
* embed() are called (Task 893's defensive ordering), so these tests do
|
|
13
|
+
* not need to mock neo4j-driver.
|
|
14
|
+
*/
|
|
15
|
+
import { describe, it, expect } from "vitest";
|
|
16
|
+
import { profileUpdate } from "../profile-update.js";
|
|
17
|
+
const ACCT = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee";
|
|
18
|
+
const USER = "user-893-validation";
|
|
19
|
+
function buildValidator() {
|
|
20
|
+
const schema = {
|
|
21
|
+
markdownLabels: new Map([
|
|
22
|
+
[
|
|
23
|
+
"Person",
|
|
24
|
+
{
|
|
25
|
+
label: "Person",
|
|
26
|
+
required: [
|
|
27
|
+
{ kind: "simple", name: "givenName" },
|
|
28
|
+
{ kind: "simple", name: "familyName" },
|
|
29
|
+
{ kind: "any-of", names: ["email", "telephone"] },
|
|
30
|
+
],
|
|
31
|
+
sourceFile: "schema-base.md",
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
]),
|
|
35
|
+
wrongToCorrect: new Map([
|
|
36
|
+
["phone", { correct: "telephone", sourceFile: "schema-base.md" }],
|
|
37
|
+
["firstName", { correct: "givenName", sourceFile: "schema-base.md" }],
|
|
38
|
+
]),
|
|
39
|
+
forbiddenByLabel: new Map([
|
|
40
|
+
[
|
|
41
|
+
"Person",
|
|
42
|
+
new Map([
|
|
43
|
+
[
|
|
44
|
+
"name",
|
|
45
|
+
{
|
|
46
|
+
rationale: "use givenName + familyName",
|
|
47
|
+
sourceFile: "schema-base.md",
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
]),
|
|
51
|
+
],
|
|
52
|
+
]),
|
|
53
|
+
sourceFiles: ["schema-base.md"],
|
|
54
|
+
};
|
|
55
|
+
const liveSource = {
|
|
56
|
+
recognisedLabels: () => new Set(["Person", "AdminUser"]),
|
|
57
|
+
liveLabels: () => new Set(["Person", "AdminUser"]),
|
|
58
|
+
declaredLabels: () => new Set(["Person", "AdminUser"]),
|
|
59
|
+
liveReady: () => true,
|
|
60
|
+
};
|
|
61
|
+
return { schema, liveSource, emit: () => { } };
|
|
62
|
+
}
|
|
63
|
+
describe("profile-update — personFields open Record + central validator (Task 893)", () => {
|
|
64
|
+
it("rejects synonym key (`phone`) before opening any session", async () => {
|
|
65
|
+
await expect(profileUpdate({
|
|
66
|
+
accountId: ACCT,
|
|
67
|
+
userId: USER,
|
|
68
|
+
category: "communication",
|
|
69
|
+
key: "preferredChannel",
|
|
70
|
+
value: "whatsapp",
|
|
71
|
+
personFields: { phone: "+447111111111" },
|
|
72
|
+
validator: buildValidator(),
|
|
73
|
+
})).rejects.toThrow(/property name 'phone' is not Schema\.org — use 'telephone'/);
|
|
74
|
+
});
|
|
75
|
+
it("rejects Forbidden Property `name` before opening any session", async () => {
|
|
76
|
+
await expect(profileUpdate({
|
|
77
|
+
accountId: ACCT,
|
|
78
|
+
userId: USER,
|
|
79
|
+
category: "communication",
|
|
80
|
+
key: "preferredChannel",
|
|
81
|
+
value: "whatsapp",
|
|
82
|
+
personFields: { name: "Joel Smalley" },
|
|
83
|
+
validator: buildValidator(),
|
|
84
|
+
})).rejects.toThrow(/'name' is not a valid Person property/);
|
|
85
|
+
});
|
|
86
|
+
it("loud-fails when personFields is non-empty but no validator is supplied", async () => {
|
|
87
|
+
// The tool surface (index.ts) closure-captures the validator at
|
|
88
|
+
// startup; a regression that drops it at the call site must throw
|
|
89
|
+
// rather than silently skip validation.
|
|
90
|
+
await expect(profileUpdate({
|
|
91
|
+
accountId: ACCT,
|
|
92
|
+
userId: USER,
|
|
93
|
+
category: "communication",
|
|
94
|
+
key: "preferredChannel",
|
|
95
|
+
value: "whatsapp",
|
|
96
|
+
personFields: { homeLocation: "London" },
|
|
97
|
+
// validator deliberately omitted
|
|
98
|
+
})).rejects.toThrow(/`personFields` requires the schema validator/);
|
|
99
|
+
});
|
|
100
|
+
it("loud-fails when LLM tries to overwrite system-managed Person properties (account-isolation guard)", async () => {
|
|
101
|
+
// Direct attack: agent passes `accountId: <other>` hoping `SET p +=
|
|
102
|
+
// $fields` will silently overwrite the row's account scope. The
|
|
103
|
+
// tool surface must reject before any Neo4j touch.
|
|
104
|
+
await expect(profileUpdate({
|
|
105
|
+
accountId: ACCT,
|
|
106
|
+
userId: USER,
|
|
107
|
+
category: "communication",
|
|
108
|
+
key: "preferredChannel",
|
|
109
|
+
value: "whatsapp",
|
|
110
|
+
personFields: { accountId: "ffffffff-ffff-ffff-ffff-ffffffffffff" },
|
|
111
|
+
validator: buildValidator(),
|
|
112
|
+
})).rejects.toThrow(/'accountId' is a system-managed Person property/);
|
|
113
|
+
// Same check for provenance-stamp tampering.
|
|
114
|
+
await expect(profileUpdate({
|
|
115
|
+
accountId: ACCT,
|
|
116
|
+
userId: USER,
|
|
117
|
+
category: "communication",
|
|
118
|
+
key: "preferredChannel",
|
|
119
|
+
value: "whatsapp",
|
|
120
|
+
personFields: { createdByAgent: "system" },
|
|
121
|
+
validator: buildValidator(),
|
|
122
|
+
})).rejects.toThrow(/'createdByAgent' is a system-managed Person property/);
|
|
123
|
+
});
|
|
124
|
+
it("personFields with all-empty-string values is treated as a no-op (no validator call required)", async () => {
|
|
125
|
+
// Hygiene strips empty strings BEFORE validate. If after hygiene
|
|
126
|
+
// there's nothing left, validation is skipped — no validator
|
|
127
|
+
// requirement, no throw, no Neo4j touch.
|
|
128
|
+
//
|
|
129
|
+
// We use category=communication + a non-empty Preference value so
|
|
130
|
+
// the function passes its base validations; then asserts that the
|
|
131
|
+
// hygiene-empty personFields does not trigger the validator-missing
|
|
132
|
+
// throw. The function will then proceed past the synchronous block
|
|
133
|
+
// into the Neo4j path which is unreachable in this test environment;
|
|
134
|
+
// we expect any thrown error to NOT be the "requires the schema
|
|
135
|
+
// validator" error.
|
|
136
|
+
await expect(profileUpdate({
|
|
137
|
+
accountId: ACCT,
|
|
138
|
+
userId: USER,
|
|
139
|
+
category: "communication",
|
|
140
|
+
key: "preferredChannel",
|
|
141
|
+
value: "whatsapp",
|
|
142
|
+
personFields: { homeLocation: "", knowsLanguage: " " },
|
|
143
|
+
// validator deliberately omitted — hygiene drops both keys, so
|
|
144
|
+
// the validator is never called.
|
|
145
|
+
})).rejects.not.toThrow(/requires the schema validator/);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
//# sourceMappingURL=profile-update-personfields-open.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-update-personfields-open.test.js","sourceRoot":"","sources":["../../../src/tools/__tests__/profile-update-personfields-open.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,51 +8,13 @@ export interface LinkedInConnectionRow {
|
|
|
8
8
|
/** ISO 8601 date (YYYY-MM-DD), parsed by the caller from "23 Apr 2026". */
|
|
9
9
|
connectedOn: string;
|
|
10
10
|
}
|
|
11
|
-
export
|
|
12
|
-
/** `whatsapp-export:<conversationId>:<lineHash>` — natural key for :Message. */
|
|
13
|
-
messageId: string;
|
|
14
|
-
/** Same value across all rows in one call. Asserted in normalisation. */
|
|
15
|
-
conversationId: string;
|
|
16
|
-
/** elementId of the :AdminUser or :Person who sent this message. */
|
|
17
|
-
senderNodeId: string;
|
|
18
|
-
/** Raw senderName as it appeared in the export — kept for audit, never used as a key. */
|
|
19
|
-
senderName: string;
|
|
20
|
-
/** ISO 8601 datetime (with timezone offset). Parser converts the `[DD/MM/YY, HH:MM:SS]` line prefix. */
|
|
21
|
-
dateSent: string;
|
|
22
|
-
body: string;
|
|
23
|
-
/** Position in the export file, 0-based. Tiebreaker for `dateSent` ordering when same-second timestamps exist. */
|
|
24
|
-
sequenceIndex: number;
|
|
25
|
-
}
|
|
26
|
-
export type ArchiveRow = LinkedInConnectionRow | WhatsAppExportRow;
|
|
27
|
-
/** Conversation block for archiveType='whatsapp-export'. */
|
|
28
|
-
export interface WhatsAppExportConversationBlock {
|
|
29
|
-
conversationId: string;
|
|
30
|
-
/** SHA-256 of the source `_chat.txt` (the raw bytes), prefixed for grep-ability. */
|
|
31
|
-
archiveSourceFile: string;
|
|
32
|
-
firstMessageAt: string;
|
|
33
|
-
lastMessageAt: string;
|
|
34
|
-
participantCount: number;
|
|
35
|
-
messageCount: number;
|
|
36
|
-
}
|
|
11
|
+
export type ArchiveRow = LinkedInConnectionRow;
|
|
37
12
|
export interface ArchiveWriteParams {
|
|
38
13
|
archiveType: string;
|
|
39
14
|
ownerNodeId: string;
|
|
40
15
|
accountId: string;
|
|
41
16
|
rows: ArchiveRow[];
|
|
42
17
|
sessionId?: string;
|
|
43
|
-
/** Required when archiveType='whatsapp-export'; ignored otherwise. */
|
|
44
|
-
conversation?: WhatsAppExportConversationBlock;
|
|
45
|
-
/** Required when archiveType='whatsapp-export'; ignored otherwise. */
|
|
46
|
-
participantNodeIds?: string[];
|
|
47
|
-
/**
|
|
48
|
-
* Required when archiveType='whatsapp-export'. Operator-supplied path to the
|
|
49
|
-
* source `_chat.txt`. The server re-computes `sha256(file)` and asserts it
|
|
50
|
-
* matches `conversation.archiveSourceFile` before any write — defence in
|
|
51
|
-
* depth against the agent submitting parsed rows for one file together with
|
|
52
|
-
* a stale conversation block from another. Closes the silent-substitution
|
|
53
|
-
* window (Task 805).
|
|
54
|
-
*/
|
|
55
|
-
archiveFilePath?: string;
|
|
56
18
|
}
|
|
57
19
|
export interface ArchiveWriteResult {
|
|
58
20
|
archiveType: string;
|
|
@@ -89,12 +51,4 @@ export interface ArchiveHandlerFinalizeResult {
|
|
|
89
51
|
export declare function memoryArchiveWrite(params: ArchiveWriteParams): Promise<ArchiveWriteResult>;
|
|
90
52
|
export declare const PERSON_AND_CONNECTED_EDGE_CYPHER = "\nMATCH (owner) WHERE elementId(owner) = $ownerNodeId\nWITH owner, $rows AS rows\nUNWIND rows AS row\nMERGE (p:Person {linkedinUrl: row.linkedinUrl})\n ON CREATE SET\n p.accountId = $accountId,\n p.source = 'linkedin',\n p.createdByAgent = 'linkedin-import',\n p.createdBySource = 'linkedin-import',\n p.createdBySession = $sessionId,\n p.createdAt = datetime(),\n p.scope = 'admin'\nSET\n p.givenName = row.givenName,\n p.familyName = row.familyName,\n p.currentTitle = row.title\nFOREACH (_ IN CASE WHEN row.email IS NOT NULL AND row.email <> '' THEN [1] ELSE [] END |\n SET p.email = row.email\n)\nMERGE (owner)-[c:CONNECTED_ON_LINKEDIN]->(p)\n ON CREATE SET\n c.connectedOn = date(row.connectedOn),\n c.source = 'linkedin',\n c.createdAt = datetime()\nRETURN count(*) AS processed\n";
|
|
91
53
|
export declare const ORG_AND_WORKS_FOR_CYPHER = "\nUNWIND $rows AS row\nWITH row WHERE row.company IS NOT NULL AND row.company <> ''\nMATCH (p:Person {linkedinUrl: row.linkedinUrl})\nMERGE (o:Organization {accountId: $accountId, name: row.company})\n ON CREATE SET\n o.source = 'linkedin',\n o.createdByAgent = 'linkedin-import',\n o.createdBySource = 'linkedin-import',\n o.createdBySession = $sessionId,\n o.createdAt = datetime(),\n o.scope = 'admin'\nMERGE (p)-[w:WORKS_FOR]->(o)\n ON CREATE SET\n w.title = row.title,\n w.source = 'linkedin',\n w.current = true,\n w.createdAt = datetime()\n ON MATCH SET\n w.title = coalesce(row.title, w.title)\nRETURN count(*) AS processed\n";
|
|
92
|
-
export declare const WHATSAPP_CONVERSATION_AND_MESSAGES_CYPHER = "\nMATCH (owner) WHERE elementId(owner) = $ownerNodeId\nWITH owner, $rows AS rows, $conversation AS conv\nMERGE (c:Conversation {conversationId: conv.conversationId})\n ON CREATE SET\n c:WhatsAppConversation,\n c.accountId = $accountId,\n c.source = 'whatsapp',\n c.createdByAgent = 'whatsapp-import',\n c.createdBySource = 'whatsapp-import',\n c.createdBySession = $sessionId,\n c.createdAt = datetime(),\n c.scope = 'admin',\n c.agentType = 'admin',\n c.archiveSourceFile = conv.archiveSourceFile,\n c.firstMessageAt = datetime(conv.firstMessageAt),\n c.lastMessageAt = datetime(conv.lastMessageAt),\n c.participantCount = conv.participantCount,\n c.messageCount = conv.messageCount\n ON MATCH SET\n c:WhatsAppConversation,\n c.lastMessageAt = datetime(conv.lastMessageAt),\n c.participantCount = conv.participantCount,\n c.messageCount = conv.messageCount,\n c.lastImportedAt = datetime(),\n c.lastImportedBySession = $sessionId\nWITH owner, c, rows\nUNWIND rows AS row\nMATCH (sender) WHERE elementId(sender) = row.senderNodeId\nMERGE (m:Message {messageId: row.messageId})\n ON CREATE SET\n m:WhatsAppMessage,\n m.accountId = $accountId,\n m.source = 'whatsapp',\n m.createdByAgent = 'whatsapp-import',\n m.createdBySource = 'whatsapp-import',\n m.createdBySession = $sessionId,\n m.createdAt = datetime(),\n m.conversationId = row.conversationId,\n m.dateSent = datetime(row.dateSent),\n m.body = row.body,\n m.senderName = row.senderName,\n m.sequenceIndex = row.sequenceIndex,\n m.scope = 'admin'\nMERGE (m)-[:PART_OF]->(c)\nMERGE (sender)-[s:SENT]->(m)\n ON CREATE SET\n s.source = 'whatsapp',\n s.createdAt = datetime()\nMERGE (sender)-[p:PARTICIPANT_IN]->(c)\n ON CREATE SET\n p.source = 'whatsapp',\n p.createdAt = datetime()\nRETURN count(*) AS processed\n";
|
|
93
|
-
export declare const WHATSAPP_NEXT_CHAIN_CYPHER = "\nMATCH (c:Conversation:WhatsAppConversation {conversationId: $conversationId})\nMATCH (m:Message)-[:PART_OF]->(c)\nWITH c, m ORDER BY m.dateSent ASC, m.sequenceIndex ASC, m.messageId ASC\nWITH c, collect(m) AS msgs\nUNWIND range(0, size(msgs) - 2) AS i\nWITH msgs[i] AS prev, msgs[i + 1] AS next\nWHERE prev <> next\nMERGE (prev)-[r:NEXT]->(next)\n ON CREATE SET\n r.source = 'whatsapp',\n r.createdAt = datetime()\nRETURN count(r) AS nextEdges\n";
|
|
94
|
-
/**
|
|
95
|
-
* Re-compute `whatsapp-export:<sha256>` from the file at `archiveFilePath`
|
|
96
|
-
* and assert it matches `expectedArchiveSourceFile`. Throws with a named
|
|
97
|
-
* mismatch error before any Cypher runs.
|
|
98
|
-
*/
|
|
99
|
-
export declare function verifyArchiveSourceFileHash(archiveFilePath: string, expectedArchiveSourceFile: string): void;
|
|
100
54
|
//# 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":"
|
|
1
|
+
{"version":3,"file":"memory-archive-write.d.ts","sourceRoot":"","sources":["../../src/tools/memory-archive-write.ts"],"names":[],"mappings":"AA8BA,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,MAAM,MAAM,UAAU,GAAG,qBAAqB,CAAC;AAE/C,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,UAAU,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,oFAAoF;IACpF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpD,gEAAgE;IAChE,eAAe,CAAC,EAAE,IAAI,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;IAC1D,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAMD,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,SAAS,EAAE,UAAU,EAAE,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,6BAA6B;IAC5C,MAAM,EAAE,kBAAkB,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB;wEACoE;IACpE,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;4DACwD;IACxD,MAAM,EAAE,IAAI,GAAG,SAAS,GAAG,SAAS,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAqBD,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,kBAAkB,CAAC,CA2F7B;AAYD,eAAO,MAAM,gCAAgC,m3BA0B5C,CAAC;AAEF,eAAO,MAAM,wBAAwB,8sBAqBpC,CAAC"}
|
|
@@ -1,39 +1,27 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
|
-
import { readFileSync } from "node:fs";
|
|
3
1
|
import { getSession } from "../lib/neo4j.js";
|
|
4
2
|
/**
|
|
5
|
-
* memory-archive-write — deterministic bulk-archive write surface
|
|
3
|
+
* memory-archive-write — deterministic bulk-archive write surface for flat
|
|
4
|
+
* datasets only (LinkedIn Connections.csv and future CRM-type seeds).
|
|
6
5
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
6
|
+
* Distinct from memory-write (per-node, adjacency-required) and memory-ingest
|
|
7
|
+
* (narrative document → Section / ConversationArchive). Conversation
|
|
8
|
+
* transcripts (WhatsApp, Telegram, Signal, …) flow through the
|
|
9
|
+
* `conversation-archive` skill instead, which writes :ConversationArchive
|
|
10
|
+
* + :Section:Conversation chunks via memory-ingest — see Task 894.
|
|
11
11
|
*
|
|
12
12
|
* Doctrine:
|
|
13
13
|
* - The Cypher body for each archiveType is fixed inside this tool.
|
|
14
14
|
* The agent supplies parsed rows + the archiveType discriminant,
|
|
15
15
|
* never raw Cypher.
|
|
16
|
-
* - 500-row UNWIND batches per executeWrite transaction.
|
|
17
|
-
* batches risk Neo4j Community heap pressure on a Pi 5.
|
|
16
|
+
* - 500-row UNWIND batches per executeWrite transaction.
|
|
18
17
|
* - Per-node provenance stamps (createdByAgent, createdBySession,
|
|
19
18
|
* source, createdAt) come from this server, not the agent.
|
|
20
|
-
* - Owner / participant nodes match by elementId so both :AdminUser
|
|
21
|
-
* and external :Person flow through one path.
|
|
22
19
|
* - Counters are per-handler — each handler picks the keys that
|
|
23
|
-
* describe its archiveType.
|
|
24
|
-
* JSON; nothing programmatic depends on the linkedin-specific
|
|
25
|
-
* legacy field names.
|
|
26
|
-
* - For archive types with cross-batch graph state (WhatsApp's
|
|
27
|
-
* :NEXT chronology), the handler implements an optional
|
|
28
|
-
* `finalize` hook that runs after all batches in its own
|
|
29
|
-
* `executeWrite` transaction. Failure surfaces as
|
|
30
|
-
* `nextChainStatus='failed'` on the result — never silent partial
|
|
31
|
-
* state.
|
|
20
|
+
* describe its archiveType.
|
|
32
21
|
*/
|
|
33
22
|
const BATCH_SIZE = 500;
|
|
34
23
|
const HANDLERS = {
|
|
35
24
|
"linkedin-connections": linkedinConnectionsHandler(),
|
|
36
|
-
"whatsapp-export": whatsappExportHandler(),
|
|
37
25
|
};
|
|
38
26
|
// ---------------------------------------------------------------------------
|
|
39
27
|
// Entry point
|
|
@@ -240,301 +228,4 @@ function normaliseLinkedinRow(row) {
|
|
|
240
228
|
connectedOn: row.connectedOn,
|
|
241
229
|
};
|
|
242
230
|
}
|
|
243
|
-
// ---------------------------------------------------------------------------
|
|
244
|
-
// whatsapp-export handler (Task 804)
|
|
245
|
-
// ---------------------------------------------------------------------------
|
|
246
|
-
//
|
|
247
|
-
// Owner anchor: the operator who exported the chat (:AdminUser or :Person).
|
|
248
|
-
// Recorded as `createdBySession`-stamped provenance on the Conversation node;
|
|
249
|
-
// not a graph edge, since the exporter is metadata, not a semantic role.
|
|
250
|
-
//
|
|
251
|
-
// Per call the input expresses one Conversation + N Messages + edges:
|
|
252
|
-
// 1. (:Conversation:WhatsAppConversation {conversationId}) — MERGE, sublabel on first create
|
|
253
|
-
// 2. (:Message:WhatsAppMessage {messageId})-[:PART_OF]->(:Conversation)
|
|
254
|
-
// 3. (sender:AdminUser|:Person {elementId})-[:SENT]->(:Message)
|
|
255
|
-
// 4. (sender)-[:PARTICIPANT_IN]->(:Conversation) — rolled up per distinct sender
|
|
256
|
-
// 5. (:Message)-[:NEXT]->(:Message) — chronology, finalize step
|
|
257
|
-
//
|
|
258
|
-
// Natural keys:
|
|
259
|
-
// :Conversation:WhatsAppConversation — conversationId (whatsapp-export:<sha256(file)>:<accountId>)
|
|
260
|
-
// :Message:WhatsAppMessage — messageId (whatsapp-export:<conversationId>:<lineHash>)
|
|
261
|
-
// participants — elementId resolved by the skill's confirmation flow
|
|
262
|
-
//
|
|
263
|
-
// Provenance stamped on every node: source='whatsapp', createdByAgent='whatsapp-import',
|
|
264
|
-
// createdBySession=$sessionId, createdAt=datetime(), archiveSourceFile=<sha256 prefix>.
|
|
265
|
-
// On re-import, ON MATCH refreshes lastMessageAt / messageCount / participantCount /
|
|
266
|
-
// lastImportedAt / lastImportedBySession on the Conversation only — node-creation
|
|
267
|
-
// stamps are preserved.
|
|
268
|
-
//
|
|
269
|
-
// Cross-batch state: NEXT chain depends on full-conversation chronology. The
|
|
270
|
-
// finalize hook runs ORDER BY dateSent ASC, sequenceIndex ASC, then MERGEs
|
|
271
|
-
// pairwise NEXT edges. Idempotent — re-import with a 50-message append adds
|
|
272
|
-
// 50 NEXT edges and updates conversation scalars, no duplicates.
|
|
273
|
-
// ---------------------------------------------------------------------------
|
|
274
|
-
// MERGE on the base label only, then SET the sublabel in ON CREATE — Task 633
|
|
275
|
-
// pattern documented at platform/neo4j/schema.cypher:374-388 and used by
|
|
276
|
-
// `ensureConversation` in platform/ui/app/lib/neo4j-store.ts. MERGEing on
|
|
277
|
-
// `:Base:Sublabel` directly would refuse to match a pre-existing node that
|
|
278
|
-
// carries only the base label, then CREATE a duplicate that violates the
|
|
279
|
-
// `conversationId IS UNIQUE` constraint on `:Conversation`. The base+SET
|
|
280
|
-
// pattern is constraint-safe and idempotent across Task-633-style sublabel
|
|
281
|
-
// backfill histories.
|
|
282
|
-
export const WHATSAPP_CONVERSATION_AND_MESSAGES_CYPHER = `
|
|
283
|
-
MATCH (owner) WHERE elementId(owner) = $ownerNodeId
|
|
284
|
-
WITH owner, $rows AS rows, $conversation AS conv
|
|
285
|
-
MERGE (c:Conversation {conversationId: conv.conversationId})
|
|
286
|
-
ON CREATE SET
|
|
287
|
-
c:WhatsAppConversation,
|
|
288
|
-
c.accountId = $accountId,
|
|
289
|
-
c.source = 'whatsapp',
|
|
290
|
-
c.createdByAgent = 'whatsapp-import',
|
|
291
|
-
c.createdBySource = 'whatsapp-import',
|
|
292
|
-
c.createdBySession = $sessionId,
|
|
293
|
-
c.createdAt = datetime(),
|
|
294
|
-
c.scope = 'admin',
|
|
295
|
-
c.agentType = 'admin',
|
|
296
|
-
c.archiveSourceFile = conv.archiveSourceFile,
|
|
297
|
-
c.firstMessageAt = datetime(conv.firstMessageAt),
|
|
298
|
-
c.lastMessageAt = datetime(conv.lastMessageAt),
|
|
299
|
-
c.participantCount = conv.participantCount,
|
|
300
|
-
c.messageCount = conv.messageCount
|
|
301
|
-
ON MATCH SET
|
|
302
|
-
c:WhatsAppConversation,
|
|
303
|
-
c.lastMessageAt = datetime(conv.lastMessageAt),
|
|
304
|
-
c.participantCount = conv.participantCount,
|
|
305
|
-
c.messageCount = conv.messageCount,
|
|
306
|
-
c.lastImportedAt = datetime(),
|
|
307
|
-
c.lastImportedBySession = $sessionId
|
|
308
|
-
WITH owner, c, rows
|
|
309
|
-
UNWIND rows AS row
|
|
310
|
-
MATCH (sender) WHERE elementId(sender) = row.senderNodeId
|
|
311
|
-
MERGE (m:Message {messageId: row.messageId})
|
|
312
|
-
ON CREATE SET
|
|
313
|
-
m:WhatsAppMessage,
|
|
314
|
-
m.accountId = $accountId,
|
|
315
|
-
m.source = 'whatsapp',
|
|
316
|
-
m.createdByAgent = 'whatsapp-import',
|
|
317
|
-
m.createdBySource = 'whatsapp-import',
|
|
318
|
-
m.createdBySession = $sessionId,
|
|
319
|
-
m.createdAt = datetime(),
|
|
320
|
-
m.conversationId = row.conversationId,
|
|
321
|
-
m.dateSent = datetime(row.dateSent),
|
|
322
|
-
m.body = row.body,
|
|
323
|
-
m.senderName = row.senderName,
|
|
324
|
-
m.sequenceIndex = row.sequenceIndex,
|
|
325
|
-
m.scope = 'admin'
|
|
326
|
-
MERGE (m)-[:PART_OF]->(c)
|
|
327
|
-
MERGE (sender)-[s:SENT]->(m)
|
|
328
|
-
ON CREATE SET
|
|
329
|
-
s.source = 'whatsapp',
|
|
330
|
-
s.createdAt = datetime()
|
|
331
|
-
MERGE (sender)-[p:PARTICIPANT_IN]->(c)
|
|
332
|
-
ON CREATE SET
|
|
333
|
-
p.source = 'whatsapp',
|
|
334
|
-
p.createdAt = datetime()
|
|
335
|
-
RETURN count(*) AS processed
|
|
336
|
-
`;
|
|
337
|
-
// Tertiary tiebreaker `m.messageId ASC` makes ordering total even when two
|
|
338
|
-
// messages share the same dateSent + sequenceIndex (operator-error duplicate
|
|
339
|
-
// row in input, or two messages emitted in the same second by the same
|
|
340
|
-
// sender). Without it, Neo4j's ordering of equal keys is undefined and the
|
|
341
|
-
// chain topology can drift across re-imports — MERGE on (prev, next) is
|
|
342
|
-
// idempotent per pair, but pairs themselves would shuffle.
|
|
343
|
-
export const WHATSAPP_NEXT_CHAIN_CYPHER = `
|
|
344
|
-
MATCH (c:Conversation:WhatsAppConversation {conversationId: $conversationId})
|
|
345
|
-
MATCH (m:Message)-[:PART_OF]->(c)
|
|
346
|
-
WITH c, m ORDER BY m.dateSent ASC, m.sequenceIndex ASC, m.messageId ASC
|
|
347
|
-
WITH c, collect(m) AS msgs
|
|
348
|
-
UNWIND range(0, size(msgs) - 2) AS i
|
|
349
|
-
WITH msgs[i] AS prev, msgs[i + 1] AS next
|
|
350
|
-
WHERE prev <> next
|
|
351
|
-
MERGE (prev)-[r:NEXT]->(next)
|
|
352
|
-
ON CREATE SET
|
|
353
|
-
r.source = 'whatsapp',
|
|
354
|
-
r.createdAt = datetime()
|
|
355
|
-
RETURN count(r) AS nextEdges
|
|
356
|
-
`;
|
|
357
|
-
function whatsappExportHandler() {
|
|
358
|
-
return {
|
|
359
|
-
async verifyArchive(session, params) {
|
|
360
|
-
const { ownerNodeId, accountId, conversation, participantNodeIds, rows, archiveFilePath } = params;
|
|
361
|
-
if (!conversation || !conversation.conversationId) {
|
|
362
|
-
throw new Error("whatsapp-export: `conversation` block with conversationId is required.");
|
|
363
|
-
}
|
|
364
|
-
if (!Array.isArray(participantNodeIds) || participantNodeIds.length === 0) {
|
|
365
|
-
throw new Error("whatsapp-export: `participantNodeIds` must be a non-empty array (operator-confirmed senders).");
|
|
366
|
-
}
|
|
367
|
-
if (!archiveFilePath || !archiveFilePath.trim()) {
|
|
368
|
-
throw new Error("whatsapp-export: `archiveFilePath` is required (Task 805) — the server recomputes sha256 from the file and asserts it matches conversation.archiveSourceFile.");
|
|
369
|
-
}
|
|
370
|
-
// Hash gate (Task 805). Re-compute sha256 from the operator-supplied
|
|
371
|
-
// path and compare against the conversation block's archiveSourceFile.
|
|
372
|
-
// Mismatch is a hard reject before any Cypher runs — closes the
|
|
373
|
-
// silent-substitution window where the agent could pair rows[] for
|
|
374
|
-
// one file with a stale conversation block from another.
|
|
375
|
-
verifyArchiveSourceFileHash(archiveFilePath, conversation.archiveSourceFile);
|
|
376
|
-
// Cross-row conversationId invariant: one call = one conversation.
|
|
377
|
-
for (let i = 0; i < rows.length; i++) {
|
|
378
|
-
const row = rows[i];
|
|
379
|
-
if (row.conversationId !== conversation.conversationId) {
|
|
380
|
-
throw new Error(`whatsapp-export: row[${i}].conversationId="${row.conversationId}" mismatches conversation.conversationId="${conversation.conversationId}". One archive-write call writes exactly one conversation.`);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
// Owner verification (mirrors linkedin-connections logic).
|
|
384
|
-
const ownerRes = await session.run(`MATCH (n) WHERE elementId(n) = $ownerNodeId
|
|
385
|
-
RETURN labels(n) AS labels, n.accountId AS accountId LIMIT 1`, { ownerNodeId });
|
|
386
|
-
if (ownerRes.records.length === 0) {
|
|
387
|
-
throw new Error(`ownerNodeId ${ownerNodeId} not found. Re-run the archive-owner confirmation flow before invoking memory-archive-write.`);
|
|
388
|
-
}
|
|
389
|
-
const ownerLabels = ownerRes.records[0].get("labels") ?? [];
|
|
390
|
-
const ownerAccountId = ownerRes.records[0].get("accountId");
|
|
391
|
-
if (!ownerLabels.includes("AdminUser") && !ownerLabels.includes("Person")) {
|
|
392
|
-
throw new Error(`ownerNodeId ${ownerNodeId} has labels [${ownerLabels.join(", ")}]; expected :AdminUser or :Person.`);
|
|
393
|
-
}
|
|
394
|
-
if (ownerAccountId && ownerAccountId !== accountId) {
|
|
395
|
-
throw new Error(`ownerNodeId ${ownerNodeId} belongs to account ${ownerAccountId}, not ${accountId}. Cross-account archive ingest refused.`);
|
|
396
|
-
}
|
|
397
|
-
// Participant verification: every senderNodeId must resolve to :AdminUser
|
|
398
|
-
// or :Person in the same accountId. Distinct in case the skill passed
|
|
399
|
-
// the same nodeId twice. Log when dedup collapses the array — two
|
|
400
|
-
// distinct senderNames mapping to the same elementId is operator-confirmed
|
|
401
|
-
// intent (Step 4 phone-vs-name same-person heuristic), but a silent
|
|
402
|
-
// collapse without a log line hides the merge from the audit trail.
|
|
403
|
-
const distinctParticipantIds = Array.from(new Set(participantNodeIds));
|
|
404
|
-
if (distinctParticipantIds.length !== participantNodeIds.length) {
|
|
405
|
-
process.stderr.write(`[memory-archive-write] participantNodeIds-deduped archiveType=whatsapp-export submitted=${participantNodeIds.length} distinct=${distinctParticipantIds.length}\n`);
|
|
406
|
-
}
|
|
407
|
-
const participantRes = await session.run(`UNWIND $ids AS id
|
|
408
|
-
MATCH (n) WHERE elementId(n) = id
|
|
409
|
-
RETURN id AS elemId, labels(n) AS labels, n.accountId AS accountId`, { ids: distinctParticipantIds });
|
|
410
|
-
const found = new Set();
|
|
411
|
-
const rejected = [];
|
|
412
|
-
for (const record of participantRes.records) {
|
|
413
|
-
const elemId = record.get("elemId");
|
|
414
|
-
const labels = record.get("labels") ?? [];
|
|
415
|
-
const acct = record.get("accountId");
|
|
416
|
-
found.add(elemId);
|
|
417
|
-
if (!labels.includes("AdminUser") && !labels.includes("Person")) {
|
|
418
|
-
rejected.push(`${elemId}: labels=[${labels.join(",")}] (expected :AdminUser or :Person)`);
|
|
419
|
-
continue;
|
|
420
|
-
}
|
|
421
|
-
if (acct && acct !== accountId) {
|
|
422
|
-
rejected.push(`${elemId}: accountId=${acct} (expected ${accountId})`);
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
for (const id of distinctParticipantIds) {
|
|
426
|
-
if (!found.has(id))
|
|
427
|
-
rejected.push(`${id}: not found`);
|
|
428
|
-
}
|
|
429
|
-
const ok = distinctParticipantIds.length - rejected.length;
|
|
430
|
-
process.stderr.write(`[memory-archive-write] verifyParticipants archiveType=whatsapp-export ok=${ok} rejected=${rejected.length}\n`);
|
|
431
|
-
if (rejected.length > 0) {
|
|
432
|
-
throw new Error(`whatsapp-export: ${rejected.length} participant(s) failed verification: ${rejected.join("; ")}. Re-run the participant confirmation flow.`);
|
|
433
|
-
}
|
|
434
|
-
},
|
|
435
|
-
async writeBatch(session, ctx) {
|
|
436
|
-
const { params, batchRows, sessionId } = ctx;
|
|
437
|
-
const queryParams = {
|
|
438
|
-
ownerNodeId: params.ownerNodeId,
|
|
439
|
-
accountId: params.accountId,
|
|
440
|
-
sessionId,
|
|
441
|
-
conversation: params.conversation,
|
|
442
|
-
rows: batchRows.map((r) => normaliseWhatsappRow(r)),
|
|
443
|
-
};
|
|
444
|
-
return await session.executeWrite(async (tx) => {
|
|
445
|
-
const res = await tx.run(WHATSAPP_CONVERSATION_AND_MESSAGES_CYPHER, queryParams);
|
|
446
|
-
const stats = res.summary.counters.updates();
|
|
447
|
-
// Task 887 §B' — per-batch counters reflect exactly what Neo4j's
|
|
448
|
-
// summary reports. The pre-887 shape carried `createdSentEdges` and
|
|
449
|
-
// `createdParticipantEdges` as constant 0 — a stale bookkeeper that
|
|
450
|
-
// contradicted `relationshipsCreated=N` from the same row. Decomposing
|
|
451
|
-
// per-edge-type would need separate Cypher passes per row; the
|
|
452
|
-
// brief's success-criterion #5 accepts removal as the parity fix.
|
|
453
|
-
// Keeps `createdMessages` (from `nodesCreated`, accurate) and
|
|
454
|
-
// `relationshipsCreated` (sum of :PART_OF + :SENT + :PARTICIPANT_IN
|
|
455
|
-
// creations, authoritative). `labelsAdded` retained for the
|
|
456
|
-
// sublabel-promotion audit on first WhatsApp import.
|
|
457
|
-
return {
|
|
458
|
-
createdMessages: stats.nodesCreated,
|
|
459
|
-
relationshipsCreated: stats.relationshipsCreated,
|
|
460
|
-
labelsAdded: stats.labelsAdded,
|
|
461
|
-
};
|
|
462
|
-
});
|
|
463
|
-
},
|
|
464
|
-
async finalize(session, ctx) {
|
|
465
|
-
const { params, hadBatchErrors } = ctx;
|
|
466
|
-
const conversationId = params.conversation?.conversationId;
|
|
467
|
-
if (!conversationId) {
|
|
468
|
-
return { counters: {}, status: "skipped", reason: "no conversationId" };
|
|
469
|
-
}
|
|
470
|
-
const result = await session.executeWrite(async (tx) => {
|
|
471
|
-
const res = await tx.run(WHATSAPP_NEXT_CHAIN_CYPHER, { conversationId });
|
|
472
|
-
const stats = res.summary.counters.updates();
|
|
473
|
-
const nextEdges = res.records[0]?.get("nextEdges") ?? 0;
|
|
474
|
-
const nextEdgeCount = typeof nextEdges === "number"
|
|
475
|
-
? nextEdges
|
|
476
|
-
: typeof nextEdges?.toNumber === "function"
|
|
477
|
-
? nextEdges.toNumber()
|
|
478
|
-
: 0;
|
|
479
|
-
return {
|
|
480
|
-
counters: {
|
|
481
|
-
nextEdgesProcessed: nextEdgeCount,
|
|
482
|
-
nextEdgesCreated: stats.relationshipsCreated,
|
|
483
|
-
},
|
|
484
|
-
status: (hadBatchErrors ? "partial" : "ok"),
|
|
485
|
-
reason: hadBatchErrors ? "one or more batches reported errors; NEXT chain rebuilt over written messages" : undefined,
|
|
486
|
-
};
|
|
487
|
-
});
|
|
488
|
-
return result;
|
|
489
|
-
},
|
|
490
|
-
};
|
|
491
|
-
}
|
|
492
|
-
function normaliseWhatsappRow(row) {
|
|
493
|
-
if (!row.messageId || !row.messageId.trim()) {
|
|
494
|
-
throw new Error("whatsapp-export row missing messageId (natural key).");
|
|
495
|
-
}
|
|
496
|
-
if (!row.conversationId || !row.conversationId.trim()) {
|
|
497
|
-
throw new Error("whatsapp-export row missing conversationId.");
|
|
498
|
-
}
|
|
499
|
-
if (!row.senderNodeId || !row.senderNodeId.trim()) {
|
|
500
|
-
throw new Error("whatsapp-export row missing senderNodeId (operator-confirmed sender).");
|
|
501
|
-
}
|
|
502
|
-
if (!row.dateSent || Number.isNaN(Date.parse(row.dateSent))) {
|
|
503
|
-
throw new Error(`whatsapp-export row dateSent="${row.dateSent}" is not parseable as ISO 8601. Parser must convert the [DD/MM/YY, HH:MM:SS] line prefix to ISO 8601 with timezone.`);
|
|
504
|
-
}
|
|
505
|
-
if (typeof row.sequenceIndex !== "number" || row.sequenceIndex < 0) {
|
|
506
|
-
throw new Error(`whatsapp-export row sequenceIndex="${row.sequenceIndex}" must be a non-negative number.`);
|
|
507
|
-
}
|
|
508
|
-
return {
|
|
509
|
-
messageId: row.messageId.trim(),
|
|
510
|
-
conversationId: row.conversationId.trim(),
|
|
511
|
-
senderNodeId: row.senderNodeId.trim(),
|
|
512
|
-
senderName: (row.senderName ?? "").trim(),
|
|
513
|
-
dateSent: row.dateSent,
|
|
514
|
-
body: row.body ?? "",
|
|
515
|
-
sequenceIndex: row.sequenceIndex,
|
|
516
|
-
};
|
|
517
|
-
}
|
|
518
|
-
// ---------------------------------------------------------------------------
|
|
519
|
-
// Hash gate (Task 805) — exported for unit testing.
|
|
520
|
-
// ---------------------------------------------------------------------------
|
|
521
|
-
/**
|
|
522
|
-
* Re-compute `whatsapp-export:<sha256>` from the file at `archiveFilePath`
|
|
523
|
-
* and assert it matches `expectedArchiveSourceFile`. Throws with a named
|
|
524
|
-
* mismatch error before any Cypher runs.
|
|
525
|
-
*/
|
|
526
|
-
export function verifyArchiveSourceFileHash(archiveFilePath, expectedArchiveSourceFile) {
|
|
527
|
-
let actualHash;
|
|
528
|
-
try {
|
|
529
|
-
const fileBytes = readFileSync(archiveFilePath);
|
|
530
|
-
actualHash = `whatsapp-export:${createHash("sha256").update(fileBytes).digest("hex")}`;
|
|
531
|
-
}
|
|
532
|
-
catch (err) {
|
|
533
|
-
throw new Error(`whatsapp-export: failed to read archiveFilePath="${archiveFilePath}": ${err instanceof Error ? err.message : String(err)}`);
|
|
534
|
-
}
|
|
535
|
-
if (actualHash !== expectedArchiveSourceFile) {
|
|
536
|
-
process.stderr.write(`[memory-archive-write] archiveSourceFile-hash-mismatch operator=${expectedArchiveSourceFile} actual=${actualHash}\n`);
|
|
537
|
-
throw new Error(`whatsapp-export: archiveSourceFile hash mismatch — operator-supplied="${expectedArchiveSourceFile}" actual="${actualHash}". The parser was run on a different file than archiveFilePath; re-run whatsapp-export-parse.`);
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
231
|
//# sourceMappingURL=memory-archive-write.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-archive-write.js","sourceRoot":"","sources":["../../src/tools/memory-archive-write.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"memory-archive-write.js","sourceRoot":"","sources":["../../src/tools/memory-archive-write.ts"],"names":[],"mappings":"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"}
|