@rubytech/create-realagent 1.0.436 → 1.0.437

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 (26) hide show
  1. package/package.json +1 -1
  2. package/payload/maxy/server.js +135 -40
  3. package/payload/platform/neo4j/schema.cypher +6 -0
  4. package/payload/platform/plugins/contacts/mcp/dist/index.js +34 -16
  5. package/payload/platform/plugins/contacts/mcp/dist/index.js.map +1 -1
  6. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.d.ts +2 -2
  7. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.d.ts.map +1 -1
  8. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js +34 -9
  9. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js.map +1 -1
  10. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-delete.d.ts +2 -1
  11. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-delete.d.ts.map +1 -1
  12. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-delete.js +13 -7
  13. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-delete.js.map +1 -1
  14. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.d.ts +2 -1
  15. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.d.ts.map +1 -1
  16. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.js +1 -0
  17. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-list.js.map +1 -1
  18. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.d.ts +2 -1
  19. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.d.ts.map +1 -1
  20. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js +10 -1
  21. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js.map +1 -1
  22. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-update.d.ts +1 -0
  23. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-update.d.ts.map +1 -1
  24. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-update.js +8 -4
  25. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-update.js.map +1 -1
  26. package/payload/platform/plugins/docs/references/contacts-guide.md +7 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/create-realagent",
3
- "version": "1.0.436",
3
+ "version": "1.0.437",
4
4
  "description": "Install Real Agent — Built for agents. By agents.",
5
5
  "bin": {
6
6
  "create-realagent": "./dist/index.js"
@@ -2845,7 +2845,7 @@ var serveStatic = (options = { root: "" }) => {
2845
2845
  };
2846
2846
 
2847
2847
  // server/index.ts
2848
- import { readFileSync as readFileSync17, existsSync as existsSync17, watchFile } from "fs";
2848
+ import { readFileSync as readFileSync18, existsSync as existsSync18, watchFile } from "fs";
2849
2849
  import { resolve as resolve15, join as join5 } from "path";
2850
2850
  import { homedir as homedir2 } from "os";
2851
2851
 
@@ -9375,6 +9375,86 @@ async function POST11(req) {
9375
9375
  }
9376
9376
 
9377
9377
  // app/api/admin/chat/route.ts
9378
+ import { existsSync as existsSync12, readFileSync as readFileSync12, writeFileSync as writeFileSync8, mkdirSync as mkdirSync6 } from "fs";
9379
+ import { dirname as dirname2 } from "path";
9380
+ function isComponentDone(parsed) {
9381
+ return typeof parsed === "object" && parsed !== null && parsed._componentDone === true && typeof parsed.component === "string" && typeof parsed.payload === "string";
9382
+ }
9383
+ function transformComponentDone(envelope) {
9384
+ const { component, payload } = envelope;
9385
+ if (component === "document-editor") {
9386
+ try {
9387
+ const inner = JSON.parse(payload);
9388
+ if (typeof inner === "object" && inner !== null) {
9389
+ if (inner.action === "approve" && typeof inner.content === "string") {
9390
+ const path = inner.filePath ?? "unknown";
9391
+ return `[User approved document: ${path}]
9392
+
9393
+ ${inner.content}`;
9394
+ }
9395
+ if (inner.type === "comment" && typeof inner.text === "string") {
9396
+ return `[User commented on document: "${inner.text}"]`;
9397
+ }
9398
+ }
9399
+ } catch {
9400
+ }
9401
+ }
9402
+ return payload;
9403
+ }
9404
+ var VOLATILE_STATE_FILE = "/tmp/maxy-agent-create-state.json";
9405
+ function advanceGateIfNeeded(envelope, accountDir, logFn) {
9406
+ if (!existsSync12(VOLATILE_STATE_FILE)) return;
9407
+ const { component, payload } = envelope;
9408
+ let gateFlag = null;
9409
+ let agentSlug = "";
9410
+ if (component === "document-editor") {
9411
+ try {
9412
+ const inner = typeof payload === "string" ? JSON.parse(payload) : payload;
9413
+ if (typeof inner === "object" && inner !== null && typeof inner.filePath === "string") {
9414
+ const match2 = inner.filePath.match(/agents\/([^/]+)\/(SOUL\.md|KNOWLEDGE\.md)$/);
9415
+ if (match2 && match2[1] !== "admin") {
9416
+ agentSlug = match2[1];
9417
+ gateFlag = match2[2] === "SOUL.md" ? "soul" : "knowledge";
9418
+ }
9419
+ }
9420
+ } catch {
9421
+ }
9422
+ } else if (component === "form") {
9423
+ gateFlag = "config";
9424
+ }
9425
+ if (!gateFlag) return;
9426
+ let state;
9427
+ try {
9428
+ state = JSON.parse(readFileSync12(VOLATILE_STATE_FILE, "utf-8"));
9429
+ } catch (err) {
9430
+ logFn(`ERROR \u2014 failed to read state file for advancement: ${err instanceof Error ? err.message : String(err)}`);
9431
+ return;
9432
+ }
9433
+ const gates = state.gates;
9434
+ if (!gates || typeof gates !== "object") {
9435
+ logFn("WARNING \u2014 state file has unexpected structure, skipping advancement");
9436
+ return;
9437
+ }
9438
+ if (!state.slug && agentSlug) {
9439
+ state.slug = agentSlug;
9440
+ }
9441
+ if (gates[gateFlag] === true) return;
9442
+ gates[gateFlag] = true;
9443
+ try {
9444
+ writeFileSync8(VOLATILE_STATE_FILE, JSON.stringify(state));
9445
+ } catch (err) {
9446
+ logFn(`ERROR \u2014 failed to write volatile state after advancement: ${err instanceof Error ? err.message : String(err)}`);
9447
+ }
9448
+ const durablePath = `${accountDir}/.claude/agent-create-state.json`;
9449
+ try {
9450
+ mkdirSync6(dirname2(durablePath), { recursive: true });
9451
+ writeFileSync8(durablePath, JSON.stringify(state));
9452
+ } catch (err) {
9453
+ logFn(`WARNING \u2014 failed to write durable state after advancement: ${err instanceof Error ? err.message : String(err)}`);
9454
+ }
9455
+ const pending = Object.entries(gates).filter(([, v]) => !v).map(([k]) => k);
9456
+ logFn(`${gateFlag} gate advanced (route-level). Pending: ${pending.length > 0 ? pending.join(", ") : "none"}`);
9457
+ }
9378
9458
  async function POST12(req) {
9379
9459
  const contentType = req.headers.get("content-type") ?? "";
9380
9460
  let message;
@@ -9510,6 +9590,21 @@ async function POST12(req) {
9510
9590
  }
9511
9591
  } catch {
9512
9592
  }
9593
+ try {
9594
+ const parsed = JSON.parse(message);
9595
+ if (isComponentDone(parsed)) {
9596
+ const componentLog = agentLogStream("component-lifecycle", account.accountDir);
9597
+ const ts = (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
9598
+ const logFn = (msg) => componentLog.write(`[${ts}] [agent-creation-approval:route] ${msg}
9599
+ `);
9600
+ advanceGateIfNeeded(parsed, account.accountDir, logFn);
9601
+ message = transformComponentDone(parsed);
9602
+ componentLog.write(`[${ts}] [component:${parsed.component}] componentDone \u2192 transformed
9603
+ `);
9604
+ componentLog.end();
9605
+ }
9606
+ } catch {
9607
+ }
9513
9608
  const encoder = new TextEncoder();
9514
9609
  const sseLog = agentLogStream("sse-events", account.accountDir);
9515
9610
  const sk = session_key.slice(0, 8);
@@ -9619,7 +9714,7 @@ async function POST13(req) {
9619
9714
  }
9620
9715
 
9621
9716
  // app/api/admin/logs/route.ts
9622
- import { existsSync as existsSync12, readdirSync as readdirSync2, readFileSync as readFileSync12, statSync as statSync3 } from "fs";
9717
+ import { existsSync as existsSync13, readdirSync as readdirSync2, readFileSync as readFileSync13, statSync as statSync3 } from "fs";
9623
9718
  import { resolve as resolve9, basename } from "path";
9624
9719
  var TAIL_BYTES = 8192;
9625
9720
  async function GET3(request) {
@@ -9635,7 +9730,7 @@ async function GET3(request) {
9635
9730
  if (!dir) continue;
9636
9731
  const filePath = resolve9(dir, safe);
9637
9732
  try {
9638
- const content = readFileSync12(filePath, "utf-8");
9733
+ const content = readFileSync13(filePath, "utf-8");
9639
9734
  const headers = { "Content-Type": "text/plain; charset=utf-8" };
9640
9735
  if (download) headers["Content-Disposition"] = `attachment; filename="${safe}"`;
9641
9736
  return new Response(content, { headers });
@@ -9661,7 +9756,7 @@ async function GET3(request) {
9661
9756
  if (!dir) continue;
9662
9757
  const filePath = resolve9(dir, fileName);
9663
9758
  try {
9664
- const content = readFileSync12(filePath, "utf-8");
9759
+ const content = readFileSync13(filePath, "utf-8");
9665
9760
  const headers = { "Content-Type": "text/plain; charset=utf-8" };
9666
9761
  if (download) headers["Content-Disposition"] = `attachment; filename="${fileName}"`;
9667
9762
  return new Response(content, { headers });
@@ -9673,7 +9768,7 @@ async function GET3(request) {
9673
9768
  const seen = /* @__PURE__ */ new Set();
9674
9769
  const logs = {};
9675
9770
  for (const dir of [accountLogDir, LOG_DIR]) {
9676
- if (!dir || !existsSync12(dir)) continue;
9771
+ if (!dir || !existsSync13(dir)) continue;
9677
9772
  let files;
9678
9773
  try {
9679
9774
  files = readdirSync2(dir).filter((f) => f.endsWith(".log"));
@@ -9683,7 +9778,7 @@ async function GET3(request) {
9683
9778
  files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync3(resolve9(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
9684
9779
  seen.add(name);
9685
9780
  try {
9686
- const content = readFileSync12(resolve9(dir, name));
9781
+ const content = readFileSync13(resolve9(dir, name));
9687
9782
  const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
9688
9783
  logs[name] = tail.trim() || "(empty)";
9689
9784
  } catch {
@@ -9718,7 +9813,7 @@ async function GET4() {
9718
9813
 
9719
9814
  // app/api/admin/attachment/[attachmentId]/route.ts
9720
9815
  import { readFile, readdir } from "fs/promises";
9721
- import { existsSync as existsSync13 } from "fs";
9816
+ import { existsSync as existsSync14 } from "fs";
9722
9817
  import { resolve as resolve10 } from "path";
9723
9818
  async function GET5(req, attachmentId) {
9724
9819
  const sessionKey = new URL(req.url).searchParams.get("session_key") ?? "";
@@ -9733,11 +9828,11 @@ async function GET5(req, attachmentId) {
9733
9828
  return new Response("Not found", { status: 404 });
9734
9829
  }
9735
9830
  const dir = resolve10(ATTACHMENTS_ROOT, accountId, attachmentId);
9736
- if (!existsSync13(dir)) {
9831
+ if (!existsSync14(dir)) {
9737
9832
  return new Response("Not found", { status: 404 });
9738
9833
  }
9739
9834
  const metaPath = resolve10(dir, `${attachmentId}.meta.json`);
9740
- if (!existsSync13(metaPath)) {
9835
+ if (!existsSync14(metaPath)) {
9741
9836
  return new Response("Not found", { status: 404 });
9742
9837
  }
9743
9838
  let meta;
@@ -9763,7 +9858,7 @@ async function GET5(req, attachmentId) {
9763
9858
  }
9764
9859
 
9765
9860
  // app/api/admin/account/route.ts
9766
- import { readFileSync as readFileSync13, writeFileSync as writeFileSync8 } from "fs";
9861
+ import { readFileSync as readFileSync14, writeFileSync as writeFileSync9 } from "fs";
9767
9862
  import { resolve as resolve11 } from "path";
9768
9863
  var VALID_CONTEXT_MODES = ["managed", "claude-code"];
9769
9864
  async function PATCH(req) {
@@ -9789,10 +9884,10 @@ async function PATCH(req) {
9789
9884
  }
9790
9885
  const configPath = resolve11(account.accountDir, "account.json");
9791
9886
  try {
9792
- const raw2 = readFileSync13(configPath, "utf-8");
9887
+ const raw2 = readFileSync14(configPath, "utf-8");
9793
9888
  const config = JSON.parse(raw2);
9794
9889
  config.contextMode = contextMode;
9795
- writeFileSync8(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
9890
+ writeFileSync9(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
9796
9891
  console.error(`[account-update] contextMode=${contextMode}`);
9797
9892
  return Response.json({ ok: true, contextMode });
9798
9893
  } catch (err) {
@@ -9803,14 +9898,14 @@ async function PATCH(req) {
9803
9898
 
9804
9899
  // app/api/admin/agents/route.ts
9805
9900
  import { resolve as resolve12 } from "path";
9806
- import { readdirSync as readdirSync3, readFileSync as readFileSync14, existsSync as existsSync14 } from "fs";
9901
+ import { readdirSync as readdirSync3, readFileSync as readFileSync15, existsSync as existsSync15 } from "fs";
9807
9902
  async function GET6() {
9808
9903
  const account = resolveAccount();
9809
9904
  if (!account) {
9810
9905
  return Response.json({ agents: [] });
9811
9906
  }
9812
9907
  const agentsDir = resolve12(account.accountDir, "agents");
9813
- if (!existsSync14(agentsDir)) {
9908
+ if (!existsSync15(agentsDir)) {
9814
9909
  return Response.json({ agents: [] });
9815
9910
  }
9816
9911
  const agents = [];
@@ -9820,9 +9915,9 @@ async function GET6() {
9820
9915
  if (!entry.isDirectory()) continue;
9821
9916
  if (entry.name === "admin") continue;
9822
9917
  const configPath = resolve12(agentsDir, entry.name, "config.json");
9823
- if (!existsSync14(configPath)) continue;
9918
+ if (!existsSync15(configPath)) continue;
9824
9919
  try {
9825
- const config = JSON.parse(readFileSync14(configPath, "utf-8"));
9920
+ const config = JSON.parse(readFileSync15(configPath, "utf-8"));
9826
9921
  agents.push({
9827
9922
  slug: entry.name,
9828
9923
  displayName: config.displayName ?? entry.name,
@@ -9840,15 +9935,15 @@ async function GET6() {
9840
9935
  }
9841
9936
 
9842
9937
  // app/api/admin/version/route.ts
9843
- import { readFileSync as readFileSync15, existsSync as existsSync15 } from "fs";
9938
+ import { readFileSync as readFileSync16, existsSync as existsSync16 } from "fs";
9844
9939
  import { resolve as resolve13, join as join3 } from "path";
9845
9940
  var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve13(process.cwd(), "..");
9846
9941
  var brandHostname = "maxy";
9847
9942
  var brandNpmPackage = "@rubytech/create-maxy";
9848
9943
  var brandJsonPath = join3(PLATFORM_ROOT6, "config", "brand.json");
9849
- if (existsSync15(brandJsonPath)) {
9944
+ if (existsSync16(brandJsonPath)) {
9850
9945
  try {
9851
- const brand = JSON.parse(readFileSync15(brandJsonPath, "utf-8"));
9946
+ const brand = JSON.parse(readFileSync16(brandJsonPath, "utf-8"));
9852
9947
  if (brand.hostname) brandHostname = brand.hostname;
9853
9948
  if (brand.npm?.packageName) brandNpmPackage = brand.npm.packageName;
9854
9949
  } catch {
@@ -9861,8 +9956,8 @@ var CACHE_TTL_MS = 60 * 60 * 1e3;
9861
9956
  var FETCH_TIMEOUT_MS = 5e3;
9862
9957
  var latestCache = null;
9863
9958
  function readInstalled() {
9864
- if (!existsSync15(VERSION_FILE)) return "unknown";
9865
- const content = readFileSync15(VERSION_FILE, "utf-8").trim();
9959
+ if (!existsSync16(VERSION_FILE)) return "unknown";
9960
+ const content = readFileSync16(VERSION_FILE, "utf-8").trim();
9866
9961
  return content || "unknown";
9867
9962
  }
9868
9963
  async function fetchLatest() {
@@ -9916,15 +10011,15 @@ async function GET7() {
9916
10011
 
9917
10012
  // app/api/admin/version/upgrade/route.ts
9918
10013
  import { spawn as spawn4 } from "child_process";
9919
- import { existsSync as existsSync16, statSync as statSync4, writeFileSync as writeFileSync9, readFileSync as readFileSync16, openSync as openSync2, closeSync as closeSync2 } from "fs";
10014
+ import { existsSync as existsSync17, statSync as statSync4, writeFileSync as writeFileSync10, readFileSync as readFileSync17, openSync as openSync2, closeSync as closeSync2 } from "fs";
9920
10015
  import { resolve as resolve14, join as join4 } from "path";
9921
10016
  var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve14(process.cwd(), "..");
9922
10017
  var upgradePkg = "@rubytech/create-maxy";
9923
10018
  var upgradeHostname = "maxy";
9924
10019
  var brandPath = join4(PLATFORM_ROOT7, "config", "brand.json");
9925
- if (existsSync16(brandPath)) {
10020
+ if (existsSync17(brandPath)) {
9926
10021
  try {
9927
- const brand = JSON.parse(readFileSync16(brandPath, "utf-8"));
10022
+ const brand = JSON.parse(readFileSync17(brandPath, "utf-8"));
9928
10023
  if (brand.npm?.packageName) upgradePkg = brand.npm.packageName;
9929
10024
  if (brand.hostname) upgradeHostname = brand.hostname;
9930
10025
  } catch {
@@ -9934,7 +10029,7 @@ var LOCK_FILE = `/tmp/${upgradeHostname}-upgrade.lock`;
9934
10029
  var LOG_FILE = `/tmp/${upgradeHostname}-upgrade.log`;
9935
10030
  var LOCK_MAX_AGE_MS = 3 * 60 * 1e3;
9936
10031
  function isLockFresh() {
9937
- if (!existsSync16(LOCK_FILE)) return false;
10032
+ if (!existsSync17(LOCK_FILE)) return false;
9938
10033
  try {
9939
10034
  const stat = statSync4(LOCK_FILE);
9940
10035
  return Date.now() - stat.mtimeMs < LOCK_MAX_AGE_MS;
@@ -9960,7 +10055,7 @@ async function POST14(req) {
9960
10055
  return Response.json({ ok: false, error: "upgrade already in progress" }, { status: 409 });
9961
10056
  }
9962
10057
  try {
9963
- writeFileSync9(LOCK_FILE, String(Date.now()));
10058
+ writeFileSync10(LOCK_FILE, String(Date.now()));
9964
10059
  } catch (err) {
9965
10060
  console.error("[admin/version/upgrade] failed to write lock file:", err);
9966
10061
  }
@@ -10090,12 +10185,12 @@ async function POST15() {
10090
10185
  var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
10091
10186
  var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join5(PLATFORM_ROOT8, "config", "brand.json") : "";
10092
10187
  var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", domain: "getmaxy.com" };
10093
- if (BRAND_JSON_PATH && !existsSync17(BRAND_JSON_PATH)) {
10188
+ if (BRAND_JSON_PATH && !existsSync18(BRAND_JSON_PATH)) {
10094
10189
  console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
10095
10190
  }
10096
- if (BRAND_JSON_PATH && existsSync17(BRAND_JSON_PATH)) {
10191
+ if (BRAND_JSON_PATH && existsSync18(BRAND_JSON_PATH)) {
10097
10192
  try {
10098
- const parsed = JSON.parse(readFileSync17(BRAND_JSON_PATH, "utf-8"));
10193
+ const parsed = JSON.parse(readFileSync18(BRAND_JSON_PATH, "utf-8"));
10099
10194
  BRAND = { ...BRAND, ...parsed };
10100
10195
  } catch (err) {
10101
10196
  console.error(`[brand] Failed to parse brand.json: ${err.message}`);
@@ -10110,8 +10205,8 @@ var brandLoginOpts = {
10110
10205
  var ALIAS_DOMAINS_PATH = join5(homedir2(), BRAND.configDir, "alias-domains.json");
10111
10206
  function loadAliasDomains() {
10112
10207
  try {
10113
- if (!existsSync17(ALIAS_DOMAINS_PATH)) return null;
10114
- const parsed = JSON.parse(readFileSync17(ALIAS_DOMAINS_PATH, "utf-8"));
10208
+ if (!existsSync18(ALIAS_DOMAINS_PATH)) return null;
10209
+ const parsed = JSON.parse(readFileSync18(ALIAS_DOMAINS_PATH, "utf-8"));
10115
10210
  if (!Array.isArray(parsed)) {
10116
10211
  console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
10117
10212
  return null;
@@ -10441,9 +10536,9 @@ app.get(
10441
10536
  );
10442
10537
  var htmlCache = /* @__PURE__ */ new Map();
10443
10538
  var brandLogoPath = "/brand/maxy-monochrome.png";
10444
- if (BRAND_JSON_PATH && existsSync17(BRAND_JSON_PATH)) {
10539
+ if (BRAND_JSON_PATH && existsSync18(BRAND_JSON_PATH)) {
10445
10540
  try {
10446
- const fullBrand = JSON.parse(readFileSync17(BRAND_JSON_PATH, "utf-8"));
10541
+ const fullBrand = JSON.parse(readFileSync18(BRAND_JSON_PATH, "utf-8"));
10447
10542
  if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
10448
10543
  } catch {
10449
10544
  }
@@ -10457,7 +10552,7 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
10457
10552
  function cachedHtml(file) {
10458
10553
  let html = htmlCache.get(file);
10459
10554
  if (!html) {
10460
- html = readFileSync17(resolve15(process.cwd(), "public", file), "utf-8");
10555
+ html = readFileSync18(resolve15(process.cwd(), "public", file), "utf-8");
10461
10556
  html = html.replace("</head>", `${brandScript}
10462
10557
  </head>`);
10463
10558
  htmlCache.set(file, html);
@@ -10469,13 +10564,13 @@ function loadBrandingCache(agentSlug) {
10469
10564
  const configDir = join5(homedir2(), BRAND.configDir);
10470
10565
  try {
10471
10566
  const accountJsonPath = join5(configDir, "account.json");
10472
- if (!existsSync17(accountJsonPath)) return null;
10473
- const account = JSON.parse(readFileSync17(accountJsonPath, "utf-8"));
10567
+ if (!existsSync18(accountJsonPath)) return null;
10568
+ const account = JSON.parse(readFileSync18(accountJsonPath, "utf-8"));
10474
10569
  const accountId = account.accountId;
10475
10570
  if (!accountId) return null;
10476
10571
  const cachePath = join5(configDir, "branding-cache", accountId, `${agentSlug}.json`);
10477
- if (!existsSync17(cachePath)) return null;
10478
- return JSON.parse(readFileSync17(cachePath, "utf-8"));
10572
+ if (!existsSync18(cachePath)) return null;
10573
+ return JSON.parse(readFileSync18(cachePath, "utf-8"));
10479
10574
  } catch {
10480
10575
  return null;
10481
10576
  }
@@ -10484,8 +10579,8 @@ function resolveDefaultSlug() {
10484
10579
  try {
10485
10580
  const configDir = join5(homedir2(), BRAND.configDir);
10486
10581
  const accountJsonPath = join5(configDir, "account.json");
10487
- if (!existsSync17(accountJsonPath)) return null;
10488
- const account = JSON.parse(readFileSync17(accountJsonPath, "utf-8"));
10582
+ if (!existsSync18(accountJsonPath)) return null;
10583
+ const account = JSON.parse(readFileSync18(accountJsonPath, "utf-8"));
10489
10584
  return account.defaultAgent || null;
10490
10585
  } catch {
10491
10586
  return null;
@@ -8,9 +8,15 @@
8
8
  // ----------------------------------------------------------
9
9
 
10
10
  // Person.email must be unique (waitlist signups, future users)
11
+ // Allows multiple nulls — phone-only contacts are not affected.
11
12
  CREATE CONSTRAINT person_email_unique IF NOT EXISTS
12
13
  FOR (p:Person) REQUIRE p.email IS UNIQUE;
13
14
 
15
+ // Person.telephone must be unique (phone-first channels: WhatsApp, SMS, Telegram)
16
+ // Allows multiple nulls — email-only contacts are not affected.
17
+ CREATE CONSTRAINT person_telephone_unique IF NOT EXISTS
18
+ FOR (p:Person) REQUIRE p.telephone IS UNIQUE;
19
+
14
20
  // Service.serviceId must be unique within the Maxy account
15
21
  CREATE CONSTRAINT service_id_unique IF NOT EXISTS
16
22
  FOR (s:Service) REQUIRE s.serviceId IS UNIQUE;
@@ -15,11 +15,11 @@ const accountId = process.env.ACCOUNT_ID;
15
15
  if (!accountId) {
16
16
  throw new Error("ACCOUNT_ID environment variable is required");
17
17
  }
18
- server.tool("contact-create", "Create a new contact (schema:Person) in the graph. Deduplicates by email — returns existing contact if email already exists.", {
18
+ server.tool("contact-create", "Create a new contact (schema:Person) in the graph. Requires at least one of email or telephone. Deduplicates by whichever identifier is provided — returns existing contact if email or phone already exists.", {
19
19
  givenName: z.string().describe("First name"),
20
20
  familyName: z.string().optional().describe("Last name"),
21
- email: z.string().email().describe("Email address (canonical identifier)"),
22
- telephone: z.string().optional().describe("Phone number"),
21
+ email: z.string().email().optional().describe("Email address (identifier — at least one of email or telephone required)"),
22
+ telephone: z.string().min(1).max(30).optional().describe("Phone number (identifier — at least one of email or telephone required)"),
23
23
  jobTitle: z.string().optional().describe("Job title"),
24
24
  source: z
25
25
  .string()
@@ -36,7 +36,7 @@ server.tool("contact-create", "Create a new contact (schema:Person) in the graph
36
36
  content: [
37
37
  {
38
38
  type: "text",
39
- text: `Contact already exists with email ${result.email} (ID: ${result.nodeId}). No duplicate created.`,
39
+ text: `Contact already exists with ${result.identifier} (ID: ${result.nodeId}). No duplicate created.`,
40
40
  },
41
41
  ],
42
42
  };
@@ -45,7 +45,7 @@ server.tool("contact-create", "Create a new contact (schema:Person) in the graph
45
45
  content: [
46
46
  {
47
47
  type: "text",
48
- text: `Contact created: ${params.givenName} <${result.email}> (ID: ${result.nodeId}, status: ${params.status ?? "waitlist"})`,
48
+ text: `Contact created: ${params.givenName} ${result.identifier} (ID: ${result.nodeId}, status: ${params.status ?? "waitlist"})`,
49
49
  },
50
50
  ],
51
51
  };
@@ -62,13 +62,14 @@ server.tool("contact-create", "Create a new contact (schema:Person) in the graph
62
62
  };
63
63
  }
64
64
  });
65
- server.tool("contact-lookup", "Search for contacts by email, name, or list recent contacts. Returns schema:Person nodes.", {
65
+ server.tool("contact-lookup", "Search for contacts by email, telephone, name, or list recent contacts. Returns schema:Person nodes.", {
66
66
  email: z.string().optional().describe("Exact email match"),
67
+ telephone: z.string().optional().describe("Exact phone number match"),
67
68
  name: z.string().optional().describe("Partial name search (first or last name)"),
68
69
  limit: z.number().int().optional().describe("Max results (default 10)"),
69
- }, async ({ email, name, limit }) => {
70
+ }, async ({ email, telephone, name, limit }) => {
70
71
  try {
71
- const results = await contactLookup({ email, name, accountId, limit });
72
+ const results = await contactLookup({ email, telephone, name, accountId, limit });
72
73
  if (results.length === 0) {
73
74
  return {
74
75
  content: [
@@ -77,7 +78,14 @@ server.tool("contact-lookup", "Search for contacts by email, name, or list recen
77
78
  };
78
79
  }
79
80
  const formatted = results
80
- .map((c) => `${c.givenName}${c.familyName ? ` ${c.familyName}` : ""} <${c.email}> — ${c.status} (from ${c.source}, ${c.createdOn})`)
81
+ .map((c) => {
82
+ const identifierPart = c.email
83
+ ? `<${c.email}>`
84
+ : c.telephone
85
+ ? `<${c.telephone}>`
86
+ : "";
87
+ return `${c.givenName}${c.familyName ? ` ${c.familyName}` : ""} ${identifierPart} — ${c.status} (from ${c.source}, ${c.createdOn})`;
88
+ })
81
89
  .join("\n");
82
90
  return {
83
91
  content: [{ type: "text", text: formatted }],
@@ -95,16 +103,18 @@ server.tool("contact-lookup", "Search for contacts by email, name, or list recen
95
103
  };
96
104
  }
97
105
  });
98
- server.tool("contact-update", "Update properties of an existing contact. Cannot change email or accountId.", {
106
+ server.tool("contact-update", "Update properties of an existing contact. Identify by nodeId, email, or telephone. Cannot change email or accountId.", {
99
107
  email: z.string().optional().describe("Find contact by email"),
108
+ telephone: z.string().optional().describe("Find contact by phone number"),
100
109
  nodeId: z.string().optional().describe("Find contact by node ID"),
101
110
  updates: z
102
111
  .record(z.string(), z.unknown())
103
112
  .describe("Properties to update (e.g. status, telephone, jobTitle)"),
104
- }, async ({ email, nodeId, updates }) => {
113
+ }, async ({ email, telephone, nodeId, updates }) => {
105
114
  try {
106
115
  const result = await contactUpdate({
107
116
  email,
117
+ telephone,
108
118
  nodeId,
109
119
  updates: updates,
110
120
  accountId,
@@ -156,7 +166,14 @@ server.tool("contact-list", "List contacts with optional filters. Returns summar
156
166
  }
157
167
  const header = `${result.total} total contacts${params.status ? ` with status '${params.status}'` : ""}:\n\n`;
158
168
  const formatted = result.contacts
159
- .map((c) => `${c.givenName}${c.familyName ? ` ${c.familyName}` : ""} <${c.email}> — ${c.status} (${c.source}, ${c.createdOn})`)
169
+ .map((c) => {
170
+ const identifierPart = c.email
171
+ ? `<${c.email}>`
172
+ : c.telephone
173
+ ? `<${c.telephone}>`
174
+ : "";
175
+ return `${c.givenName}${c.familyName ? ` ${c.familyName}` : ""} ${identifierPart} — ${c.status} (${c.source}, ${c.createdOn})`;
176
+ })
160
177
  .join("\n");
161
178
  return {
162
179
  content: [{ type: "text", text: header + formatted }],
@@ -174,17 +191,18 @@ server.tool("contact-list", "List contacts with optional filters. Returns summar
174
191
  };
175
192
  }
176
193
  });
177
- server.tool("contact-delete", "Permanently delete a contact (Person node) and all its relationships from the graph. Identify the contact by email or node ID. This is irreversible.", {
194
+ server.tool("contact-delete", "Permanently delete a contact (Person node) and all its relationships from the graph. Identify by email, telephone, or node ID. This is irreversible.", {
178
195
  email: z.string().optional().describe("Find contact by email"),
196
+ telephone: z.string().optional().describe("Find contact by phone number"),
179
197
  nodeId: z.string().optional().describe("Find contact by node ID"),
180
- }, async ({ email, nodeId }) => {
198
+ }, async ({ email, telephone, nodeId }) => {
181
199
  try {
182
- const result = await contactDelete({ email, nodeId, accountId });
200
+ const result = await contactDelete({ email, telephone, nodeId, accountId });
183
201
  return {
184
202
  content: [
185
203
  {
186
204
  type: "text",
187
- text: `Contact deleted: ${result.email}`,
205
+ text: `Contact deleted: ${result.identifier}`,
188
206
  },
189
207
  ],
190
208
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  interface ContactCreateParams {
2
2
  givenName: string;
3
3
  familyName?: string;
4
- email: string;
4
+ email?: string;
5
5
  telephone?: string;
6
6
  jobTitle?: string;
7
7
  source: string;
@@ -10,7 +10,7 @@ interface ContactCreateParams {
10
10
  }
11
11
  interface ContactCreateResult {
12
12
  nodeId: string;
13
- email: string;
13
+ identifier: string;
14
14
  created: boolean;
15
15
  alreadyExists: boolean;
16
16
  }
@@ -1 +1 @@
1
- {"version":3,"file":"contact-create.d.ts","sourceRoot":"","sources":["../../src/tools/contact-create.ts"],"names":[],"mappings":"AAqBA,UAAU,mBAAmB;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,mBAAmB;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CAiE9B"}
1
+ {"version":3,"file":"contact-create.d.ts","sourceRoot":"","sources":["../../src/tools/contact-create.ts"],"names":[],"mappings":"AAqBA,UAAU,mBAAmB;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,mBAAmB;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CA+F9B"}
@@ -20,14 +20,34 @@ async function computeEmbedding(text) {
20
20
  }
21
21
  export async function contactCreate(params) {
22
22
  const { givenName, familyName, email, telephone, jobTitle, source, status = "waitlist", accountId, } = params;
23
+ const normalizedEmail = email?.toLowerCase().trim();
24
+ const normalizedPhone = telephone?.trim();
25
+ if (!normalizedEmail && !normalizedPhone) {
26
+ throw new Error("At least one of email or telephone is required");
27
+ }
23
28
  const session = getSession();
24
29
  try {
25
- // Check for existing contact by email (dedup)
26
- const existing = await session.run(`MATCH (p:Person {email: $email, accountId: $accountId}) RETURN elementId(p) AS nodeId`, { email: email.toLowerCase(), accountId });
30
+ // Dedup: check for existing contact by whichever identifiers are provided (OR logic)
31
+ const dedupConditions = [];
32
+ const dedupParams = { accountId };
33
+ if (normalizedEmail) {
34
+ dedupConditions.push("p.email = $email");
35
+ dedupParams.email = normalizedEmail;
36
+ }
37
+ if (normalizedPhone) {
38
+ dedupConditions.push("p.telephone = $telephone");
39
+ dedupParams.telephone = normalizedPhone;
40
+ }
41
+ const existing = await session.run(`MATCH (p:Person {accountId: $accountId})
42
+ WHERE ${dedupConditions.join(" OR ")}
43
+ RETURN elementId(p) AS nodeId, p.email AS email, p.telephone AS telephone`, dedupParams);
27
44
  if (existing.records.length > 0) {
45
+ const matchedEmail = existing.records[0].get("email");
46
+ const matchedPhone = existing.records[0].get("telephone");
47
+ const matchedIdentifier = matchedEmail ?? matchedPhone ?? "unknown";
28
48
  return {
29
49
  nodeId: existing.records[0].get("nodeId"),
30
- email: email.toLowerCase(),
50
+ identifier: matchedIdentifier,
31
51
  created: false,
32
52
  alreadyExists: true,
33
53
  };
@@ -35,28 +55,33 @@ export async function contactCreate(params) {
35
55
  // Create new Person node (schema:Person)
36
56
  const props = {
37
57
  givenName,
38
- email: email.toLowerCase(),
39
58
  source,
40
59
  status,
41
60
  accountId,
42
61
  createdOn: new Date().toISOString(),
43
62
  };
63
+ if (normalizedEmail)
64
+ props.email = normalizedEmail;
65
+ if (normalizedPhone)
66
+ props.telephone = normalizedPhone;
44
67
  if (familyName)
45
68
  props.familyName = familyName;
46
- if (telephone)
47
- props.telephone = telephone;
48
69
  if (jobTitle)
49
70
  props.jobTitle = jobTitle;
50
- // Compute embedding for vector search
51
- const textForEmbedding = `Person: ${givenName}${familyName ? ` ${familyName}` : ""} <${email}> source: ${source} status: ${status}`;
71
+ // Compute embedding for vector search — use whichever identifier is available
72
+ const identifierText = normalizedEmail
73
+ ? `<${normalizedEmail}>`
74
+ : normalizedPhone ?? "";
75
+ const textForEmbedding = `Person: ${givenName}${familyName ? ` ${familyName}` : ""} ${identifierText} source: ${source} status: ${status}`;
52
76
  const embedding = await computeEmbedding(textForEmbedding);
53
77
  if (embedding.length > 0) {
54
78
  props.embedding = embedding;
55
79
  }
56
80
  const result = await session.run(`CREATE (p:Person $props) RETURN elementId(p) AS nodeId`, { props });
81
+ const primaryIdentifier = normalizedEmail ?? normalizedPhone ?? "unknown";
57
82
  return {
58
83
  nodeId: result.records[0].get("nodeId"),
59
- email: email.toLowerCase(),
84
+ identifier: primaryIdentifier,
60
85
  created: true,
61
86
  alreadyExists: false,
62
87
  };
@@ -1 +1 @@
1
- {"version":3,"file":"contact-create.js","sourceRoot":"","sources":["../../src/tools/contact-create.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"contact-create.js","sourceRoot":"","sources":["../../src/tools/contact-create.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,12 @@
1
1
  interface ContactDeleteParams {
2
2
  nodeId?: string;
3
3
  email?: string;
4
+ telephone?: string;
4
5
  accountId?: string;
5
6
  }
6
7
  interface ContactDeleteResult {
7
8
  deleted: boolean;
8
- email: string;
9
+ identifier: string;
9
10
  }
10
11
  export declare function contactDelete(params: ContactDeleteParams): Promise<ContactDeleteResult>;
11
12
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"contact-delete.d.ts","sourceRoot":"","sources":["../../src/tools/contact-delete.ts"],"names":[],"mappings":"AAEA,UAAU,mBAAmB;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,mBAAmB;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CAwC9B"}
1
+ {"version":3,"file":"contact-delete.d.ts","sourceRoot":"","sources":["../../src/tools/contact-delete.ts"],"names":[],"mappings":"AAEA,UAAU,mBAAmB;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,mBAAmB;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CA8C9B"}
@@ -1,8 +1,8 @@
1
1
  import { getSession } from "../lib/neo4j.js";
2
2
  export async function contactDelete(params) {
3
- const { nodeId, email, accountId } = params;
4
- if (!nodeId && !email) {
5
- throw new Error("Either nodeId or email must be provided");
3
+ const { nodeId, email, telephone, accountId } = params;
4
+ if (!nodeId && !email && !telephone) {
5
+ throw new Error("Either nodeId, email, or telephone must be provided");
6
6
  }
7
7
  const session = getSession();
8
8
  try {
@@ -12,20 +12,26 @@ export async function contactDelete(params) {
12
12
  matchClause = `MATCH (p:Person) WHERE elementId(p) = $nodeId AND p.accountId = $accountId`;
13
13
  queryParams.nodeId = nodeId;
14
14
  }
15
- else {
15
+ else if (email) {
16
16
  matchClause = `MATCH (p:Person {email: $email, accountId: $accountId})`;
17
17
  queryParams.email = email.toLowerCase();
18
18
  }
19
+ else {
20
+ matchClause = `MATCH (p:Person {telephone: $telephone, accountId: $accountId})`;
21
+ queryParams.telephone = telephone.trim();
22
+ }
19
23
  const result = await session.run(`${matchClause}
20
- WITH p, p.email AS deletedEmail
24
+ WITH p, p.email AS deletedEmail, p.telephone AS deletedPhone
21
25
  DETACH DELETE p
22
- RETURN deletedEmail`, queryParams);
26
+ RETURN deletedEmail, deletedPhone`, queryParams);
23
27
  if (result.records.length === 0) {
24
28
  throw new Error("Contact not found");
25
29
  }
30
+ const deletedEmail = result.records[0].get("deletedEmail");
31
+ const deletedPhone = result.records[0].get("deletedPhone");
26
32
  return {
27
33
  deleted: true,
28
- email: result.records[0].get("deletedEmail"),
34
+ identifier: deletedEmail ?? deletedPhone ?? "unknown",
29
35
  };
30
36
  }
31
37
  finally {
@@ -1 +1 @@
1
- {"version":3,"file":"contact-delete.js","sourceRoot":"","sources":["../../src/tools/contact-delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAa7C,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAA2B;IAE3B,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IAE5C,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,IAAI,WAAmB,CAAC;QACxB,MAAM,WAAW,GAA4B,EAAE,SAAS,EAAE,CAAC;QAE3D,IAAI,MAAM,EAAE,CAAC;YACX,WAAW,GAAG,4EAA4E,CAAC;YAC3F,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC;QAC9B,CAAC;aAAM,CAAC;YACN,WAAW,GAAG,yDAAyD,CAAC;YACxE,WAAW,CAAC,KAAK,GAAG,KAAM,CAAC,WAAW,EAAE,CAAC;QAC3C,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B,GAAG,WAAW;;;2BAGO,EACrB,WAAW,CACZ,CAAC;QAEF,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACvC,CAAC;QAED,OAAO;YACL,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAW;SACvD,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"contact-delete.js","sourceRoot":"","sources":["../../src/tools/contact-delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAc7C,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAA2B;IAE3B,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IAEvD,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,IAAI,WAAmB,CAAC;QACxB,MAAM,WAAW,GAA4B,EAAE,SAAS,EAAE,CAAC;QAE3D,IAAI,MAAM,EAAE,CAAC;YACX,WAAW,GAAG,4EAA4E,CAAC;YAC3F,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC;QAC9B,CAAC;aAAM,IAAI,KAAK,EAAE,CAAC;YACjB,WAAW,GAAG,yDAAyD,CAAC;YACxE,WAAW,CAAC,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,WAAW,GAAG,iEAAiE,CAAC;YAChF,WAAW,CAAC,SAAS,GAAG,SAAU,CAAC,IAAI,EAAE,CAAC;QAC5C,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B,GAAG,WAAW;;;yCAGqB,EACnC,WAAW,CACZ,CAAC;QAEF,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACvC,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAkB,CAAC;QAC5E,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAkB,CAAC;QAE5E,OAAO;YACL,OAAO,EAAE,IAAI;YACb,UAAU,EAAE,YAAY,IAAI,YAAY,IAAI,SAAS;SACtD,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
@@ -9,7 +9,8 @@ interface ContactSummary {
9
9
  nodeId: string;
10
10
  givenName: string;
11
11
  familyName?: string;
12
- email: string;
12
+ email?: string;
13
+ telephone?: string;
13
14
  status: string;
14
15
  source: string;
15
16
  createdOn: string;
@@ -1 +1 @@
1
- {"version":3,"file":"contact-list.d.ts","sourceRoot":"","sources":["../../src/tools/contact-list.ts"],"names":[],"mappings":"AAGA,UAAU,iBAAiB;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,cAAc;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC;IAAE,QAAQ,EAAE,cAAc,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAkExD"}
1
+ {"version":3,"file":"contact-list.d.ts","sourceRoot":"","sources":["../../src/tools/contact-list.ts"],"names":[],"mappings":"AAGA,UAAU,iBAAiB;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,cAAc;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC;IAAE,QAAQ,EAAE,cAAc,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAmExD"}
@@ -33,6 +33,7 @@ export async function contactList(params) {
33
33
  givenName: p.givenName,
34
34
  familyName: p.familyName,
35
35
  email: p.email,
36
+ telephone: p.telephone,
36
37
  status: p.status,
37
38
  source: p.source,
38
39
  createdOn: p.createdOn,
@@ -1 +1 @@
1
- {"version":3,"file":"contact-list.js","sourceRoot":"","sources":["../../src/tools/contact-list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,cAAc,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAoB7C,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAyB;IAEzB,MAAM,EACJ,MAAM,EACN,MAAM,EACN,KAAK,EACL,SAAS,EACT,KAAK,GAAG,EAAE,GACX,GAAG,MAAM,CAAC;IAEX,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,CAAC,0BAA0B,CAAC,CAAC;QAChD,MAAM,WAAW,GAA4B,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QAEpF,IAAI,MAAM,EAAE,CAAC;YACX,UAAU,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;YACtC,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC;QAC9B,CAAC;QAED,IAAI,MAAM,EAAE,CAAC;YACX,UAAU,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;YACtC,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC;QAC9B,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV,UAAU,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;YACzC,WAAW,CAAC,KAAK,GAAG,KAAK,CAAC;QAC5B,CAAC;QAED,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAE7C,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,GAAG,CACnC,0BAA0B,WAAW,2BAA2B,EAChE,WAAW,CACZ,CAAC;QACF,MAAM,KAAK,GACT,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CACnC,CAAC,QAAQ,EAAE,CAAC;QAEb,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,GAAG,CAClC;eACS,WAAW;;;oBAGN,EACd,WAAW,CACZ,CAAC;QAEF,MAAM,QAAQ,GAAqB,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;YACnE,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC;YACrC,OAAO;gBACL,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAW;gBACtC,SAAS,EAAE,CAAC,CAAC,SAAmB;gBAChC,UAAU,EAAE,CAAC,CAAC,UAAgC;gBAC9C,KAAK,EAAE,CAAC,CAAC,KAAe;gBACxB,MAAM,EAAE,CAAC,CAAC,MAAgB;gBAC1B,MAAM,EAAE,CAAC,CAAC,MAAgB;gBAC1B,SAAS,EAAE,CAAC,CAAC,SAAmB;aACjC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC7B,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"contact-list.js","sourceRoot":"","sources":["../../src/tools/contact-list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,cAAc,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAqB7C,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAyB;IAEzB,MAAM,EACJ,MAAM,EACN,MAAM,EACN,KAAK,EACL,SAAS,EACT,KAAK,GAAG,EAAE,GACX,GAAG,MAAM,CAAC;IAEX,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,CAAC,0BAA0B,CAAC,CAAC;QAChD,MAAM,WAAW,GAA4B,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QAEpF,IAAI,MAAM,EAAE,CAAC;YACX,UAAU,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;YACtC,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC;QAC9B,CAAC;QAED,IAAI,MAAM,EAAE,CAAC;YACX,UAAU,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;YACtC,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC;QAC9B,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV,UAAU,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;YACzC,WAAW,CAAC,KAAK,GAAG,KAAK,CAAC;QAC5B,CAAC;QAED,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAE7C,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,GAAG,CACnC,0BAA0B,WAAW,2BAA2B,EAChE,WAAW,CACZ,CAAC;QACF,MAAM,KAAK,GACT,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CACnC,CAAC,QAAQ,EAAE,CAAC;QAEb,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,GAAG,CAClC;eACS,WAAW;;;oBAGN,EACd,WAAW,CACZ,CAAC;QAEF,MAAM,QAAQ,GAAqB,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;YACnE,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC;YACrC,OAAO;gBACL,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAW;gBACtC,SAAS,EAAE,CAAC,CAAC,SAAmB;gBAChC,UAAU,EAAE,CAAC,CAAC,UAAgC;gBAC9C,KAAK,EAAE,CAAC,CAAC,KAA2B;gBACpC,SAAS,EAAE,CAAC,CAAC,SAA+B;gBAC5C,MAAM,EAAE,CAAC,CAAC,MAAgB;gBAC1B,MAAM,EAAE,CAAC,CAAC,MAAgB;gBAC1B,SAAS,EAAE,CAAC,CAAC,SAAmB;aACjC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC7B,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
@@ -1,5 +1,6 @@
1
1
  interface ContactLookupParams {
2
2
  email?: string;
3
+ telephone?: string;
3
4
  name?: string;
4
5
  accountId?: string;
5
6
  limit?: number;
@@ -8,7 +9,7 @@ interface ContactRecord {
8
9
  nodeId: string;
9
10
  givenName: string;
10
11
  familyName?: string;
11
- email: string;
12
+ email?: string;
12
13
  telephone?: string;
13
14
  jobTitle?: string;
14
15
  source: string;
@@ -1 +1 @@
1
- {"version":3,"file":"contact-lookup.d.ts","sourceRoot":"","sources":["../../src/tools/contact-lookup.ts"],"names":[],"mappings":"AAGA,UAAU,mBAAmB;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,aAAa;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,aAAa,EAAE,CAAC,CAuD1B"}
1
+ {"version":3,"file":"contact-lookup.d.ts","sourceRoot":"","sources":["../../src/tools/contact-lookup.ts"],"names":[],"mappings":"AAGA,UAAU,mBAAmB;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,aAAa;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,aAAa,EAAE,CAAC,CA+D1B"}
@@ -1,7 +1,7 @@
1
1
  import neo4j from "neo4j-driver";
2
2
  import { getSession } from "../lib/neo4j.js";
3
3
  export async function contactLookup(params) {
4
- const { email, name, accountId, limit = 10 } = params;
4
+ const { email, telephone, name, accountId, limit = 10 } = params;
5
5
  const session = getSession();
6
6
  try {
7
7
  let query;
@@ -15,6 +15,15 @@ export async function contactLookup(params) {
15
15
  `;
16
16
  queryParams = { email: email.toLowerCase(), accountId, limit: neo4j.int(limit) };
17
17
  }
18
+ else if (telephone) {
19
+ query = `
20
+ MATCH (p:Person {accountId: $accountId})
21
+ WHERE p.telephone = $telephone
22
+ RETURN p, elementId(p) AS nodeId
23
+ LIMIT $limit
24
+ `;
25
+ queryParams = { telephone: telephone.trim(), accountId, limit: neo4j.int(limit) };
26
+ }
18
27
  else if (name) {
19
28
  query = `
20
29
  MATCH (p:Person {accountId: $accountId})
@@ -1 +1 @@
1
- {"version":3,"file":"contact-lookup.js","sourceRoot":"","sources":["../../src/tools/contact-lookup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,cAAc,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAqB7C,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAA2B;IAE3B,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,GAAG,EAAE,EAAE,GAAG,MAAM,CAAC;IAEtD,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,IAAI,KAAa,CAAC;QAClB,IAAI,WAAoC,CAAC;QAEzC,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,GAAG;;;;;OAKP,CAAC;YACF,WAAW,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QACnF,CAAC;aAAM,IAAI,IAAI,EAAE,CAAC;YAChB,KAAK,GAAG;;;;;;OAMP,CAAC;YACF,WAAW,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7D,CAAC;aAAM,CAAC;YACN,KAAK,GAAG;;;;;OAKP,CAAC;YACF,WAAW,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QACvD,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QAErD,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;YACnC,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC;YACrC,OAAO;gBACL,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAW;gBACtC,SAAS,EAAE,CAAC,CAAC,SAAmB;gBAChC,UAAU,EAAE,CAAC,CAAC,UAAgC;gBAC9C,KAAK,EAAE,CAAC,CAAC,KAAe;gBACxB,SAAS,EAAE,CAAC,CAAC,SAA+B;gBAC5C,QAAQ,EAAE,CAAC,CAAC,QAA8B;gBAC1C,MAAM,EAAE,CAAC,CAAC,MAAgB;gBAC1B,MAAM,EAAE,CAAC,CAAC,MAAgB;gBAC1B,SAAS,EAAE,CAAC,CAAC,SAAmB;aACjC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"contact-lookup.js","sourceRoot":"","sources":["../../src/tools/contact-lookup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,cAAc,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAsB7C,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAA2B;IAE3B,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,GAAG,EAAE,EAAE,GAAG,MAAM,CAAC;IAEjE,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,IAAI,KAAa,CAAC;QAClB,IAAI,WAAoC,CAAC;QAEzC,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,GAAG;;;;;OAKP,CAAC;YACF,WAAW,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QACnF,CAAC;aAAM,IAAI,SAAS,EAAE,CAAC;YACrB,KAAK,GAAG;;;;;OAKP,CAAC;YACF,WAAW,GAAG,EAAE,SAAS,EAAE,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QACpF,CAAC;aAAM,IAAI,IAAI,EAAE,CAAC;YAChB,KAAK,GAAG;;;;;;OAMP,CAAC;YACF,WAAW,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7D,CAAC;aAAM,CAAC;YACN,KAAK,GAAG;;;;;OAKP,CAAC;YACF,WAAW,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QACvD,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QAErD,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;YACnC,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC;YACrC,OAAO;gBACL,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAW;gBACtC,SAAS,EAAE,CAAC,CAAC,SAAmB;gBAChC,UAAU,EAAE,CAAC,CAAC,UAAgC;gBAC9C,KAAK,EAAE,CAAC,CAAC,KAA2B;gBACpC,SAAS,EAAE,CAAC,CAAC,SAA+B;gBAC5C,QAAQ,EAAE,CAAC,CAAC,QAA8B;gBAC1C,MAAM,EAAE,CAAC,CAAC,MAAgB;gBAC1B,MAAM,EAAE,CAAC,CAAC,MAAgB;gBAC1B,SAAS,EAAE,CAAC,CAAC,SAAmB;aACjC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
@@ -1,6 +1,7 @@
1
1
  interface ContactUpdateParams {
2
2
  nodeId?: string;
3
3
  email?: string;
4
+ telephone?: string;
4
5
  updates: Record<string, unknown>;
5
6
  accountId?: string;
6
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"contact-update.d.ts","sourceRoot":"","sources":["../../src/tools/contact-update.ts"],"names":[],"mappings":"AAEA,UAAU,mBAAmB;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,mBAAmB;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CA4D9B"}
1
+ {"version":3,"file":"contact-update.d.ts","sourceRoot":"","sources":["../../src/tools/contact-update.ts"],"names":[],"mappings":"AAEA,UAAU,mBAAmB;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,mBAAmB;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CA+D9B"}
@@ -1,8 +1,8 @@
1
1
  import { getSession } from "../lib/neo4j.js";
2
2
  export async function contactUpdate(params) {
3
- const { nodeId, email, updates, accountId } = params;
4
- if (!nodeId && !email) {
5
- throw new Error("Either nodeId or email must be provided");
3
+ const { nodeId, email, telephone, updates, accountId } = params;
4
+ if (!nodeId && !email && !telephone) {
5
+ throw new Error("Either nodeId, email, or telephone must be provided");
6
6
  }
7
7
  const session = getSession();
8
8
  try {
@@ -12,10 +12,14 @@ export async function contactUpdate(params) {
12
12
  matchClause = `MATCH (p:Person) WHERE elementId(p) = $nodeId AND p.accountId = $accountId`;
13
13
  queryParams.nodeId = nodeId;
14
14
  }
15
- else {
15
+ else if (email) {
16
16
  matchClause = `MATCH (p:Person {email: $email, accountId: $accountId})`;
17
17
  queryParams.email = email.toLowerCase();
18
18
  }
19
+ else {
20
+ matchClause = `MATCH (p:Person {telephone: $telephone, accountId: $accountId})`;
21
+ queryParams.telephone = telephone.trim();
22
+ }
19
23
  // Build SET clauses from updates (excluding protected fields)
20
24
  const protectedFields = new Set(["accountId", "email", "createdOn", "embedding"]);
21
25
  const setClauses = [];
@@ -1 +1 @@
1
- {"version":3,"file":"contact-update.js","sourceRoot":"","sources":["../../src/tools/contact-update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAc7C,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAA2B;IAE3B,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IAErD,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,IAAI,WAAmB,CAAC;QACxB,MAAM,WAAW,GAA4B,EAAE,SAAS,EAAE,CAAC;QAE3D,IAAI,MAAM,EAAE,CAAC;YACX,WAAW,GAAG,4EAA4E,CAAC;YAC3F,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC;QAC9B,CAAC;aAAM,CAAC;YACN,WAAW,GAAG,yDAAyD,CAAC;YACxE,WAAW,CAAC,KAAK,GAAG,KAAM,CAAC,WAAW,EAAE,CAAC;QAC3C,CAAC;QAED,8DAA8D;QAC9D,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;QAClF,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,IAAI,UAAU,GAAG,CAAC,CAAC;QAEnB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACnD,IAAI,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,SAAS;YACvC,MAAM,SAAS,GAAG,OAAO,UAAU,EAAE,CAAC;YACtC,UAAU,CAAC,IAAI,CAAC,KAAK,GAAG,OAAO,SAAS,EAAE,CAAC,CAAC;YAC5C,WAAW,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;YAC/B,UAAU,EAAE,CAAC;QACf,CAAC;QAED,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC/C,CAAC;QAED,UAAU,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QAC5C,WAAW,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAEjD,MAAM,KAAK,GAAG;QACV,WAAW;YACP,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;;KAE5B,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QAErD,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACvC,CAAC;QAED,OAAO;YACL,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAW;YACjD,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"contact-update.js","sourceRoot":"","sources":["../../src/tools/contact-update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAe7C,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAA2B;IAE3B,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IAEhE,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,IAAI,WAAmB,CAAC;QACxB,MAAM,WAAW,GAA4B,EAAE,SAAS,EAAE,CAAC;QAE3D,IAAI,MAAM,EAAE,CAAC;YACX,WAAW,GAAG,4EAA4E,CAAC;YAC3F,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC;QAC9B,CAAC;aAAM,IAAI,KAAK,EAAE,CAAC;YACjB,WAAW,GAAG,yDAAyD,CAAC;YACxE,WAAW,CAAC,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,WAAW,GAAG,iEAAiE,CAAC;YAChF,WAAW,CAAC,SAAS,GAAG,SAAU,CAAC,IAAI,EAAE,CAAC;QAC5C,CAAC;QAED,8DAA8D;QAC9D,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;QAClF,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,IAAI,UAAU,GAAG,CAAC,CAAC;QAEnB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACnD,IAAI,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,SAAS;YACvC,MAAM,SAAS,GAAG,OAAO,UAAU,EAAE,CAAC;YACtC,UAAU,CAAC,IAAI,CAAC,KAAK,GAAG,OAAO,SAAS,EAAE,CAAC,CAAC;YAC5C,WAAW,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;YAC/B,UAAU,EAAE,CAAC;QACf,CAAC;QAED,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC/C,CAAC;QAED,UAAU,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QAC5C,WAAW,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAEjD,MAAM,KAAK,GAAG;QACV,WAAW;YACP,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;;KAE5B,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QAErD,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACvC,CAAC;QAED,OAAO;YACL,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAW;YACjD,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## What a Contact Is
4
4
 
5
- A contact is a Person node in Maxy's memory graph. Each person has a first name and email address, plus optional fields like last name, phone number, and job title. Contacts are linked to conversations, other people, and business context.
5
+ A contact is a Person node in Maxy's memory graph. Each person has a first name and at least one identifier — email address, phone number, or both. Optional fields include last name and job title. Contacts are linked to conversations, other people, and business context.
6
6
 
7
7
  ## Adding a Contact
8
8
 
@@ -10,10 +10,11 @@ Tell Maxy naturally:
10
10
 
11
11
  - "Add John Smith to my contacts — he's a potential client I met at the conference"
12
12
  - "Create a contact for sarah@acme.com, her name is Sarah Chen, she's the head of procurement at Acme"
13
+ - "Add Hazel to contacts, phone +27747309676, she's a virtual assistant"
13
14
 
14
15
  Maxy will extract the details and confirm the record before saving.
15
16
 
16
- Required: first name and email address. Everything else is optional but useful.
17
+ Required: first name and at least one of email or phone number. Everything else is optional but useful.
17
18
 
18
19
  ## Looking Up a Contact
19
20
 
@@ -22,8 +23,9 @@ Ask naturally:
22
23
  - "What do you know about John Smith?"
23
24
  - "Look up Sarah Chen"
24
25
  - "Find the contact from Acme procurement"
26
+ - "Look up +27747309676"
25
27
 
26
- Maxy searches by name, company, email, or any detail you provide.
28
+ Maxy searches by name, email, phone number, or any detail you provide.
27
29
 
28
30
  ## Updating a Contact
29
31
 
@@ -51,8 +53,8 @@ To review the waitlist: "Show me the waitlist" or "Who's on the waitlist?"
51
53
  |-------|-------------|
52
54
  | `givenName` | First name (required) |
53
55
  | `familyName` | Last name (optional) |
54
- | `email` | Email address (required — used to deduplicate contacts) |
55
- | `telephone` | Phone number |
56
+ | `email` | Email address (identifierat least one of email or telephone required; used to deduplicate) |
57
+ | `telephone` | Phone number (identifier — at least one of email or telephone required; used to deduplicate) |
56
58
  | `jobTitle` | Job title or role |
57
59
  | `source` | Where this contact came from (e.g. "public.maxy.bot", "telegram", "manual") |
58
60
  | `status` | Contact status (e.g. "active", "prospect", "waitlist") |