@rubytech/create-realagent 1.0.828 → 1.0.829

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.
Files changed (72) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/neo4j/schema.cypher +2 -1
  3. package/payload/platform/package.json +2 -2
  4. package/payload/platform/plugins/admin/hooks/__tests__/archive-ingest-surface-gate.test.sh +39 -54
  5. package/payload/platform/plugins/admin/hooks/archive-ingest-surface-gate.sh +26 -58
  6. package/payload/platform/plugins/admin/skills/onboarding/SKILL.md +2 -2
  7. package/payload/platform/plugins/docs/references/plugins-guide.md +1 -1
  8. package/payload/platform/plugins/memory/PLUGIN.md +4 -4
  9. package/payload/platform/plugins/memory/mcp/dist/index.js +18 -218
  10. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  11. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js +103 -0
  12. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js.map +1 -1
  13. package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.d.ts.map +1 -1
  14. package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.js +30 -20
  15. package/payload/platform/plugins/memory/mcp/dist/lib/llm-classifier.js.map +1 -1
  16. package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.d.ts +16 -1
  17. package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.d.ts.map +1 -1
  18. package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.js +12 -3
  19. package/payload/platform/plugins/memory/mcp/dist/lib/schema-validator.js.map +1 -1
  20. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js +2 -138
  21. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write.test.js.map +1 -1
  22. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.js +10 -5
  23. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.js.map +1 -1
  24. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.d.ts +2 -0
  25. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.d.ts.map +1 -0
  26. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.js +148 -0
  27. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.js.map +1 -0
  28. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts +1 -64
  29. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts.map +1 -1
  30. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js +6 -336
  31. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
  32. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts +7 -11
  33. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts.map +1 -1
  34. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +1 -11
  35. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
  36. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts +21 -17
  37. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts.map +1 -1
  38. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js +77 -37
  39. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -1
  40. package/payload/platform/plugins/memory/references/schema-base.md +2 -0
  41. package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +54 -4
  42. package/payload/platform/plugins/whatsapp/PLUGIN.md +1 -1
  43. package/payload/platform/scripts/seed-neo4j.sh +15 -14
  44. package/payload/platform/templates/specialists/agents/database-operator.md +9 -15
  45. package/payload/server/chunk-CUSH3UXP.js +2305 -0
  46. package/payload/server/chunk-IWNDVGKT.js +10077 -0
  47. package/payload/server/chunk-KC7NUABI.js +654 -0
  48. package/payload/server/chunk-WUVXPZIV.js +1116 -0
  49. package/payload/server/client-pool-3TM3SRIA.js +32 -0
  50. package/payload/server/cloudflare-task-tracker-4NIODMGL.js +19 -0
  51. package/payload/server/maxy-edge.js +3 -3
  52. package/payload/server/neo4j-migrations-XTQ4WEV6.js +428 -0
  53. package/payload/server/server.js +6 -6
  54. package/payload/platform/plugins/whatsapp-import/PLUGIN.md +0 -48
  55. package/payload/platform/plugins/whatsapp-import/bin/ingest.mjs +0 -617
  56. package/payload/platform/plugins/whatsapp-import/bin/whatsapp-ingest.sh +0 -98
  57. package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/delta-append.test.ts +0 -163
  58. package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/parse-export-lrm.test.ts +0 -83
  59. package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/parse-export.test.ts +0 -678
  60. package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/sessionize.test.ts +0 -91
  61. package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/to-classifier-input.test.ts +0 -59
  62. package/payload/platform/plugins/whatsapp-import/lib/src/delta-cursor.ts +0 -54
  63. package/payload/platform/plugins/whatsapp-import/lib/src/derive-keys.ts +0 -82
  64. package/payload/platform/plugins/whatsapp-import/lib/src/index.ts +0 -22
  65. package/payload/platform/plugins/whatsapp-import/lib/src/parse-export.ts +0 -471
  66. package/payload/platform/plugins/whatsapp-import/lib/src/sessionize.ts +0 -81
  67. package/payload/platform/plugins/whatsapp-import/lib/src/to-classifier-input.ts +0 -48
  68. package/payload/platform/plugins/whatsapp-import/lib/tsconfig.json +0 -9
  69. package/payload/platform/plugins/whatsapp-import/lib/vitest.config.ts +0 -9
  70. package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import/SKILL.md +0 -124
  71. package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import/references/conversation-archive-shape.md +0 -143
  72. package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import/references/export-parse.md +0 -109
@@ -1,98 +0,0 @@
1
- #!/usr/bin/env bash
2
- # =============================================================================
3
- # whatsapp-ingest.sh — single deterministic Bash entry for WhatsApp archive
4
- # ingestion (Task 891 — chunked :ConversationArchive shape).
5
- #
6
- # Pipeline: parse → bind canonical sender set → derive conversationIdentity →
7
- # look up prior :ConversationArchive (delta cursor) → sessionize delta at
8
- # gap-hours boundary → classify each session via Haiku (mode='chat') →
9
- # memory-ingest with parentLabel='ConversationArchive'.
10
- #
11
- # Usage:
12
- # bash whatsapp-ingest.sh <archive.zip|dir|_chat.txt>
13
- # --owner-element-id <id>
14
- # --participant-person-ids <csv>
15
- # --scope <admin|public>
16
- # [--session-gap-hours <N>] (default 12)
17
- # [--account-id <accountId>]
18
- # [--timezone <iana-zone>]
19
- # [--date-format <DD/MM/YY|MM/DD/YY|DD/MM/YYYY|MM/DD/YYYY>]
20
- #
21
- # `--owner-element-id` + `--participant-person-ids` form the closed sender
22
- # set; any parsed senderName outside that set LOUD-FAILs with `parser-miss`
23
- # and exits non-zero. `--filter` and `--subject-person-id` are gone — chunked
24
- # Section:Conversation rows bound the operator surface naturally.
25
- #
26
- # Exit 0 + JSON summary on stdout on success.
27
- # Exit !0 + one [whatsapp-import] FAIL line on stderr on failure.
28
- # =============================================================================
29
-
30
- set -euo pipefail
31
-
32
- arg_fail() {
33
- local reason="$1"
34
- echo "[whatsapp-import] FAIL phase=argv reason=\"${reason}\"" >&2
35
- exit 1
36
- }
37
-
38
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
39
- PLATFORM_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
40
- INGEST_MJS="$SCRIPT_DIR/ingest.mjs"
41
-
42
- if [ ! -f "$INGEST_MJS" ]; then
43
- arg_fail "ingest.mjs not found at $INGEST_MJS — run from a built install"
44
- fi
45
-
46
- ARCHIVE=""
47
- HAS_OWNER=0
48
- OWNER_VAL=""
49
- HAS_PARTICIPANTS=0
50
- PARTICIPANTS_VAL=""
51
- HAS_SCOPE=0
52
- SCOPE_VAL=""
53
-
54
- ARGS=("$@")
55
- i=0
56
- while [ $i -lt ${#ARGS[@]} ]; do
57
- a="${ARGS[$i]}"
58
- case "$a" in
59
- --owner-element-id) HAS_OWNER=1; OWNER_VAL="${ARGS[$((i + 1))]:-}"; i=$((i + 2)); continue ;;
60
- --participant-person-ids) HAS_PARTICIPANTS=1; PARTICIPANTS_VAL="${ARGS[$((i + 1))]:-}"; i=$((i + 2)); continue ;;
61
- --scope) HAS_SCOPE=1; SCOPE_VAL="${ARGS[$((i + 1))]:-}"; i=$((i + 2)); continue ;;
62
- --session-gap-hours|--account-id|--timezone|--date-format) i=$((i + 2)); continue ;;
63
- --*) i=$((i + 2)); continue ;;
64
- *)
65
- if [ -z "$ARCHIVE" ]; then ARCHIVE="$a"; fi
66
- i=$((i + 1))
67
- continue
68
- ;;
69
- esac
70
- done
71
-
72
- [ -n "$ARCHIVE" ] || arg_fail "missing positional <archive>"
73
- [ "$HAS_OWNER" -eq 1 ] && [ -n "$OWNER_VAL" ] || arg_fail "missing --owner-element-id (or empty value)"
74
- [ "$HAS_PARTICIPANTS" -eq 1 ] && [ -n "$PARTICIPANTS_VAL" ] || arg_fail "missing --participant-person-ids (csv of operator-confirmed :Person/:AdminUser elementIds, owner excluded)"
75
- [ "$HAS_SCOPE" -eq 1 ] && [ -n "$SCOPE_VAL" ] || arg_fail "missing --scope (or empty value)"
76
- case "$SCOPE_VAL" in
77
- admin|public) : ;;
78
- *) arg_fail "invalid --scope \"$SCOPE_VAL\" (admin|public)" ;;
79
- esac
80
-
81
- if [ -z "${NEO4J_PASSWORD:-}" ]; then
82
- NEO4J_PASSWORD_FILE="$PLATFORM_ROOT/config/.neo4j-password"
83
- if [ -f "$NEO4J_PASSWORD_FILE" ]; then
84
- NEO4J_PASSWORD="$(cat "$NEO4J_PASSWORD_FILE")"
85
- export NEO4J_PASSWORD
86
- else
87
- arg_fail "NEO4J_PASSWORD not in env and $NEO4J_PASSWORD_FILE not found"
88
- fi
89
- fi
90
-
91
- if [ -z "${NEO4J_URI:-}" ]; then
92
- arg_fail "NEO4J_URI not set (no default — set in env)"
93
- fi
94
-
95
- export NEO4J_USER="${NEO4J_USER:-neo4j}"
96
- export MAXY_PLATFORM_ROOT="$PLATFORM_ROOT"
97
-
98
- exec node "$INGEST_MJS" "$@"
@@ -1,163 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { findDeltaCursor } from "../delta-cursor.js";
3
- import {
4
- deriveConversationIdentity,
5
- deriveMessageContentHash,
6
- normaliseSenderName,
7
- } from "../derive-keys.js";
8
- import type { ParsedLine } from "../parse-export.js";
9
-
10
- function mk(dateSent: string, senderName: string, body: string): ParsedLine {
11
- return { dateSent, senderName, body, sequenceIndex: 0 };
12
- }
13
-
14
- describe("deriveConversationIdentity", () => {
15
- it("is stable across participant order (sorted internally)", () => {
16
- const a = deriveConversationIdentity({
17
- accountId: "acct-1",
18
- participantElementIds: ["1:abc:1", "1:abc:2"],
19
- });
20
- const b = deriveConversationIdentity({
21
- accountId: "acct-1",
22
- participantElementIds: ["1:abc:2", "1:abc:1"],
23
- });
24
- expect(a).toBe(b);
25
- });
26
-
27
- it("changes when accountId differs", () => {
28
- const a = deriveConversationIdentity({
29
- accountId: "acct-1",
30
- participantElementIds: ["1:abc:1", "1:abc:2"],
31
- });
32
- const b = deriveConversationIdentity({
33
- accountId: "acct-2",
34
- participantElementIds: ["1:abc:1", "1:abc:2"],
35
- });
36
- expect(a).not.toBe(b);
37
- });
38
-
39
- it("rejects empty participant array", () => {
40
- expect(() =>
41
- deriveConversationIdentity({
42
- accountId: "acct-1",
43
- participantElementIds: [],
44
- }),
45
- ).toThrow(/non-empty/);
46
- });
47
-
48
- it("rejects empty accountId", () => {
49
- expect(() =>
50
- deriveConversationIdentity({
51
- accountId: "",
52
- participantElementIds: ["1:abc:1"],
53
- }),
54
- ).toThrow(/accountId/);
55
- });
56
-
57
- it("treats DM and group identically (same formula, different array length)", () => {
58
- const dm = deriveConversationIdentity({
59
- accountId: "acct-1",
60
- participantElementIds: ["1:a:1", "1:a:2"],
61
- });
62
- const group = deriveConversationIdentity({
63
- accountId: "acct-1",
64
- participantElementIds: ["1:a:1", "1:a:2", "1:a:3"],
65
- });
66
- expect(dm).not.toBe(group);
67
- // Both must hex-decode to a sha256 (64 hex chars).
68
- expect(dm).toMatch(/^[a-f0-9]{64}$/);
69
- expect(group).toMatch(/^[a-f0-9]{64}$/);
70
- });
71
- });
72
-
73
- describe("deriveMessageContentHash", () => {
74
- it("is content-only — no archive bytes contribute", () => {
75
- const a = deriveMessageContentHash({
76
- dateSent: "2026-03-14T10:00:00+00:00",
77
- senderName: "Joel",
78
- body: "hi",
79
- });
80
- const b = deriveMessageContentHash({
81
- dateSent: "2026-03-14T10:00:00+00:00",
82
- senderName: "Joel",
83
- body: "hi",
84
- });
85
- expect(a).toBe(b);
86
- });
87
-
88
- it("changes when any field changes", () => {
89
- const base = {
90
- dateSent: "2026-03-14T10:00:00+00:00",
91
- senderName: "Joel",
92
- body: "hi",
93
- };
94
- expect(deriveMessageContentHash(base)).not.toBe(
95
- deriveMessageContentHash({ ...base, body: "hello" }),
96
- );
97
- expect(deriveMessageContentHash(base)).not.toBe(
98
- deriveMessageContentHash({ ...base, senderName: "Adam" }),
99
- );
100
- expect(deriveMessageContentHash(base)).not.toBe(
101
- deriveMessageContentHash({ ...base, dateSent: "2026-03-14T10:00:01+00:00" }),
102
- );
103
- });
104
-
105
- it("collapses NFKC-equivalent sender names to one hash", () => {
106
- const a = deriveMessageContentHash({
107
- dateSent: "2026-03-14T10:00:00+00:00",
108
- senderName: " ADAM Mackay ",
109
- body: "hi",
110
- });
111
- const b = deriveMessageContentHash({
112
- dateSent: "2026-03-14T10:00:00+00:00",
113
- senderName: "adam mackay",
114
- body: "hi",
115
- });
116
- expect(a).toBe(b);
117
- });
118
- });
119
-
120
- describe("normaliseSenderName", () => {
121
- it("returns NFKC-trim-lower form", () => {
122
- expect(normaliseSenderName(" Adam Mackay ")).toBe("adam mackay");
123
- });
124
- });
125
-
126
- describe("findDeltaCursor", () => {
127
- const lines: ParsedLine[] = [
128
- mk("2026-03-14T10:00:00+00:00", "Joel", "first"),
129
- mk("2026-03-14T10:01:00+00:00", "Adam", "second"),
130
- mk("2026-03-14T10:02:00+00:00", "Joel", "third"),
131
- ];
132
- const hashFor = (l: ParsedLine) =>
133
- deriveMessageContentHash({
134
- dateSent: l.dateSent,
135
- senderName: l.senderName,
136
- body: l.body,
137
- });
138
-
139
- it("returns 'found' with deltaStart = cursor + 1 when the hash matches a prior line", () => {
140
- const result = findDeltaCursor(lines, hashFor(lines[0]));
141
- expect(result).toEqual({ kind: "found", deltaStart: 1 });
142
- });
143
-
144
- it("returns 'empty' when the cursor is the last line (no new messages)", () => {
145
- const result = findDeltaCursor(lines, hashFor(lines[2]));
146
- expect(result).toEqual({ kind: "empty" });
147
- });
148
-
149
- it("returns 'missing' when no parsed line matches (LOUD-FAIL upstream)", () => {
150
- const result = findDeltaCursor(lines, "deadbeef".repeat(8));
151
- expect(result).toEqual({ kind: "missing" });
152
- });
153
-
154
- it("returns 'missing' for an empty parsed sequence (cursor cannot exist)", () => {
155
- const result = findDeltaCursor([], hashFor(lines[0]));
156
- expect(result).toEqual({ kind: "missing" });
157
- });
158
-
159
- it("rejects empty cursor hash", () => {
160
- expect(() => findDeltaCursor(lines, "")).toThrow(/non-empty/);
161
- expect(() => findDeltaCursor(lines, " ")).toThrow(/non-empty/);
162
- });
163
- });
@@ -1,83 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
- import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
3
- import { tmpdir } from "node:os";
4
- import { join } from "node:path";
5
- import { parseExport } from "../parse-export.js";
6
-
7
- // Task 887 — bidi-strip regression. Some WhatsApp exports prefix every
8
- // timestamp header with U+200E (LEFT-TO-RIGHT MARK) or U+200F (RTL MARK).
9
- // Pre-fix `decodeAndNormalise` left those bytes in place; the timestamp
10
- // regex (`^\[(\d{2})\/...`) failed; the LRM-prefixed line was glued onto
11
- // the previous body as a continuation; the next clean header parsed its
12
- // senderName off the polluted body — leaking 23 :Person nodes per import
13
- // in the Adam Mackay archive. The fix strips U+200E/U+200F before
14
- // tokenisation; this test reproduces the failure shape.
15
-
16
- let workDir: string;
17
-
18
- beforeEach(() => {
19
- workDir = mkdtempSync(join(tmpdir(), "whatsapp-export-lrm-"));
20
- });
21
-
22
- afterEach(() => {
23
- rmSync(workDir, { recursive: true, force: true });
24
- });
25
-
26
- function writeChat(name: string, content: string): string {
27
- const filePath = join(workDir, name);
28
- writeFileSync(filePath, content);
29
- return filePath;
30
- }
31
-
32
- describe("parseExport — bidi-strip (Task 887)", () => {
33
- it("strips U+200E from timestamp headers and parses each row independently", () => {
34
- const LRM = "‎";
35
- const filePath = writeChat(
36
- "_chat.txt",
37
- [
38
- `${LRM}[04/02/26, 11:52:16] Adam Mackay: hi`,
39
- `${LRM}[04/02/26, 11:52:30] Joel Smalley: hey`,
40
- "",
41
- ].join("\n"),
42
- );
43
-
44
- const result = parseExport({
45
- filePath,
46
- accountId: "acct-887",
47
- timezone: "Europe/London",
48
- });
49
-
50
- expect(result.parsedLines).toHaveLength(2);
51
- expect(result.parsedLines.map((l) => l.senderName).sort()).toEqual([
52
- "Adam Mackay",
53
- "Joel Smalley",
54
- ]);
55
- for (const line of result.parsedLines) {
56
- expect(line.senderName).not.toContain("\n");
57
- expect(line.senderName).not.toContain("[");
58
- expect(line.senderName).not.toContain(LRM);
59
- }
60
- });
61
-
62
- it("strips U+200F (RLM) on the timestamp line", () => {
63
- const RLM = "‏";
64
- const filePath = writeChat(
65
- "_chat.txt",
66
- [
67
- `${RLM}[14/03/26, 10:15:23] Joel: Hello`,
68
- `${RLM}[14/03/26, 10:16:01] Sarah: Hi back`,
69
- "",
70
- ].join("\n"),
71
- );
72
-
73
- const result = parseExport({
74
- filePath,
75
- accountId: "acct-887",
76
- timezone: "Europe/London",
77
- });
78
-
79
- expect(result.parsedLines).toHaveLength(2);
80
- expect(result.parsedLines[0].senderName).toBe("Joel");
81
- expect(result.parsedLines[1].senderName).toBe("Sarah");
82
- });
83
- });