@datasynx/agentic-crm 1.6.0 → 1.8.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 +39 -70
  2. package/dist/cli.js.map +1 -1
  3. package/dist/daemon/worker.js +24 -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-BBAlKZg6.d.ts → index-DoYT-azq.d.ts} +8 -8
  9. package/dist/index-DoYT-azq.d.ts.map +1 -0
  10. package/dist/{index-DNHsURo5.d.cts → index-Ewy4f1XW.d.cts} +12 -12
  11. package/dist/{index-DNHsURo5.d.cts.map → index-Ewy4f1XW.d.cts.map} +1 -1
  12. package/dist/index.d.cts +12 -12
  13. package/dist/index.d.cts.map +1 -1
  14. package/dist/index.d.ts +8 -8
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/{knowledge-base-Cc0niBFf.js → knowledge-base-Byo0zwM5.js} +2 -1
  17. package/dist/knowledge-base-Byo0zwM5.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 +303 -137
  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 +303 -137
  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-BbInMUgp.js → server-C0XkJQBo.js} +167 -132
  36. package/dist/server-C0XkJQBo.js.map +1 -0
  37. package/dist/{token-resolver-BRLOmRvF.js → token-resolver-D98qPOOf.js} +3 -2
  38. package/dist/{token-resolver-BRLOmRvF.js.map → token-resolver-D98qPOOf.js.map} +1 -1
  39. package/dist/token-store-B0h0USqe.js +43 -0
  40. package/dist/token-store-B0h0USqe.js.map +1 -0
  41. package/dist/token-store-CEmz8d-0.js +2 -0
  42. package/dist/velocity-BtX1l5Gh.js +2 -0
  43. package/dist/velocity-C2l4cW0K.js +123 -0
  44. package/dist/velocity-C2l4cW0K.js.map +1 -0
  45. package/package.json +1 -1
  46. package/dist/index-BBAlKZg6.d.ts.map +0 -1
  47. package/dist/knowledge-base-Cc0niBFf.js.map +0 -1
  48. package/dist/microsoft-DgbVlHdT.js.map +0 -1
  49. package/dist/server-BbInMUgp.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-Cc0niBFf.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";
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-BbInMUgp.js");
245
+ const { startHttp } = await import("./server-C0XkJQBo.js");
245
246
  await startHttp(port);
246
247
  } else {
247
- const { startStdio } = await import("./server-BbInMUgp.js");
248
+ const { startStdio } = await import("./server-C0XkJQBo.js");
248
249
  await startStdio();
249
250
  }
250
251
  });
251
- const TOOL_COUNT = 59;
252
+ const TOOL_COUNT = 60;
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)
@@ -377,6 +378,7 @@ It combines graph, health, revenue simulation, playbook, and org intelligence in
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)
379
380
  - \`get_pipeline_changes({ since?, days? })\` — pipeline time-travel: what changed (won/lost/moved/value) since a date
381
+ - \`get_pipeline_velocity({ stalledDays? })\` — stage dwell times, sales cycle, and stalled deals from snapshot history
380
382
 
381
383
  ### Custom Objects (Platform / metadata)
382
384
  - \`define_custom_object({ name, label?, fields })\` — define a runtime entity type with typed fields (no migration), admin
@@ -638,7 +640,8 @@ create_ticket · update_ticket · list_tickets · close_ticket ·
638
640
  send_nps_survey · get_survey_results ·
639
641
  search_knowledge_base · create_kb_article ·
640
642
  backup_now · list_backups ·
641
- trigger_sync · get_audit_log · get_logs · get_diagnostics · get_pipeline_changes ·
643
+ trigger_sync · get_audit_log · get_logs · get_diagnostics ·
644
+ get_pipeline_changes · get_pipeline_velocity ·
642
645
  define_custom_object · create_record · list_records · list_custom_objects
643
646
 
644
647
  ## Data: ${dataDir}`.trim();
@@ -3017,6 +3020,34 @@ pipelineCommand.command("changes").description("Show what changed in the pipelin
3017
3020
  for (const d of diff.added) console.log(` ${d.slug}/${d.name}`);
3018
3021
  }
3019
3022
  });
3023
+ pipelineCommand.command("velocity").description("Stage dwell times, sales cycle, and stalled deals from snapshot history").option("--stalled-days <n>", "Days in one stage before a deal counts as stalled (default 14)").action(async (opts) => {
3024
+ const { analyzeVelocity } = await import("./velocity-BtX1l5Gh.js");
3025
+ const analyzeOpts = {};
3026
+ if (opts.stalledDays !== void 0) {
3027
+ const n = parseInt(opts.stalledDays, 10);
3028
+ if (Number.isFinite(n) && n > 0) analyzeOpts.stalledDays = n;
3029
+ }
3030
+ const report = analyzeVelocity(dataDir$17(), analyzeOpts);
3031
+ if (report.snapshotCount === 0) {
3032
+ console.log(info("No snapshots yet. Run 'dxcrm pipeline snapshot' (or let the daemon take daily ones)."));
3033
+ return;
3034
+ }
3035
+ console.log(bold(`Pipeline velocity (${report.snapshotCount} snapshots, ${report.fromId} → ${report.toId})`));
3036
+ if (report.stageDurations.length) {
3037
+ console.log(info("\nAvg time in stage:"));
3038
+ for (const s of report.stageDurations) {
3039
+ const samples = `${s.samples} sample${s.samples === 1 ? "" : "s"}`;
3040
+ console.log(` ${s.stage.padEnd(14)} ${s.avgDays}d (${samples})`);
3041
+ }
3042
+ }
3043
+ const cycle = report.avgSalesCycleDays;
3044
+ const cycleStr = cycle === null ? "n/a (no won deals yet)" : `${cycle}d avg`;
3045
+ console.log(`\n ${"Sales cycle".padEnd(14)} ${cycleStr} over ${report.wonCount} won`);
3046
+ if (report.stalledDeals.length) {
3047
+ console.log(error(`\nStalled deals (> ${report.stalledThresholdDays}d in stage):`));
3048
+ for (const d of report.stalledDeals) console.log(` ${d.slug}/${d.name}: ${d.stage}, ${d.daysInStage}d €${d.value.toLocaleString()}`);
3049
+ } else console.log(success(`\nNo stalled deals (threshold ${report.stalledThresholdDays}d).`));
3050
+ });
3020
3051
  //#endregion
3021
3052
  //#region src/commands/rbac.ts
3022
3053
  const ROLES = [
@@ -4482,68 +4513,6 @@ complianceCommand.command("status", { isDefault: true }).description("Show the a
4482
4513
  });
4483
4514
  //#endregion
4484
4515
  //#region src/commands/mailbox.ts
4485
- /** Default IMAP endpoints for OAuth providers. */
4486
- const PROVIDER_IMAP_HOST = {
4487
- gmail: {
4488
- host: "imap.gmail.com",
4489
- port: 993
4490
- },
4491
- microsoft: {
4492
- host: "outlook.office365.com",
4493
- port: 993
4494
- }
4495
- };
4496
- /** Read IMAP mailbox connection settings from the environment. */
4497
- function imapConfigFromEnv(env = process.env) {
4498
- const host = env["DXCRM_IMAP_HOST"];
4499
- const user = env["DXCRM_IMAP_USER"];
4500
- const pass = env["DXCRM_IMAP_PASS"];
4501
- const accessToken = env["DXCRM_IMAP_TOKEN"];
4502
- if (!host || !user || !pass && !accessToken) return null;
4503
- return {
4504
- host,
4505
- port: env["DXCRM_IMAP_PORT"] ? Number(env["DXCRM_IMAP_PORT"]) : 993,
4506
- secure: env["DXCRM_IMAP_SECURE"] !== "false",
4507
- mailbox: env["DXCRM_IMAP_MAILBOX"] ?? "INBOX",
4508
- auth: accessToken ? {
4509
- user,
4510
- accessToken
4511
- } : {
4512
- user,
4513
- pass
4514
- }
4515
- };
4516
- }
4517
- /** Parse a "provider:user" account string. */
4518
- function parseAccount(account) {
4519
- const idx = account.indexOf(":");
4520
- if (idx < 0) return null;
4521
- const provider = account.slice(0, idx);
4522
- const user = account.slice(idx + 1);
4523
- if (provider !== "gmail" && provider !== "microsoft" || !user) return null;
4524
- return {
4525
- provider,
4526
- user
4527
- };
4528
- }
4529
- /** Build an IMAP config for a stored OAuth account, refreshing the token if needed. */
4530
- async function resolveAccountConfig(dataDir, account, env = process.env, mailbox) {
4531
- const parsed = parseAccount(account);
4532
- if (!parsed) throw new Error(`Invalid --account '${account}'. Use 'gmail:you@gmail.com' or 'microsoft:you@org.com'.`);
4533
- const { getFreshAccessToken } = await import("./token-resolver-BRLOmRvF.js");
4534
- const accessToken = await getFreshAccessToken(dataDir, parsed.provider, parsed.user, { env });
4535
- const { host, port } = PROVIDER_IMAP_HOST[parsed.provider];
4536
- return {
4537
- host,
4538
- port,
4539
- secure: true,
4540
- mailbox: mailbox ?? env["DXCRM_IMAP_MAILBOX"] ?? "INBOX",
4541
- auth: {
4542
- user: parsed.user,
4543
- accessToken
4544
- }
4545
- };
4546
- }
4547
4516
  /**
4548
4517
  * Sync an IMAP mailbox (any provider). With a slug, all mail goes to that one
4549
4518
  * customer; without, mail is auto-routed to customers by sender/recipient
@@ -4565,7 +4534,7 @@ async function runMailboxSync(opts) {
4565
4534
  console.error(error(msg));
4566
4535
  return { error: msg };
4567
4536
  }
4568
- const { syncImapMailbox } = await import("./imap-o6PRuBvm.js");
4537
+ const { syncImapMailbox } = await import("./imap-DzeqMdZ3.js");
4569
4538
  const result = await syncImapMailbox({
4570
4539
  dataDir: opts.dataDir,
4571
4540
  config,
@@ -4597,7 +4566,7 @@ async function runLogin(provider, user) {
4597
4566
  return;
4598
4567
  }
4599
4568
  const account = user ?? (await ask("Gmail address: ")).trim();
4600
- const { runGmailLogin } = await import("./login-CYgla6-A.js");
4569
+ const { runGmailLogin } = await import("./login-yt9OOQQk.js");
4601
4570
  await runGmailLogin({
4602
4571
  dataDir,
4603
4572
  clientId,
@@ -4617,7 +4586,7 @@ async function runLogin(provider, user) {
4617
4586
  }
4618
4587
  const tenant = process.env["DXCRM_MS_TENANT"] ?? "common";
4619
4588
  const account = user ?? (await ask("Outlook/Microsoft address: ")).trim();
4620
- const { runMicrosoftLogin } = await import("./login-CYgla6-A.js");
4589
+ const { runMicrosoftLogin } = await import("./login-yt9OOQQk.js");
4621
4590
  await runMicrosoftLogin({
4622
4591
  dataDir,
4623
4592
  clientId,