@datasynx/agentic-crm 1.5.0 → 1.7.0

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 (49) hide show
  1. package/dist/cli.js +70 -76
  2. package/dist/cli.js.map +1 -1
  3. package/dist/daemon/worker.js +40 -1
  4. package/dist/daemon/worker.js.map +1 -1
  5. package/dist/{imap-o6PRuBvm.js → imap-BRgNh3T3.js} +2 -2
  6. package/dist/{imap-o6PRuBvm.js.map → imap-BRgNh3T3.js.map} +1 -1
  7. package/dist/imap-DzeqMdZ3.js +2 -0
  8. package/dist/{index-FzDsNSSb.d.ts → index-BBAlKZg6.d.ts} +3 -3
  9. package/dist/{index-FzDsNSSb.d.ts.map → index-BBAlKZg6.d.ts.map} +1 -1
  10. package/dist/{index-B5_QnkG8.d.cts → index-DcDaz_cu.d.cts} +16 -16
  11. package/dist/index-DcDaz_cu.d.cts.map +1 -0
  12. package/dist/index.d.cts +16 -16
  13. package/dist/index.d.cts.map +1 -1
  14. package/dist/index.d.ts +3 -3
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/{knowledge-base-Bx2PKQR2.js → knowledge-base-Cc0niBFf.js} +2 -1
  17. package/dist/knowledge-base-Cc0niBFf.js.map +1 -0
  18. package/dist/{login-CYgla6-A.js → login-yt9OOQQk.js} +3 -2
  19. package/dist/{login-CYgla6-A.js.map → login-yt9OOQQk.js.map} +1 -1
  20. package/dist/mailbox-config-Bu-J1O4I.js +2 -0
  21. package/dist/mailbox-config-Dn2xTn9N.js +67 -0
  22. package/dist/mailbox-config-Dn2xTn9N.js.map +1 -0
  23. package/dist/mailbox-poll-B8dvFAXT.js +80 -0
  24. package/dist/mailbox-poll-B8dvFAXT.js.map +1 -0
  25. package/dist/mcp-CdTJWTJf.d.cts.map +1 -1
  26. package/dist/mcp-CdTJWTJf.d.ts.map +1 -1
  27. package/dist/mcp.cjs +289 -130
  28. package/dist/mcp.cjs.map +1 -1
  29. package/dist/mcp.d.cts.map +1 -1
  30. package/dist/mcp.d.ts.map +1 -1
  31. package/dist/mcp.js +289 -130
  32. package/dist/mcp.js.map +1 -1
  33. package/dist/{microsoft-DgbVlHdT.js → microsoft-dsC1fQQG.js} +2 -38
  34. package/dist/microsoft-dsC1fQQG.js.map +1 -0
  35. package/dist/{server-uqXUhF4H.js → server-BbInMUgp.js} +172 -130
  36. package/dist/server-BbInMUgp.js.map +1 -0
  37. package/dist/snapshots-B6aOhoXs.js +2 -0
  38. package/dist/snapshots-CQSOaIMs.js +161 -0
  39. package/dist/snapshots-CQSOaIMs.js.map +1 -0
  40. package/dist/{token-resolver-BRLOmRvF.js → token-resolver-D98qPOOf.js} +3 -2
  41. package/dist/{token-resolver-BRLOmRvF.js.map → token-resolver-D98qPOOf.js.map} +1 -1
  42. package/dist/token-store-B0h0USqe.js +43 -0
  43. package/dist/token-store-B0h0USqe.js.map +1 -0
  44. package/dist/token-store-CEmz8d-0.js +2 -0
  45. package/package.json +2 -2
  46. package/dist/index-B5_QnkG8.d.cts.map +0 -1
  47. package/dist/knowledge-base-Bx2PKQR2.js.map +0 -1
  48. package/dist/microsoft-DgbVlHdT.js.map +0 -1
  49. package/dist/server-uqXUhF4H.js.map +0 -1
package/dist/cli.js CHANGED
@@ -5,7 +5,7 @@ import { i as writeJsonFile } from "./json-store-WWsFzXub.js";
5
5
  import { a as warning, i as success, n as error, r as info, t as bold } from "./colors-BG07TZQz.js";
6
6
  import { n as getSession } from "./session-store-CEa39Dxs.js";
7
7
  import { i as sessionCommand, r as readAllSessions } from "./session-BgGDyP2C.js";
8
- import { a as searchKbSimple, i as listKbArticles, n as getKbArticle, o as writeKbArticle, s as CAPABILITIES_TEXT, t as deleteKbArticle } from "./knowledge-base-Bx2PKQR2.js";
8
+ import { a as searchKbSimple, i as listKbArticles, n as getKbArticle, o as writeKbArticle, s as CAPABILITIES_TEXT, t as deleteKbArticle } from "./knowledge-base-Cc0niBFf.js";
9
9
  import { a as restoreCommand, t as backupCommand } from "./backup-CTlIxUdO.js";
10
10
  import { n as readSyncState } from "./sync-state-DMZgzpez.js";
11
11
  import { n as readUnmatched } from "./unmatched-transcripts-DC-VQ9YS.js";
@@ -23,6 +23,7 @@ import { n as listQuotes, r as readQuote, t as generateQuote } from "./quote-gen
23
23
  import { i as upsertTicket, n as nextTicketId, r as readTickets, t as listAllTickets } from "./ticket-writer-a9on36Wb.js";
24
24
  import { i as loadSlaRules, t as calcSlaDue } from "./sla-engine-O-A1ntu_.js";
25
25
  import { a as listSurveys, d as writeSurvey, i as getSurvey, l as savePendingSurvey, n as calcNpsScore, o as loadSurveyResponses, r as generateSurveyToken } from "./survey-engine-DngXBv47.js";
26
+ import { i as resolveAccountConfig, n as imapConfigFromEnv } from "./mailbox-config-Dn2xTn9N.js";
26
27
  import { Command } from "commander";
27
28
  import path from "path";
28
29
  import fs from "fs";
@@ -241,14 +242,14 @@ mcpCommand.command("start").description("Start MCP server (stdio by default)").o
241
242
  if (opts.http) {
242
243
  const port = parseInt(opts.port, 10);
243
244
  console.error(info(`Starting MCP server in HTTP mode on port ${port}...`));
244
- const { startHttp } = await import("./server-uqXUhF4H.js");
245
+ const { startHttp } = await import("./server-BbInMUgp.js");
245
246
  await startHttp(port);
246
247
  } else {
247
- const { startStdio } = await import("./server-uqXUhF4H.js");
248
+ const { startStdio } = await import("./server-BbInMUgp.js");
248
249
  await startStdio();
249
250
  }
250
251
  });
251
- const TOOL_COUNT = 58;
252
+ const TOOL_COUNT = 59;
252
253
  /** Claude Code: CLAUDE.md in CRM dataDir */
253
254
  function buildClaudeMd(dataDir) {
254
255
  return `# DatasynxOpenCRM v2 — Agent Instructions (${TOOL_COUNT} MCP Tools)
@@ -376,6 +377,7 @@ It combines graph, health, revenue simulation, playbook, and org intelligence in
376
377
  - \`get_audit_log({ slug?, actor?, limit? })\` — read append-only audit log of all write operations
377
378
  - \`get_logs({ level?, component?, since?, contains?, limit?, summary? })\` — query/aggregate the structured application log
378
379
  - \`get_diagnostics({ fix? })\` — self-diagnostic health check (data integrity, temp files, log errors, backups)
380
+ - \`get_pipeline_changes({ since?, days? })\` — pipeline time-travel: what changed (won/lost/moved/value) since a date
379
381
 
380
382
  ### Custom Objects (Platform / metadata)
381
383
  - \`define_custom_object({ name, label?, fields })\` — define a runtime entity type with typed fields (no migration), admin
@@ -637,7 +639,7 @@ create_ticket · update_ticket · list_tickets · close_ticket ·
637
639
  send_nps_survey · get_survey_results ·
638
640
  search_knowledge_base · create_kb_article ·
639
641
  backup_now · list_backups ·
640
- trigger_sync · get_audit_log · get_logs · get_diagnostics ·
642
+ trigger_sync · get_audit_log · get_logs · get_diagnostics · get_pipeline_changes ·
641
643
  define_custom_object · create_record · list_records · list_custom_objects
642
644
 
643
645
  ## Data: ${dataDir}`.trim();
@@ -2902,14 +2904,14 @@ function buildQuery(opts) {
2902
2904
  limit: opts.limit ?? 50
2903
2905
  };
2904
2906
  }
2905
- function dataDir$18() {
2907
+ function dataDir$19() {
2906
2908
  return process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2907
2909
  }
2908
2910
  const logsCommand = new Command("logs").description("View and analyze the structured application log").option("--level <level>", "Minimum level: debug | info | warn | error").option("--component <name>", "Filter by component (e.g. gmail-sync, lancedb)").option("--since <iso>", "Only entries at or after this ISO timestamp").option("--contains <text>", "Filter by message substring").option("--limit <n>", "Max entries to show (default: 50)", parseInt).option("--summary", "Show aggregated counts (by level + component) instead of entries").action(async (opts) => {
2909
2911
  const query = buildQuery(opts);
2910
2912
  if (opts.summary) {
2911
2913
  const { summarizeLogs } = await import("./logger-vKQS34w9.js");
2912
- const s = summarizeLogs(dataDir$18(), query);
2914
+ const s = summarizeLogs(dataDir$19(), query);
2913
2915
  console.log(bold(`Logs — ${s.total} entr${s.total === 1 ? "y" : "ies"}`));
2914
2916
  if (s.firstTs) console.log(info(` ${s.firstTs} → ${s.lastTs}`));
2915
2917
  console.log(" By level:");
@@ -2926,7 +2928,7 @@ const logsCommand = new Command("logs").description("View and analyze the struct
2926
2928
  return;
2927
2929
  }
2928
2930
  const { queryLogs } = await import("./logger-vKQS34w9.js");
2929
- const entries = queryLogs(dataDir$18(), query);
2931
+ const entries = queryLogs(dataDir$19(), query);
2930
2932
  if (entries.length === 0) {
2931
2933
  console.log(success("No matching log entries."));
2932
2934
  return;
@@ -2938,7 +2940,7 @@ const logsCommand = new Command("logs").description("View and analyze the struct
2938
2940
  });
2939
2941
  //#endregion
2940
2942
  //#region src/commands/doctor.ts
2941
- function dataDir$17() {
2943
+ function dataDir$18() {
2942
2944
  return process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2943
2945
  }
2944
2946
  function icon(status) {
@@ -2949,10 +2951,10 @@ function icon(status) {
2949
2951
  const doctorCommand = new Command("doctor").description("Run self-diagnostics: data integrity, temp files, log errors, backup freshness").option("--fix", "Clean up safely-fixable issues (orphaned temp files)").action(async (opts) => {
2950
2952
  const { runDiagnostics, cleanupTempFiles } = await import("./doctor-CYDaNmFn.js");
2951
2953
  if (opts.fix) {
2952
- const removed = cleanupTempFiles(dataDir$17());
2954
+ const removed = cleanupTempFiles(dataDir$18());
2953
2955
  console.log(removed.length > 0 ? success(`Removed ${removed.length} orphaned temp file(s).`) : warning("Nothing to fix."));
2954
2956
  }
2955
- const report = await runDiagnostics(dataDir$17());
2957
+ const report = await runDiagnostics(dataDir$18());
2956
2958
  console.log(bold("dxcrm doctor"));
2957
2959
  for (const c of report.checks) console.log(` ${icon(c.status)} ${c.name.padEnd(16)} ${c.detail}`);
2958
2960
  if (report.ok) {
@@ -2964,6 +2966,59 @@ const doctorCommand = new Command("doctor").description("Run self-diagnostics: d
2964
2966
  }
2965
2967
  });
2966
2968
  //#endregion
2969
+ //#region src/commands/pipeline.ts
2970
+ function dataDir$17() {
2971
+ return process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2972
+ }
2973
+ function daysAgoIso(days) {
2974
+ return (/* @__PURE__ */ new Date(Date.now() - days * 864e5)).toISOString().slice(0, 10);
2975
+ }
2976
+ const pipelineCommand = new Command("pipeline").description("Pipeline time-travel: daily snapshots and 'what changed?' diffs");
2977
+ pipelineCommand.command("snapshot").description("Capture a snapshot of the current pipeline across all customers").action(async () => {
2978
+ const { takeSnapshot } = await import("./snapshots-B6aOhoXs.js");
2979
+ const snap = takeSnapshot(dataDir$17());
2980
+ console.log(success(`Snapshot ${snap.id} taken — ${snap.deals.length} deal(s).`));
2981
+ });
2982
+ pipelineCommand.command("list").description("List available pipeline snapshots").action(async () => {
2983
+ const { listSnapshots } = await import("./snapshots-B6aOhoXs.js");
2984
+ const snaps = listSnapshots(dataDir$17());
2985
+ if (snaps.length === 0) {
2986
+ console.log(info("No snapshots yet. Run 'dxcrm pipeline snapshot' (or let the daemon take daily ones)."));
2987
+ return;
2988
+ }
2989
+ for (const s of snaps) console.log(`${s.id} ${String(s.dealCount).padStart(4)} deals open €${s.openValue.toLocaleString()}`);
2990
+ });
2991
+ pipelineCommand.command("changes").description("Show what changed in the pipeline since a date (default: 7 days ago)").option("--since <YYYY-MM-DD>", "Baseline date (default: 7 days ago)").action(async (opts) => {
2992
+ const since = opts.since ?? daysAgoIso(7);
2993
+ const { diffAgainstNow } = await import("./snapshots-B6aOhoXs.js");
2994
+ const diff = diffAgainstNow(dataDir$17(), since);
2995
+ if (!diff) {
2996
+ console.log(warning(`No snapshot at or before ${since}. Take snapshots first (or wait for the daemon).`));
2997
+ return;
2998
+ }
2999
+ console.log(bold(`Pipeline changes since ${diff.fromId}`));
3000
+ const line = (label, n) => ` ${label.padEnd(16)} ${n}`;
3001
+ console.log(success(line("Won", diff.won.length)));
3002
+ console.log(error(line("Lost", diff.lost.length)));
3003
+ console.log(line("New deals", diff.added.length));
3004
+ console.log(line("Removed", diff.removed.length));
3005
+ console.log(line("Stage moves", diff.advanced.length));
3006
+ console.log(line("Value changes", diff.valueChanged.length));
3007
+ const delta = diff.openValueDelta;
3008
+ const deltaStr = `${delta >= 0 ? "+" : ""}€${delta.toLocaleString()}`;
3009
+ console.log(` ${"Open value".padEnd(16)} €${diff.openValueAfter.toLocaleString()} (${delta >= 0 ? success(deltaStr) : error(deltaStr)})`);
3010
+ if (diff.won.length) console.log(success(`\nWon: ${diff.won.map((d) => d.name).join(", ")}`));
3011
+ if (diff.lost.length) console.log(error(`Lost: ${diff.lost.map((d) => d.name).join(", ")}`));
3012
+ if (diff.advanced.length) {
3013
+ console.log(info("\nStage moves:"));
3014
+ for (const m of diff.advanced) console.log(` ${m.slug}/${m.name}: ${m.from} → ${m.to}`);
3015
+ }
3016
+ if (diff.added.length) {
3017
+ console.log(info("\nNew deals:"));
3018
+ for (const d of diff.added) console.log(` ${d.slug}/${d.name}`);
3019
+ }
3020
+ });
3021
+ //#endregion
2967
3022
  //#region src/commands/rbac.ts
2968
3023
  const ROLES = [
2969
3024
  "admin",
@@ -4428,68 +4483,6 @@ complianceCommand.command("status", { isDefault: true }).description("Show the a
4428
4483
  });
4429
4484
  //#endregion
4430
4485
  //#region src/commands/mailbox.ts
4431
- /** Default IMAP endpoints for OAuth providers. */
4432
- const PROVIDER_IMAP_HOST = {
4433
- gmail: {
4434
- host: "imap.gmail.com",
4435
- port: 993
4436
- },
4437
- microsoft: {
4438
- host: "outlook.office365.com",
4439
- port: 993
4440
- }
4441
- };
4442
- /** Read IMAP mailbox connection settings from the environment. */
4443
- function imapConfigFromEnv(env = process.env) {
4444
- const host = env["DXCRM_IMAP_HOST"];
4445
- const user = env["DXCRM_IMAP_USER"];
4446
- const pass = env["DXCRM_IMAP_PASS"];
4447
- const accessToken = env["DXCRM_IMAP_TOKEN"];
4448
- if (!host || !user || !pass && !accessToken) return null;
4449
- return {
4450
- host,
4451
- port: env["DXCRM_IMAP_PORT"] ? Number(env["DXCRM_IMAP_PORT"]) : 993,
4452
- secure: env["DXCRM_IMAP_SECURE"] !== "false",
4453
- mailbox: env["DXCRM_IMAP_MAILBOX"] ?? "INBOX",
4454
- auth: accessToken ? {
4455
- user,
4456
- accessToken
4457
- } : {
4458
- user,
4459
- pass
4460
- }
4461
- };
4462
- }
4463
- /** Parse a "provider:user" account string. */
4464
- function parseAccount(account) {
4465
- const idx = account.indexOf(":");
4466
- if (idx < 0) return null;
4467
- const provider = account.slice(0, idx);
4468
- const user = account.slice(idx + 1);
4469
- if (provider !== "gmail" && provider !== "microsoft" || !user) return null;
4470
- return {
4471
- provider,
4472
- user
4473
- };
4474
- }
4475
- /** Build an IMAP config for a stored OAuth account, refreshing the token if needed. */
4476
- async function resolveAccountConfig(dataDir, account, env = process.env, mailbox) {
4477
- const parsed = parseAccount(account);
4478
- if (!parsed) throw new Error(`Invalid --account '${account}'. Use 'gmail:you@gmail.com' or 'microsoft:you@org.com'.`);
4479
- const { getFreshAccessToken } = await import("./token-resolver-BRLOmRvF.js");
4480
- const accessToken = await getFreshAccessToken(dataDir, parsed.provider, parsed.user, { env });
4481
- const { host, port } = PROVIDER_IMAP_HOST[parsed.provider];
4482
- return {
4483
- host,
4484
- port,
4485
- secure: true,
4486
- mailbox: mailbox ?? env["DXCRM_IMAP_MAILBOX"] ?? "INBOX",
4487
- auth: {
4488
- user: parsed.user,
4489
- accessToken
4490
- }
4491
- };
4492
- }
4493
4486
  /**
4494
4487
  * Sync an IMAP mailbox (any provider). With a slug, all mail goes to that one
4495
4488
  * customer; without, mail is auto-routed to customers by sender/recipient
@@ -4511,7 +4504,7 @@ async function runMailboxSync(opts) {
4511
4504
  console.error(error(msg));
4512
4505
  return { error: msg };
4513
4506
  }
4514
- const { syncImapMailbox } = await import("./imap-o6PRuBvm.js");
4507
+ const { syncImapMailbox } = await import("./imap-DzeqMdZ3.js");
4515
4508
  const result = await syncImapMailbox({
4516
4509
  dataDir: opts.dataDir,
4517
4510
  config,
@@ -4543,7 +4536,7 @@ async function runLogin(provider, user) {
4543
4536
  return;
4544
4537
  }
4545
4538
  const account = user ?? (await ask("Gmail address: ")).trim();
4546
- const { runGmailLogin } = await import("./login-CYgla6-A.js");
4539
+ const { runGmailLogin } = await import("./login-yt9OOQQk.js");
4547
4540
  await runGmailLogin({
4548
4541
  dataDir,
4549
4542
  clientId,
@@ -4563,7 +4556,7 @@ async function runLogin(provider, user) {
4563
4556
  }
4564
4557
  const tenant = process.env["DXCRM_MS_TENANT"] ?? "common";
4565
4558
  const account = user ?? (await ask("Outlook/Microsoft address: ")).trim();
4566
- const { runMicrosoftLogin } = await import("./login-CYgla6-A.js");
4559
+ const { runMicrosoftLogin } = await import("./login-yt9OOQQk.js");
4567
4560
  await runMicrosoftLogin({
4568
4561
  dataDir,
4569
4562
  clientId,
@@ -4612,6 +4605,7 @@ const ALL_COMMANDS = [
4612
4605
  auditCommand,
4613
4606
  logsCommand,
4614
4607
  doctorCommand,
4608
+ pipelineCommand,
4615
4609
  rbacCommand,
4616
4610
  gdprCommand,
4617
4611
  securityReportCommand,