@rubytech/create-realagent 1.0.822 → 1.0.824

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 (32) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/neo4j/migrations/006-prune-bogus-whatsapp-persons.ts +132 -0
  3. package/payload/platform/plugins/admin/hooks/__tests__/archive-ingest-surface-gate.test.sh +1 -1
  4. package/payload/platform/plugins/admin/hooks/archive-ingest-surface-gate.sh +2 -2
  5. package/payload/platform/plugins/docs/references/plugins-guide.md +1 -1
  6. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts.map +1 -1
  7. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js +10 -5
  8. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
  9. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-pass.d.ts +4 -0
  10. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-pass.d.ts.map +1 -1
  11. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-pass.js +106 -30
  12. package/payload/platform/plugins/memory/mcp/dist/tools/whatsapp-export-insight-pass.js.map +1 -1
  13. package/payload/platform/plugins/whatsapp-import/bin/ingest.mjs +174 -115
  14. package/payload/platform/plugins/whatsapp-import/bin/whatsapp-ingest.sh +18 -7
  15. package/payload/platform/plugins/whatsapp-import/lib/dist/parse-export.js +24 -0
  16. package/payload/platform/plugins/whatsapp-import/lib/dist/parse-export.js.map +1 -1
  17. package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/filter-gate.test.ts +2 -0
  18. package/payload/platform/plugins/whatsapp-import/lib/src/__tests__/parse-export-lrm.test.ts +83 -0
  19. package/payload/platform/plugins/whatsapp-import/lib/src/parse-export.ts +25 -0
  20. package/payload/platform/plugins/whatsapp-import/skills/whatsapp-import/SKILL.md +11 -9
  21. package/payload/platform/templates/specialists/agents/database-operator.md +1 -1
  22. package/payload/server/chunk-JNVZQMTZ.js +593 -0
  23. package/payload/server/chunk-L3T7ECLI.js +1116 -0
  24. package/payload/server/chunk-LFOR2ACU.js +10079 -0
  25. package/payload/server/chunk-NAP6XMLW.js +2233 -0
  26. package/payload/server/client-pool-M2DU74ZP.js +32 -0
  27. package/payload/server/cloudflare-task-tracker-6S23B7QX.js +17 -0
  28. package/payload/server/maxy-edge.js +3 -3
  29. package/payload/server/neo4j-migrations-YED5CFPF.js +428 -0
  30. package/payload/server/public/assets/{admin-B8cZNfuF.js → admin-DOkUspG1.js} +2 -2
  31. package/payload/server/public/index.html +1 -1
  32. package/payload/server/server.js +120 -7
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>Real Agent</title>
7
7
  <link rel="icon" href="/favicon.ico">
8
- <script type="module" crossorigin src="/assets/admin-B8cZNfuF.js"></script>
8
+ <script type="module" crossorigin src="/assets/admin-DOkUspG1.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/assets/chunk-DD-I1_y5.js">
10
10
  <link rel="modulepreload" crossorigin href="/assets/jsx-runtime-DkaAusaX.js">
11
11
  <link rel="modulepreload" crossorigin href="/assets/preload-helper-qlgyTAkD.js">
@@ -51,7 +51,7 @@ import {
51
51
  vncLog,
52
52
  waitForExit,
53
53
  writeChromiumWrapper
54
- } from "./chunk-NUXYHO6N.js";
54
+ } from "./chunk-LFOR2ACU.js";
55
55
  import {
56
56
  agentLogStream,
57
57
  clearSessionHistory,
@@ -79,7 +79,7 @@ import {
79
79
  sigtermFlushStreamLogs,
80
80
  unregisterSession,
81
81
  validateSession
82
- } from "./chunk-SALVIGXH.js";
82
+ } from "./chunk-L3T7ECLI.js";
83
83
  import {
84
84
  ACCOUNTS_DIR,
85
85
  PLATFORM_ROOT,
@@ -96,7 +96,7 @@ import {
96
96
  completeCloudflareTask,
97
97
  openCloudflareTask,
98
98
  readTunnelState
99
- } from "./chunk-CZGOB575.js";
99
+ } from "./chunk-JNVZQMTZ.js";
100
100
  import {
101
101
  GREETING_DIRECTIVE,
102
102
  HAIKU_MODEL,
@@ -128,7 +128,7 @@ import {
128
128
  verifyAndGetConversationUpdatedAt,
129
129
  verifyConversationOwnership,
130
130
  writeAdminUserAndPerson
131
- } from "./chunk-ZT6LKDTP.js";
131
+ } from "./chunk-NAP6XMLW.js";
132
132
 
133
133
  // ../lib/graph-trash/dist/index.js
134
134
  var require_dist = __commonJS({
@@ -7284,7 +7284,7 @@ var app11 = new Hono();
7284
7284
  app11.post("/cancel", requireAdminSession, async (c) => {
7285
7285
  const session_key = c.var.sessionKey;
7286
7286
  try {
7287
- const { interruptClient: interruptClient2 } = await import("./client-pool-IQU6H43X.js");
7287
+ const { interruptClient: interruptClient2 } = await import("./client-pool-M2DU74ZP.js");
7288
7288
  await interruptClient2(session_key);
7289
7289
  return c.json({ ok: true });
7290
7290
  } catch (err) {
@@ -8205,6 +8205,33 @@ app17.post("/new", requireAdminSession, async (c) => {
8205
8205
  console.log(`[session] ${(/* @__PURE__ */ new Date()).toISOString()} session reset for new conversation: oldSessionKey=${oldSessionKey.slice(0, 8)}\u2026 newSessionKey=${newSessionKey.slice(0, 8)}\u2026 previousConversationId=${previousConversationId?.slice(0, 8) ?? "none"}\u2026 newConversationId=deferred`);
8206
8206
  return c.json({ session_key: newSessionKey, conversationId: null });
8207
8207
  });
8208
+ app17.post("/switch", requireAdminSession, async (c) => {
8209
+ const sessionKey = c.var.sessionKey;
8210
+ const accountId = getAccountIdForSession(sessionKey);
8211
+ const userId = getUserIdForSession(sessionKey);
8212
+ if (!accountId || !userId) {
8213
+ return c.json({ error: "Session missing account or user context" }, 400);
8214
+ }
8215
+ const body = await c.req.json().catch(() => ({}));
8216
+ const targetSessionKey = typeof body.target_session_key === "string" ? body.target_session_key : "";
8217
+ if (!targetSessionKey) {
8218
+ return c.json({ error: "target_session_key required" }, 400);
8219
+ }
8220
+ const targetCheck = validateSession(targetSessionKey, "admin");
8221
+ if (!targetCheck.ok) {
8222
+ console.error(`[session-switch] reject reason=${targetCheck.reason} from=${sessionKey.slice(0, 8)} target=${targetSessionKey.slice(0, 8)}`);
8223
+ return c.json({ error: "Target session not registered or wrong agent type", code: targetCheck.reason }, 404);
8224
+ }
8225
+ const targetAccountId = getAccountIdForSession(targetSessionKey);
8226
+ const targetUserId = getUserIdForSession(targetSessionKey);
8227
+ if (targetAccountId !== accountId || targetUserId !== userId) {
8228
+ console.error(`[session-switch] reject reason=ownership-mismatch from=${sessionKey.slice(0, 8)} target=${targetSessionKey.slice(0, 8)} accountMatch=${targetAccountId === accountId} userMatch=${targetUserId === userId}`);
8229
+ return c.json({ error: "Target session not owned by current operator" }, 403);
8230
+ }
8231
+ const targetConversationId = getConversationIdForSession(targetSessionKey) ?? null;
8232
+ console.log(`[session-switch] from=${sessionKey.slice(0, 8)} to=${targetSessionKey.slice(0, 8)} targetConvId=${targetConversationId?.slice(0, 8) ?? "none"} accountId=${accountId.slice(0, 8)}`);
8233
+ return c.json({ session_key: targetSessionKey, conversationId: targetConversationId });
8234
+ });
8208
8235
  app17.delete("/:id", requireAdminSession, async (c) => {
8209
8236
  const conversationId = c.req.param("id");
8210
8237
  const sessionKey = c.var.sessionKey;
@@ -10521,7 +10548,22 @@ async function handleNeighbourhood(c, accountId) {
10521
10548
  });
10522
10549
  allowedIds = searchRes.results.map((r) => r.nodeId);
10523
10550
  }
10524
- const cypher = allowedIds !== null ? NEIGHBOURHOOD_SEARCH_INTERSECT_CYPHER : NEIGHBOURHOOD_CYPHER;
10551
+ let rootLabels = [];
10552
+ if (allowedIds === null) {
10553
+ const labelRes = await session.executeRead(async (tx) => {
10554
+ return await tx.run(
10555
+ `MATCH (n) WHERE elementId(n) = $elementId
10556
+ AND n.accountId = $accountId
10557
+ AND NOT n:Trashed
10558
+ AND n.deletedAt IS NULL
10559
+ RETURN labels(n) AS labels LIMIT 1`,
10560
+ { elementId, accountId }
10561
+ );
10562
+ });
10563
+ rootLabels = labelRes.records[0]?.get("labels") ?? [];
10564
+ }
10565
+ const isPersonRoot = rootLabels.includes("Person");
10566
+ const cypher = allowedIds !== null ? NEIGHBOURHOOD_SEARCH_INTERSECT_CYPHER : isPersonRoot ? NEIGHBOURHOOD_CYPHER_PERSON_ROOT : NEIGHBOURHOOD_CYPHER;
10525
10567
  const cypherParams = {
10526
10568
  accountId,
10527
10569
  elementId,
@@ -10566,6 +10608,18 @@ async function handleNeighbourhood(c, accountId) {
10566
10608
  );
10567
10609
  }
10568
10610
  }
10611
+ if (allowedIds === null) {
10612
+ const rootNode = nodes[0];
10613
+ const rootIsMessage = rootNode?.labels.includes("Message") ?? false;
10614
+ const totalMessages = nodes.filter((n) => n.labels.includes("Message")).length;
10615
+ const clusterMessageCount = totalMessages - (rootIsMessage ? 1 : 0);
10616
+ const convNode = nodes.find((n) => n.labels.some((lbl) => CLUSTER_CONVERSATION_LABELS.has(lbl)));
10617
+ const convIsExtra = convNode != null && convNode.id !== rootNode?.id ? 1 : 0;
10618
+ const neighbourCount = Math.max(0, nodes.length - 1 - clusterMessageCount - convIsExtra);
10619
+ console.error(
10620
+ `[graph-subgraph] expand root=${elementId} labels=${(rootNode?.labels ?? []).join(",")} clusterMessages=${clusterMessageCount} neighbours=${neighbourCount}`
10621
+ );
10622
+ }
10569
10623
  if (allowedIds !== null) {
10570
10624
  console.error(
10571
10625
  `[graph-page] neighbourhood-search-intersect q="${q}" allowed=${allowedIds.length} root=${elementId} rendered=${nodes.length}`
@@ -10726,6 +10780,65 @@ var NEIGHBOURHOOD_CYPHER = `
10726
10780
  [x IN windowNodes | {id: elementId(x), labels: labels(x), properties: ${CONVERSATION_PROPS_PROJECTION}}] AS nodes,
10727
10781
  [e IN rawEdges WHERE e IS NOT NULL] AS edges
10728
10782
  `;
10783
+ var NEIGHBOURHOOD_CYPHER_PERSON_ROOT = `
10784
+ MATCH (n)
10785
+ WHERE elementId(n) = $elementId
10786
+ AND n.accountId = $accountId
10787
+ AND NOT n:Trashed
10788
+ AND n.deletedAt IS NULL
10789
+
10790
+ OPTIONAL MATCH (n)-[:PART_OF]->(convFromMsg:Conversation)
10791
+ WHERE convFromMsg.accountId = $accountId
10792
+ AND NOT convFromMsg:Trashed
10793
+ AND convFromMsg.deletedAt IS NULL
10794
+ WITH n, CASE
10795
+ WHEN any(lbl IN labels(n) WHERE lbl IN ['Conversation','AdminConversation','PublicConversation']) THEN n
10796
+ ELSE convFromMsg
10797
+ END AS conv
10798
+
10799
+ OPTIONAL MATCH (conv)<-[:PART_OF]-(siblingMsg:Message)
10800
+ WHERE siblingMsg.accountId = $accountId
10801
+ AND NOT siblingMsg:Trashed
10802
+ AND siblingMsg.deletedAt IS NULL
10803
+ AND elementId(siblingMsg) <> elementId(n)
10804
+ WITH n, conv, collect(DISTINCT siblingMsg) AS siblingMessages
10805
+ WITH n, conv, siblingMessages[0..$clusterMessagesCap] AS clusterMessages
10806
+
10807
+ OPTIONAL MATCH (n)-[r]-(m)
10808
+ WHERE m.accountId = $accountId
10809
+ AND NOT m:Trashed
10810
+ AND m.deletedAt IS NULL
10811
+ AND NOT any(lbl IN labels(m) WHERE lbl IN $agentActionLabels)
10812
+ AND type(r) <> 'SENT'
10813
+ WITH n, conv, clusterMessages, m
10814
+ LIMIT $neighbourhoodLimit
10815
+ WITH n, conv, clusterMessages, collect(DISTINCT m) AS neighbours
10816
+
10817
+ WITH [n]
10818
+ + (CASE WHEN conv IS NOT NULL AND elementId(conv) <> elementId(n) THEN [conv] ELSE [] END)
10819
+ + clusterMessages
10820
+ + [x IN neighbours WHERE x IS NOT NULL
10821
+ AND elementId(x) <> elementId(n)
10822
+ AND (conv IS NULL OR elementId(x) <> elementId(conv))
10823
+ AND none(c IN clusterMessages WHERE elementId(c) = elementId(x))]
10824
+ AS windowNodes
10825
+ WITH windowNodes, [x IN windowNodes | elementId(x)] AS windowIds
10826
+ UNWIND windowNodes AS w
10827
+ OPTIONAL MATCH (w)-[r]-(o)
10828
+ WHERE elementId(o) IN windowIds
10829
+ AND type(r) <> 'SENT'
10830
+ WITH windowNodes,
10831
+ collect(DISTINCT CASE WHEN r IS NULL THEN null ELSE {
10832
+ id: elementId(r),
10833
+ from: elementId(startNode(r)),
10834
+ to: elementId(endNode(r)),
10835
+ type: type(r),
10836
+ properties: properties(r)
10837
+ } END) AS rawEdges
10838
+ RETURN
10839
+ [x IN windowNodes | {id: elementId(x), labels: labels(x), properties: ${CONVERSATION_PROPS_PROJECTION}}] AS nodes,
10840
+ [e IN rawEdges WHERE e IS NOT NULL] AS edges
10841
+ `;
10729
10842
  var NEIGHBOURHOOD_SEARCH_INTERSECT_CYPHER = `
10730
10843
  MATCH (n)
10731
10844
  WHERE elementId(n) = $elementId
@@ -12600,7 +12713,7 @@ autoDeliverPremiumPlugins(bootEntitlement?.purchasedPlugins ?? void 0);
12600
12713
  (async () => {
12601
12714
  if (!bootAccount) return;
12602
12715
  try {
12603
- const { recoverRunningCloudflareTasks } = await import("./cloudflare-task-tracker-Q4X5BYR7.js");
12716
+ const { recoverRunningCloudflareTasks } = await import("./cloudflare-task-tracker-6S23B7QX.js");
12604
12717
  const result = await recoverRunningCloudflareTasks(
12605
12718
  bootAccount.accountId,
12606
12719
  configDirForWhatsApp,