@datasynx/agentic-crm 1.8.0 → 1.9.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 (46) hide show
  1. package/dist/cli.js +71 -8
  2. package/dist/cli.js.map +1 -1
  3. package/dist/daemon/worker.js +3 -3
  4. package/dist/funnel-B2mwpZE1.js +89 -0
  5. package/dist/funnel-B2mwpZE1.js.map +1 -0
  6. package/dist/funnel-CJ7fy7hG.js +2 -0
  7. package/dist/{index-Ewy4f1XW.d.cts → index-BAutNcAT.d.cts} +17 -17
  8. package/dist/index-BAutNcAT.d.cts.map +1 -0
  9. package/dist/{index-DoYT-azq.d.ts → index-BBAlKZg6.d.ts} +8 -8
  10. package/dist/index-BBAlKZg6.d.ts.map +1 -0
  11. package/dist/index.d.cts +17 -17
  12. package/dist/index.d.cts.map +1 -1
  13. package/dist/index.d.ts +8 -8
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/{knowledge-base-Byo0zwM5.js → knowledge-base-yo-BLUcB.js} +2 -1
  16. package/dist/knowledge-base-yo-BLUcB.js.map +1 -0
  17. package/dist/{login-yt9OOQQk.js → login-dc_Hqosw.js} +2 -2
  18. package/dist/{login-yt9OOQQk.js.map → login-dc_Hqosw.js.map} +1 -1
  19. package/dist/mailbox-config-BU3vib2T.js +2 -0
  20. package/dist/{mailbox-config-Dn2xTn9N.js → mailbox-config-trjLPHPG.js} +2 -2
  21. package/dist/{mailbox-config-Dn2xTn9N.js.map → mailbox-config-trjLPHPG.js.map} +1 -1
  22. package/dist/{mailbox-poll-B8dvFAXT.js → mailbox-poll-Ban7C3X0.js} +3 -3
  23. package/dist/{mailbox-poll-B8dvFAXT.js.map → mailbox-poll-Ban7C3X0.js.map} +1 -1
  24. package/dist/mcp-CdTJWTJf.d.cts.map +1 -1
  25. package/dist/mcp-CdTJWTJf.d.ts.map +1 -1
  26. package/dist/mcp.cjs +246 -134
  27. package/dist/mcp.cjs.map +1 -1
  28. package/dist/mcp.d.cts.map +1 -1
  29. package/dist/mcp.d.ts.map +1 -1
  30. package/dist/mcp.js +246 -134
  31. package/dist/mcp.js.map +1 -1
  32. package/dist/{server-C0XkJQBo.js → server-DAcwmRPE.js} +162 -135
  33. package/dist/server-DAcwmRPE.js.map +1 -0
  34. package/dist/{token-resolver-D98qPOOf.js → token-resolver-CL8-CSgZ.js} +2 -2
  35. package/dist/{token-resolver-D98qPOOf.js.map → token-resolver-CL8-CSgZ.js.map} +1 -1
  36. package/dist/{token-store-B0h0USqe.js → token-store-BPDwePNT.js} +13 -2
  37. package/dist/token-store-BPDwePNT.js.map +1 -0
  38. package/dist/token-store-D3HCeXmE.js +2 -0
  39. package/package.json +1 -1
  40. package/dist/index-DoYT-azq.d.ts.map +0 -1
  41. package/dist/index-Ewy4f1XW.d.cts.map +0 -1
  42. package/dist/knowledge-base-Byo0zwM5.js.map +0 -1
  43. package/dist/mailbox-config-Bu-J1O4I.js +0 -2
  44. package/dist/server-C0XkJQBo.js.map +0 -1
  45. package/dist/token-store-B0h0USqe.js.map +0 -1
  46. package/dist/token-store-CEmz8d-0.js +0 -2
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-Byo0zwM5.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-yo-BLUcB.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,7 +23,8 @@ 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
+ import { i as resolveAccountConfig, n as imapConfigFromEnv, r as parseAccount } from "./mailbox-config-trjLPHPG.js";
27
+ import { i as removeMailboxToken, n as listMailboxTokens, t as isTokenExpired } from "./token-store-BPDwePNT.js";
27
28
  import { Command } from "commander";
28
29
  import path from "path";
29
30
  import fs from "fs";
@@ -242,14 +243,14 @@ mcpCommand.command("start").description("Start MCP server (stdio by default)").o
242
243
  if (opts.http) {
243
244
  const port = parseInt(opts.port, 10);
244
245
  console.error(info(`Starting MCP server in HTTP mode on port ${port}...`));
245
- const { startHttp } = await import("./server-C0XkJQBo.js");
246
+ const { startHttp } = await import("./server-DAcwmRPE.js");
246
247
  await startHttp(port);
247
248
  } else {
248
- const { startStdio } = await import("./server-C0XkJQBo.js");
249
+ const { startStdio } = await import("./server-DAcwmRPE.js");
249
250
  await startStdio();
250
251
  }
251
252
  });
252
- const TOOL_COUNT = 60;
253
+ const TOOL_COUNT = 61;
253
254
  /** Claude Code: CLAUDE.md in CRM dataDir */
254
255
  function buildClaudeMd(dataDir) {
255
256
  return `# DatasynxOpenCRM v2 — Agent Instructions (${TOOL_COUNT} MCP Tools)
@@ -379,6 +380,7 @@ It combines graph, health, revenue simulation, playbook, and org intelligence in
379
380
  - \`get_diagnostics({ fix? })\` — self-diagnostic health check (data integrity, temp files, log errors, backups)
380
381
  - \`get_pipeline_changes({ since?, days? })\` — pipeline time-travel: what changed (won/lost/moved/value) since a date
381
382
  - \`get_pipeline_velocity({ stalledDays? })\` — stage dwell times, sales cycle, and stalled deals from snapshot history
383
+ - \`get_pipeline_funnel()\` — conversion funnel & win rate: where deals leak out of the pipeline
382
384
 
383
385
  ### Custom Objects (Platform / metadata)
384
386
  - \`define_custom_object({ name, label?, fields })\` — define a runtime entity type with typed fields (no migration), admin
@@ -641,7 +643,7 @@ send_nps_survey · get_survey_results ·
641
643
  search_knowledge_base · create_kb_article ·
642
644
  backup_now · list_backups ·
643
645
  trigger_sync · get_audit_log · get_logs · get_diagnostics ·
644
- get_pipeline_changes · get_pipeline_velocity ·
646
+ get_pipeline_changes · get_pipeline_velocity · get_pipeline_funnel ·
645
647
  define_custom_object · create_record · list_records · list_custom_objects
646
648
 
647
649
  ## Data: ${dataDir}`.trim();
@@ -1846,6 +1848,12 @@ async function runStatus(opts, dataDir) {
1846
1848
  const daemonLine = daemon.running ? success(`running (PID ${daemon.pid})`) : error("not running");
1847
1849
  console.log(` Daemon: ${daemonLine}`);
1848
1850
  console.log(` Customers: ${slugs.length} active`);
1851
+ const { listMailboxTokens, isTokenExpired } = await import("./token-store-D3HCeXmE.js");
1852
+ const mailboxTokens = listMailboxTokens(dir);
1853
+ if (mailboxTokens.length > 0) {
1854
+ const valid = mailboxTokens.filter((t) => !isTokenExpired(t)).length;
1855
+ console.log(` Mailboxes: ${mailboxTokens.length} linked (${valid} valid)`);
1856
+ }
1849
1857
  const session = getSession() ?? readAllSessions(dir)[0] ?? null;
1850
1858
  if (session) {
1851
1859
  const ownerPart = session.owner ? ` [${session.owner}]` : "";
@@ -3048,6 +3056,26 @@ pipelineCommand.command("velocity").description("Stage dwell times, sales cycle,
3048
3056
  for (const d of report.stalledDeals) console.log(` ${d.slug}/${d.name}: ${d.stage}, ${d.daysInStage}d €${d.value.toLocaleString()}`);
3049
3057
  } else console.log(success(`\nNo stalled deals (threshold ${report.stalledThresholdDays}d).`));
3050
3058
  });
3059
+ pipelineCommand.command("funnel").description("Conversion funnel & win rate: where deals leak out of the pipeline").action(async () => {
3060
+ const { analyzeFunnel } = await import("./funnel-CJ7fy7hG.js");
3061
+ const report = analyzeFunnel(dataDir$17());
3062
+ if (report.snapshotCount === 0) {
3063
+ console.log(info("No snapshots yet. Run 'dxcrm pipeline snapshot' (or let the daemon take daily ones)."));
3064
+ return;
3065
+ }
3066
+ console.log(bold(`Pipeline funnel (${report.snapshotCount} snapshots, ${report.fromId} → ${report.toId})`));
3067
+ for (const s of report.stages) {
3068
+ const conv = s.conversionPctToNext === null ? "" : ` → ${s.conversionPctToNext}% convert`;
3069
+ console.log(` ${s.stage.padEnd(14)} ${String(s.reached).padStart(4)} reached${conv}`);
3070
+ }
3071
+ const wr = report.winRatePct;
3072
+ const wrStr = wr === null ? "n/a (nothing closed yet)" : `${wr}%`;
3073
+ console.log(`\n ${"Win rate".padEnd(14)} ${wrStr} (${report.wonCount} won / ${report.lostCount} lost)`);
3074
+ if (report.biggestLeak) {
3075
+ const l = report.biggestLeak;
3076
+ console.log(error(`\nBiggest leak: ${l.from} → ${l.to} (only ${l.conversionPct}% convert)`));
3077
+ }
3078
+ });
3051
3079
  //#endregion
3052
3080
  //#region src/commands/rbac.ts
3053
3081
  const ROLES = [
@@ -4513,6 +4541,22 @@ complianceCommand.command("status", { isDefault: true }).description("Show the a
4513
4541
  });
4514
4542
  //#endregion
4515
4543
  //#region src/commands/mailbox.ts
4544
+ /** Summarize every stored mailbox OAuth account. */
4545
+ function runMailboxList(dataDir) {
4546
+ return listMailboxTokens(dataDir).map((t) => ({
4547
+ account: `${t.provider}:${t.user}`,
4548
+ provider: t.provider,
4549
+ user: t.user,
4550
+ status: isTokenExpired(t) ? "expired" : "valid",
4551
+ expiresAt: new Date(t.expiresAt).toISOString()
4552
+ }));
4553
+ }
4554
+ /** Remove a stored mailbox account by "provider:user". */
4555
+ function runMailboxLogout(dataDir, account) {
4556
+ const parsed = parseAccount(account);
4557
+ if (!parsed) return { error: `Invalid account '${account}'. Use 'gmail:you@gmail.com' or 'microsoft:you@org.com'.` };
4558
+ return { removed: removeMailboxToken(dataDir, parsed.provider, parsed.user) };
4559
+ }
4516
4560
  /**
4517
4561
  * Sync an IMAP mailbox (any provider). With a slug, all mail goes to that one
4518
4562
  * customer; without, mail is auto-routed to customers by sender/recipient
@@ -4566,7 +4610,7 @@ async function runLogin(provider, user) {
4566
4610
  return;
4567
4611
  }
4568
4612
  const account = user ?? (await ask("Gmail address: ")).trim();
4569
- const { runGmailLogin } = await import("./login-yt9OOQQk.js");
4613
+ const { runGmailLogin } = await import("./login-dc_Hqosw.js");
4570
4614
  await runGmailLogin({
4571
4615
  dataDir,
4572
4616
  clientId,
@@ -4586,7 +4630,7 @@ async function runLogin(provider, user) {
4586
4630
  }
4587
4631
  const tenant = process.env["DXCRM_MS_TENANT"] ?? "common";
4588
4632
  const account = user ?? (await ask("Outlook/Microsoft address: ")).trim();
4589
- const { runMicrosoftLogin } = await import("./login-yt9OOQQk.js");
4633
+ const { runMicrosoftLogin } = await import("./login-dc_Hqosw.js");
4590
4634
  await runMicrosoftLogin({
4591
4635
  dataDir,
4592
4636
  clientId,
@@ -4612,6 +4656,25 @@ mailboxCommand.command("sync").description("Sync an IMAP mailbox; auto-routes to
4612
4656
  includeAttachments: options.attachments !== false
4613
4657
  });
4614
4658
  });
4659
+ mailboxCommand.command("list").description("List logged-in mailbox accounts and their token status").action(() => {
4660
+ const accounts = runMailboxList(process.env["DXCRM_DATA_DIR"] ?? process.cwd());
4661
+ if (accounts.length === 0) {
4662
+ console.log(info("No mailbox accounts. Run 'dxcrm mailbox login gmail|microsoft'."));
4663
+ return;
4664
+ }
4665
+ for (const a of accounts) {
4666
+ const tag = a.status === "valid" ? success("valid") : error("expired");
4667
+ console.log(`${bold(a.account)} — token ${tag} (expires ${a.expiresAt})`);
4668
+ }
4669
+ });
4670
+ mailboxCommand.command("logout").description("Remove a stored mailbox account").argument("<account>", "provider:user (e.g. gmail:you@gmail.com)").action((account) => {
4671
+ const result = runMailboxLogout(process.env["DXCRM_DATA_DIR"] ?? process.cwd(), account);
4672
+ if ("error" in result) {
4673
+ console.error(error(result.error));
4674
+ return;
4675
+ }
4676
+ console.log(result.removed ? success(`✓ Removed ${bold(account)}.`) : info(`No stored account '${account}'.`));
4677
+ });
4615
4678
  //#endregion
4616
4679
  //#region src/commands/registry.ts
4617
4680
  /** Every top-level `dxcrm` command, in display order. */