@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/mcp.js CHANGED
@@ -444,6 +444,7 @@ Config: \`.agentic/rbac.json\` | Actor: \`DXCRM_ACTOR\` env var
444
444
  | get_audit_log | Read audit log — all write operations with actor, tool, customer | admin |
445
445
  | get_logs | Query/aggregate the structured application log (level, component, errors) | admin |
446
446
  | get_diagnostics | Self-diagnostic health check (data integrity, temp files, log errors, backups) | admin |
447
+ | get_pipeline_changes | Pipeline time-travel: what changed (won/lost/moved/value) since a date | any |
447
448
  | define_custom_object | Define a runtime custom object type with typed fields (no migration) | admin |
448
449
  | create_record | Create a record of a custom object (validated against its schema) | rep+ |
449
450
  | list_records | List records of a custom object | any |
@@ -1422,7 +1423,7 @@ async function buildContext(dataDir, slug) {
1422
1423
  }
1423
1424
  //#endregion
1424
1425
  //#region src/mcp/tools/get-customer-context.ts
1425
- const DATA_DIR$53 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1426
+ const DATA_DIR$54 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1426
1427
  function triggerOnQuerySync(dataDir, slug) {
1427
1428
  const auth = getGmailAuth();
1428
1429
  if (!auth) return;
@@ -1443,7 +1444,7 @@ function triggerOnQuerySync(dataDir, slug) {
1443
1444
  }).then(() => updateSlugSyncState(dataDir, slug, { lastGmailSync: (/* @__PURE__ */ new Date()).toISOString() })).catch(() => {})).catch(() => {});
1444
1445
  } catch {}
1445
1446
  }
1446
- async function handleGetCustomerContext(input, dataDir = DATA_DIR$53) {
1447
+ async function handleGetCustomerContext(input, dataDir = DATA_DIR$54) {
1447
1448
  const targetSlug = input.slug ?? getSession()?.customerSlug;
1448
1449
  if (!targetSlug) return {
1449
1450
  content: [{
@@ -1579,8 +1580,8 @@ async function searchKnowledge(dataDir, slug, query, limit) {
1579
1580
  }
1580
1581
  //#endregion
1581
1582
  //#region src/mcp/tools/search-customer-knowledge.ts
1582
- const DATA_DIR$52 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1583
- async function handleSearchCustomerKnowledge(input, dataDir = DATA_DIR$52) {
1583
+ const DATA_DIR$53 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1584
+ async function handleSearchCustomerKnowledge(input, dataDir = DATA_DIR$53) {
1584
1585
  const limit = input.limit ?? 5;
1585
1586
  try {
1586
1587
  const results = await searchKnowledge(dataDir, input.slug, input.query, limit);
@@ -1628,14 +1629,14 @@ If no results: returns empty array with a helpful sync suggestion.`,
1628
1629
  }
1629
1630
  //#endregion
1630
1631
  //#region src/mcp/tools/list-customers.ts
1631
- const DATA_DIR$51 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1632
+ const DATA_DIR$52 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1632
1633
  function extractLastInteractionDate(interactionsPath) {
1633
1634
  if (!fs.existsSync(interactionsPath)) return void 0;
1634
1635
  const content = fs.readFileSync(interactionsPath, "utf-8");
1635
1636
  const match = /^## (\d{4}-\d{2}-\d{2})/m.exec(content);
1636
1637
  return match ? match[1] : void 0;
1637
1638
  }
1638
- async function handleListCustomers(input, dataDir = DATA_DIR$51) {
1639
+ async function handleListCustomers(input, dataDir = DATA_DIR$52) {
1639
1640
  const customersDir = path.join(dataDir, "customers");
1640
1641
  const customers = [];
1641
1642
  if (!fs.existsSync(customersDir)) return { content: [{
@@ -2148,8 +2149,8 @@ async function updateHealthFromInteraction(dataDir, slug) {
2148
2149
  }
2149
2150
  //#endregion
2150
2151
  //#region src/mcp/tools/log-interaction.ts
2151
- const DATA_DIR$50 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2152
- async function handleLogInteraction(input, dataDir = DATA_DIR$50) {
2152
+ const DATA_DIR$51 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2153
+ async function handleLogInteraction(input, dataDir = DATA_DIR$51) {
2153
2154
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
2154
2155
  const interactionDate = input.date ?? today;
2155
2156
  const sourceRef = input.source ?? `agent://log/${Date.now()}`;
@@ -2258,8 +2259,8 @@ var update_deal_exports = /* @__PURE__ */ __exportAll({
2258
2259
  handleUpdateDeal: () => handleUpdateDeal,
2259
2260
  registerUpdateDeal: () => registerUpdateDeal
2260
2261
  });
2261
- const DATA_DIR$49 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2262
- async function handleUpdateDeal(input, dataDir = DATA_DIR$49) {
2262
+ const DATA_DIR$50 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2263
+ async function handleUpdateDeal(input, dataDir = DATA_DIR$50) {
2263
2264
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
2264
2265
  const deal = {
2265
2266
  name: input.dealName,
@@ -2342,12 +2343,12 @@ Returns: { success: boolean, deal: object }`,
2342
2343
  }
2343
2344
  //#endregion
2344
2345
  //#region src/mcp/tools/export-customer.ts
2345
- const DATA_DIR$48 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2346
+ const DATA_DIR$49 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2346
2347
  function countInteractions(content) {
2347
2348
  const matches = content.match(/^## \d{4}-\d{2}-\d{2}/gm);
2348
2349
  return matches ? matches.length : 0;
2349
2350
  }
2350
- async function handleExportCustomer(input, dataDir = DATA_DIR$48) {
2351
+ async function handleExportCustomer(input, dataDir = DATA_DIR$49) {
2351
2352
  enforceRbac(dataDir, "export_customer");
2352
2353
  const customerDir = path.join(dataDir, "customers", input.slug);
2353
2354
  if (!fs.existsSync(customerDir)) return {
@@ -2460,8 +2461,8 @@ Returns:
2460
2461
  }
2461
2462
  //#endregion
2462
2463
  //#region src/mcp/tools/update-customer-facts.ts
2463
- const DATA_DIR$47 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2464
- async function handleUpdateCustomerFacts(input, dataDir = DATA_DIR$47) {
2464
+ const DATA_DIR$48 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2465
+ async function handleUpdateCustomerFacts(input, dataDir = DATA_DIR$48) {
2465
2466
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
2466
2467
  try {
2467
2468
  enforceRbac(dataDir, "update_customer_facts");
@@ -2639,8 +2640,8 @@ function scoreDealForToday(deal, todayDate) {
2639
2640
  }
2640
2641
  //#endregion
2641
2642
  //#region src/mcp/tools/get-deal-health.ts
2642
- const DATA_DIR$46 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2643
- async function handleGetDealHealth(input, dataDir = DATA_DIR$46) {
2643
+ const DATA_DIR$47 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2644
+ async function handleGetDealHealth(input, dataDir = DATA_DIR$47) {
2644
2645
  try {
2645
2646
  const deals = await readPipeline(dataDir, input.slug);
2646
2647
  const today = /* @__PURE__ */ new Date();
@@ -2689,8 +2690,8 @@ Returns: { slug, deals: [{ deal, stage, score, grade, signals, warnings }] }`,
2689
2690
  }
2690
2691
  //#endregion
2691
2692
  //#region src/mcp/tools/get-pipeline-forecast.ts
2692
- const DATA_DIR$45 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2693
- async function handleGetPipelineForecast(input, dataDir = DATA_DIR$45) {
2693
+ const DATA_DIR$46 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2694
+ async function handleGetPipelineForecast(input, dataDir = DATA_DIR$46) {
2694
2695
  try {
2695
2696
  const slugs = listCustomerSlugs(dataDir).filter((d) => !input.filter || d.includes(input.filter));
2696
2697
  const allDeals = [];
@@ -2751,8 +2752,8 @@ Returns: { deals: [...], totalWeightedValue: number, byStage: { stage: { count,
2751
2752
  }
2752
2753
  //#endregion
2753
2754
  //#region src/mcp/tools/summarize-meeting.ts
2754
- const DATA_DIR$44 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2755
- async function handleSummarizeMeeting(input, dataDir = DATA_DIR$44) {
2755
+ const DATA_DIR$45 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2756
+ async function handleSummarizeMeeting(input, dataDir = DATA_DIR$45) {
2756
2757
  try {
2757
2758
  let summary = input.transcript.slice(0, 400);
2758
2759
  let nextSteps = [];
@@ -2875,8 +2876,8 @@ function getPipelineStages(dataDir) {
2875
2876
  }
2876
2877
  //#endregion
2877
2878
  //#region src/mcp/tools/get-pipeline-stages.ts
2878
- const DATA_DIR$43 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2879
- async function handleGetPipelineStages(_input, dataDir = DATA_DIR$43) {
2879
+ const DATA_DIR$44 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2880
+ async function handleGetPipelineStages(_input, dataDir = DATA_DIR$44) {
2880
2881
  const stages = getPipelineStages(dataDir);
2881
2882
  return { content: [{
2882
2883
  type: "text",
@@ -2904,8 +2905,8 @@ async function searchAcrossCustomers(dataDir, query, limit = 5, excludeSlug) {
2904
2905
  }
2905
2906
  //#endregion
2906
2907
  //#region src/mcp/tools/get-market-intelligence.ts
2907
- const DATA_DIR$42 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2908
- async function handleGetMarketIntelligence(input, dataDir = DATA_DIR$42) {
2908
+ const DATA_DIR$43 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2909
+ async function handleGetMarketIntelligence(input, dataDir = DATA_DIR$43) {
2909
2910
  const excludeSlug = input.excludeCurrentCustomer ? input.slug : void 0;
2910
2911
  const all = listCustomerSlugs(dataDir);
2911
2912
  const totalCustomersSearched = excludeSlug ? all.filter((s) => s !== excludeSlug).length : all.length;
@@ -2936,7 +2937,7 @@ function registerGetMarketIntelligence(server) {
2936
2937
  }
2937
2938
  //#endregion
2938
2939
  //#region src/mcp/tools/get-relationship-graph.ts
2939
- const DATA_DIR$41 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2940
+ const DATA_DIR$42 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2940
2941
  function summarizeNode(n) {
2941
2942
  return {
2942
2943
  id: n.id,
@@ -2944,7 +2945,7 @@ function summarizeNode(n) {
2944
2945
  email: n.properties["email"]
2945
2946
  };
2946
2947
  }
2947
- async function handleGetRelationshipGraph(input, dataDir = DATA_DIR$41) {
2948
+ async function handleGetRelationshipGraph(input, dataDir = DATA_DIR$42) {
2948
2949
  try {
2949
2950
  const graph = readGraph(dataDir, input.slug);
2950
2951
  const stakeholders = getStakeholders(graph);
@@ -3012,9 +3013,9 @@ Returns: {
3012
3013
  }
3013
3014
  //#endregion
3014
3015
  //#region src/mcp/tools/get-relationship-health.ts
3015
- const DATA_DIR$40 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3016
+ const DATA_DIR$41 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3016
3017
  const MAX_HEALTH_AGE_MS = 3600 * 1e3;
3017
- async function handleGetRelationshipHealth(input, dataDir = DATA_DIR$40) {
3018
+ async function handleGetRelationshipHealth(input, dataDir = DATA_DIR$41) {
3018
3019
  try {
3019
3020
  let health = readHealth(dataDir, input.slug);
3020
3021
  if (health === null || Date.now() - new Date(health.updatedAt).getTime() > MAX_HEALTH_AGE_MS) {
@@ -3683,8 +3684,8 @@ async function runDealAgent(config, dataDir, llmFn = callLlm) {
3683
3684
  }
3684
3685
  //#endregion
3685
3686
  //#region src/mcp/tools/run-deal-agent.ts
3686
- const DATA_DIR$39 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3687
- async function handleRunDealAgent(input, dataDir = DATA_DIR$39) {
3687
+ const DATA_DIR$40 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3688
+ async function handleRunDealAgent(input, dataDir = DATA_DIR$40) {
3688
3689
  try {
3689
3690
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
3690
3691
  const result = await runDealAgent({
@@ -3751,8 +3752,8 @@ Returns: { assessment, riskLevel, plan[], actionsQueued[], actionsExecuted[], tr
3751
3752
  }
3752
3753
  //#endregion
3753
3754
  //#region src/mcp/tools/approve-agent-action.ts
3754
- const DATA_DIR$38 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3755
- async function handleApproveAgentAction(input, dataDir = DATA_DIR$38) {
3755
+ const DATA_DIR$39 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3756
+ async function handleApproveAgentAction(input, dataDir = DATA_DIR$39) {
3756
3757
  try {
3757
3758
  const queue = readAgentQueue(dataDir, input.slug);
3758
3759
  const idx = queue.pendingActions.findIndex((a) => a.actionId === input.actionId);
@@ -4012,8 +4013,8 @@ async function buildSimulationInput(dataDir, horizon, today, externalSignals = [
4012
4013
  }
4013
4014
  //#endregion
4014
4015
  //#region src/mcp/tools/simulate-revenue.ts
4015
- const DATA_DIR$37 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4016
- async function handleSimulateRevenue(input, dataDir = DATA_DIR$37) {
4016
+ const DATA_DIR$38 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4017
+ async function handleSimulateRevenue(input, dataDir = DATA_DIR$38) {
4017
4018
  try {
4018
4019
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4019
4020
  const horizon = input.horizon ?? "quarter";
@@ -4071,8 +4072,8 @@ Returns: { forecast: { p10, p50, p90, expected, stdDev, atRiskRevenue, byCloseMo
4071
4072
  }
4072
4073
  //#endregion
4073
4074
  //#region src/mcp/tools/get-playbook.ts
4074
- const DATA_DIR$36 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4075
- async function handleGetPlaybook(input, dataDir = DATA_DIR$36) {
4075
+ const DATA_DIR$37 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4076
+ async function handleGetPlaybook(input, dataDir = DATA_DIR$37) {
4076
4077
  try {
4077
4078
  const playbooks = listPlaybooks(dataDir, input.slug);
4078
4079
  if (!(input.stage !== void 0 || input.value !== void 0 || input.healthScore !== void 0)) return { content: [{
@@ -4157,12 +4158,12 @@ Returns: { matches: [{ name, score, trigger, successRate, usedCount, content }],
4157
4158
  ...healthScore !== void 0 ? { healthScore } : {},
4158
4159
  ...daysSinceContact !== void 0 ? { daysSinceContact } : {},
4159
4160
  ...championPresent !== void 0 ? { championPresent } : {}
4160
- }, DATA_DIR$36));
4161
+ }, DATA_DIR$37));
4161
4162
  }
4162
4163
  //#endregion
4163
4164
  //#region src/mcp/tools/create-playbook.ts
4164
- const DATA_DIR$35 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4165
- async function handleCreatePlaybook(input, dataDir = DATA_DIR$35) {
4165
+ const DATA_DIR$36 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4166
+ async function handleCreatePlaybook(input, dataDir = DATA_DIR$36) {
4166
4167
  try {
4167
4168
  const name = toKebabCase(input.name);
4168
4169
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -4235,12 +4236,12 @@ Returns: { success: true, playbook: { name, trigger, successRate, path } }`,
4235
4236
  trigger,
4236
4237
  content,
4237
4238
  ...successRate !== void 0 ? { successRate } : {}
4238
- }, DATA_DIR$35));
4239
+ }, DATA_DIR$36));
4239
4240
  }
4240
4241
  //#endregion
4241
4242
  //#region src/mcp/tools/list-playbooks.ts
4242
- const DATA_DIR$34 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4243
- async function handleListPlaybooks(input, dataDir = DATA_DIR$34) {
4243
+ const DATA_DIR$35 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4244
+ async function handleListPlaybooks(input, dataDir = DATA_DIR$35) {
4244
4245
  try {
4245
4246
  const playbooks = listPlaybooks(dataDir, input.slug);
4246
4247
  return { content: [{
@@ -4279,12 +4280,12 @@ Args:
4279
4280
 
4280
4281
  Returns: { playbooks: [{ name, trigger, successRate, usedCount, lastUpdated }], count, slug }`,
4281
4282
  inputSchema: z.object({ slug: z.string().describe("Customer ID") })
4282
- }, async ({ slug }) => handleListPlaybooks({ slug }, DATA_DIR$34));
4283
+ }, async ({ slug }) => handleListPlaybooks({ slug }, DATA_DIR$35));
4283
4284
  }
4284
4285
  //#endregion
4285
4286
  //#region src/mcp/tools/distill-playbook.ts
4286
- const DATA_DIR$33 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4287
- async function handleDistillPlaybook(input, dataDir = DATA_DIR$33, llmFn = callLlm) {
4287
+ const DATA_DIR$34 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4288
+ async function handleDistillPlaybook(input, dataDir = DATA_DIR$34, llmFn = callLlm) {
4288
4289
  try {
4289
4290
  const result = await distillPlaybook(dataDir, input.slug, input.dealName, input.outcome, llmFn);
4290
4291
  if (!result.ok) {
@@ -4343,7 +4344,7 @@ Returns: { success: true, playbook: { name, trigger, successRate, path }, reason
4343
4344
  slug,
4344
4345
  dealName,
4345
4346
  outcome
4346
- }, DATA_DIR$33));
4347
+ }, DATA_DIR$34));
4347
4348
  }
4348
4349
  //#endregion
4349
4350
  //#region src/core/goal-engine.ts
@@ -4561,8 +4562,8 @@ function getActiveGoals(dataDir) {
4561
4562
  }
4562
4563
  //#endregion
4563
4564
  //#region src/mcp/tools/pursue-goal.ts
4564
- const DATA_DIR$32 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4565
- async function handlePursueGoal(input, dataDir = DATA_DIR$32, options = {}) {
4565
+ const DATA_DIR$33 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4566
+ async function handlePursueGoal(input, dataDir = DATA_DIR$33, options = {}) {
4566
4567
  try {
4567
4568
  enforceRbac(dataDir, "pursue_goal");
4568
4569
  const goal = await pursueGoal(dataDir, {
@@ -4625,12 +4626,12 @@ Returns: { goalId, description, target, deadline, decomposition: { analysis, cur
4625
4626
  goal,
4626
4627
  deadline,
4627
4628
  ...context !== void 0 ? { context } : {}
4628
- }, DATA_DIR$32));
4629
+ }, DATA_DIR$33));
4629
4630
  }
4630
4631
  //#endregion
4631
4632
  //#region src/mcp/tools/get-goal-status.ts
4632
- const DATA_DIR$31 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4633
- async function handleGetGoalStatus(input, dataDir = DATA_DIR$31) {
4633
+ const DATA_DIR$32 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4634
+ async function handleGetGoalStatus(input, dataDir = DATA_DIR$32) {
4634
4635
  try {
4635
4636
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4636
4637
  const allGoals = input.goalId ? readGoals(dataDir).filter((g) => g.id === input.goalId) : getActiveGoals(dataDir);
@@ -4689,17 +4690,17 @@ Args:
4689
4690
 
4690
4691
  Returns: { goals: [{ id, description, target, progress, status, deadline, daysRemaining, subGoals }], activeCount, completedCount }`,
4691
4692
  inputSchema: z.object({ goalId: z.string().optional().describe("Specific goal ID (omit for all active goals)") })
4692
- }, async ({ goalId }) => handleGetGoalStatus({ ...goalId !== void 0 ? { goalId } : {} }, DATA_DIR$31));
4693
+ }, async ({ goalId }) => handleGetGoalStatus({ ...goalId !== void 0 ? { goalId } : {} }, DATA_DIR$32));
4693
4694
  }
4694
4695
  //#endregion
4695
4696
  //#region src/mcp/tools/register-push-subscription.ts
4696
- const DATA_DIR$30 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4697
+ const DATA_DIR$31 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4697
4698
  const VALID_PROVIDERS = [
4698
4699
  "gmail",
4699
4700
  "microsoft-graph",
4700
4701
  "slack"
4701
4702
  ];
4702
- async function handleRegisterPushSubscription(input, dataDir = DATA_DIR$30) {
4703
+ async function handleRegisterPushSubscription(input, dataDir = DATA_DIR$31) {
4703
4704
  try {
4704
4705
  if (!VALID_PROVIDERS.includes(input.provider)) return { content: [{
4705
4706
  type: "text",
@@ -4785,12 +4786,12 @@ Returns: { subscriptionId, provider, slug, status, expiresAt, createdAt, warning
4785
4786
  ...microsoftResource !== void 0 ? { microsoftResource } : {},
4786
4787
  ...slackTeamId !== void 0 ? { slackTeamId } : {},
4787
4788
  ...slackChannelId !== void 0 ? { slackChannelId } : {}
4788
- }, DATA_DIR$30));
4789
+ }, DATA_DIR$31));
4789
4790
  }
4790
4791
  //#endregion
4791
4792
  //#region src/mcp/tools/get-push-status.ts
4792
- const DATA_DIR$29 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4793
- async function handleGetPushStatus(input, dataDir = DATA_DIR$29) {
4793
+ const DATA_DIR$30 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4794
+ async function handleGetPushStatus(input, dataDir = DATA_DIR$30) {
4794
4795
  try {
4795
4796
  let subs = await readSubscriptions(dataDir);
4796
4797
  if (input.slug) subs = subs.filter((s) => s.slug === input.slug);
@@ -4862,7 +4863,7 @@ Returns: { subscriptions: [{ id, provider, slug, status, expiresAt, expiresInHou
4862
4863
  }, async ({ slug, provider }) => handleGetPushStatus({
4863
4864
  ...slug !== void 0 ? { slug } : {},
4864
4865
  ...provider !== void 0 ? { provider } : {}
4865
- }, DATA_DIR$29));
4866
+ }, DATA_DIR$30));
4866
4867
  }
4867
4868
  //#endregion
4868
4869
  //#region src/core/org-intelligence.ts
@@ -4928,8 +4929,8 @@ function deriveRecommendation(people, missingRoles) {
4928
4929
  }
4929
4930
  //#endregion
4930
4931
  //#region src/mcp/tools/get-org-intelligence.ts
4931
- const DATA_DIR$28 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4932
- async function handleGetOrgIntelligence(input, dataDir = DATA_DIR$28) {
4932
+ const DATA_DIR$29 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4933
+ async function handleGetOrgIntelligence(input, dataDir = DATA_DIR$29) {
4933
4934
  try {
4934
4935
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4935
4936
  const map = buildStakeholderMap(dataDir, input.slug, today, input.dealName);
@@ -5062,8 +5063,8 @@ function buildExecutiveSummary(slug, dealName, stakeholders, overallHealth, sim,
5062
5063
  }
5063
5064
  //#endregion
5064
5065
  //#region src/mcp/tools/open-deal-room.ts
5065
- const DATA_DIR$27 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5066
- async function handleOpenDealRoom(input, dataDir = DATA_DIR$27) {
5066
+ const DATA_DIR$28 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5067
+ async function handleOpenDealRoom(input, dataDir = DATA_DIR$28) {
5067
5068
  try {
5068
5069
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
5069
5070
  const brief = await buildDealRoom(dataDir, input.slug, input.dealName, today);
@@ -5146,8 +5147,8 @@ async function buildDailyBriefing(dataDir, today) {
5146
5147
  }
5147
5148
  //#endregion
5148
5149
  //#region src/mcp/tools/get-proactive-briefing.ts
5149
- const DATA_DIR$26 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5150
- async function handleGetProactiveBriefing(input, dataDir = DATA_DIR$26) {
5150
+ const DATA_DIR$27 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5151
+ async function handleGetProactiveBriefing(input, dataDir = DATA_DIR$27) {
5151
5152
  try {
5152
5153
  const briefing = await buildDailyBriefing(dataDir, input.date ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10));
5153
5154
  return { content: [{
@@ -5247,15 +5248,15 @@ function getTemplate(dataDir, id) {
5247
5248
  }
5248
5249
  //#endregion
5249
5250
  //#region src/mcp/tools/list-email-templates.ts
5250
- const DATA_DIR$25 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5251
- async function handleListEmailTemplates(input, dataDir = DATA_DIR$25) {
5251
+ const DATA_DIR$26 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5252
+ async function handleListEmailTemplates(input, dataDir = DATA_DIR$26) {
5252
5253
  const summary = listTemplates(dataDir, input.category ? { category: input.category } : {}).map(({ body: _body, ...meta }) => meta);
5253
5254
  return { content: [{
5254
5255
  type: "text",
5255
5256
  text: JSON.stringify(summary, null, 2)
5256
5257
  }] };
5257
5258
  }
5258
- function registerListEmailTemplates(server, dataDir = DATA_DIR$25) {
5259
+ function registerListEmailTemplates(server, dataDir = DATA_DIR$26) {
5259
5260
  server.registerTool("list_email_templates", {
5260
5261
  description: "List available email templates. Optionally filter by category (e.g. 'outreach', 'followup', 'support').",
5261
5262
  inputSchema: z.object({ category: z.string().optional().describe("Filter by category") })
@@ -5289,8 +5290,8 @@ async function buildVariablesFromCustomer(dataDir, slug) {
5289
5290
  }
5290
5291
  //#endregion
5291
5292
  //#region src/mcp/tools/get-email-template.ts
5292
- const DATA_DIR$24 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5293
- async function handleGetEmailTemplate(input, dataDir = DATA_DIR$24) {
5293
+ const DATA_DIR$25 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5294
+ async function handleGetEmailTemplate(input, dataDir = DATA_DIR$25) {
5294
5295
  const tmpl = getTemplate(dataDir, input.id);
5295
5296
  if (!tmpl) return { content: [{
5296
5297
  type: "text",
@@ -5306,7 +5307,7 @@ async function handleGetEmailTemplate(input, dataDir = DATA_DIR$24) {
5306
5307
  }, null, 2)
5307
5308
  }] };
5308
5309
  }
5309
- function registerGetEmailTemplate(server, dataDir = DATA_DIR$24) {
5310
+ function registerGetEmailTemplate(server, dataDir = DATA_DIR$25) {
5310
5311
  server.registerTool("get_email_template", {
5311
5312
  description: "Get a specific email template by ID, including its body and detected variables.",
5312
5313
  inputSchema: z.object({ id: z.string().describe("Template ID (e.g. 'enterprise-intro')") })
@@ -5314,8 +5315,8 @@ function registerGetEmailTemplate(server, dataDir = DATA_DIR$24) {
5314
5315
  }
5315
5316
  //#endregion
5316
5317
  //#region src/mcp/tools/draft-email.ts
5317
- const DATA_DIR$23 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5318
- async function handleDraftEmail(input, dataDir = DATA_DIR$23) {
5318
+ const DATA_DIR$24 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5319
+ async function handleDraftEmail(input, dataDir = DATA_DIR$24) {
5319
5320
  const tmpl = getTemplate(dataDir, input.templateId);
5320
5321
  if (!tmpl) return { content: [{
5321
5322
  type: "text",
@@ -5359,7 +5360,7 @@ async function handleDraftEmail(input, dataDir = DATA_DIR$23) {
5359
5360
  }, null, 2)
5360
5361
  }] };
5361
5362
  }
5362
- function registerDraftEmail(server, dataDir = DATA_DIR$23) {
5363
+ function registerDraftEmail(server, dataDir = DATA_DIR$24) {
5363
5364
  server.registerTool("draft_email", {
5364
5365
  description: `Draft a personalized email for a customer using a stored template.
5365
5366
  Variables are auto-filled from the customer's main_facts.md. Override any variable manually.
@@ -5467,8 +5468,8 @@ async function updateEnrollment(dataDir, id, updates) {
5467
5468
  }
5468
5469
  //#endregion
5469
5470
  //#region src/mcp/tools/enroll-in-sequence.ts
5470
- const DATA_DIR$22 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5471
- async function handleEnrollInSequence(input, dataDir = DATA_DIR$22) {
5471
+ const DATA_DIR$23 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5472
+ async function handleEnrollInSequence(input, dataDir = DATA_DIR$23) {
5472
5473
  const sequence = getSequence(dataDir, input.sequenceId);
5473
5474
  if (!sequence) return { content: [{
5474
5475
  type: "text",
@@ -5500,7 +5501,7 @@ async function handleEnrollInSequence(input, dataDir = DATA_DIR$22) {
5500
5501
  })
5501
5502
  }] };
5502
5503
  }
5503
- function registerEnrollInSequence(server, dataDir = DATA_DIR$22) {
5504
+ function registerEnrollInSequence(server, dataDir = DATA_DIR$23) {
5504
5505
  server.registerTool("enroll_in_sequence", {
5505
5506
  description: `Enroll a contact in an email sequence. Validates that the sequence and its first template exist.
5506
5507
  Returns: { enrollmentId, sequenceName, totalSteps }`,
@@ -5517,8 +5518,8 @@ Returns: { enrollmentId, sequenceName, totalSteps }`,
5517
5518
  }
5518
5519
  //#endregion
5519
5520
  //#region src/mcp/tools/list-sequence-enrollments.ts
5520
- const DATA_DIR$21 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5521
- async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$21) {
5521
+ const DATA_DIR$22 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5522
+ async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$22) {
5522
5523
  let enrollments = readEnrollments(dataDir);
5523
5524
  if (input.slug !== void 0) enrollments = enrollments.filter((e) => e.slug === input.slug);
5524
5525
  if (input.status !== void 0) enrollments = enrollments.filter((e) => e.status === input.status);
@@ -5527,7 +5528,7 @@ async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$21) {
5527
5528
  text: JSON.stringify({ enrollments }, null, 2)
5528
5529
  }] };
5529
5530
  }
5530
- function registerListSequenceEnrollments(server, dataDir = DATA_DIR$21) {
5531
+ function registerListSequenceEnrollments(server, dataDir = DATA_DIR$22) {
5531
5532
  server.registerTool("list_sequence_enrollments", {
5532
5533
  description: `List email sequence enrollments. Filter by customer slug or status.
5533
5534
  Returns: { enrollments: SequenceEnrollment[] }`,
@@ -5546,8 +5547,8 @@ Returns: { enrollments: SequenceEnrollment[] }`,
5546
5547
  }
5547
5548
  //#endregion
5548
5549
  //#region src/mcp/tools/unenroll-from-sequence.ts
5549
- const DATA_DIR$20 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5550
- async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$20) {
5550
+ const DATA_DIR$21 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5551
+ async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$21) {
5551
5552
  if (!await updateEnrollment(dataDir, input.enrollmentId, { status: "paused" })) return { content: [{
5552
5553
  type: "text",
5553
5554
  text: JSON.stringify({
@@ -5560,7 +5561,7 @@ async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$20) {
5560
5561
  text: JSON.stringify({ success: true })
5561
5562
  }] };
5562
5563
  }
5563
- function registerUnenrollFromSequence(server, dataDir = DATA_DIR$20) {
5564
+ function registerUnenrollFromSequence(server, dataDir = DATA_DIR$21) {
5564
5565
  server.registerTool("unenroll_from_sequence", {
5565
5566
  description: `Unenroll (pause) a contact from an email sequence. Sets status to "paused" (soft delete).
5566
5567
  Returns: { success: boolean }`,
@@ -5569,8 +5570,8 @@ Returns: { success: boolean }`,
5569
5570
  }
5570
5571
  //#endregion
5571
5572
  //#region src/mcp/tools/list-sequences.ts
5572
- const DATA_DIR$19 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5573
- async function handleListSequences(_input, dataDir = DATA_DIR$19) {
5573
+ const DATA_DIR$20 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5574
+ async function handleListSequences(_input, dataDir = DATA_DIR$20) {
5574
5575
  const sequences = listSequences(dataDir);
5575
5576
  const enrollments = readEnrollments(dataDir);
5576
5577
  const result = sequences.map((seq) => ({
@@ -5584,7 +5585,7 @@ async function handleListSequences(_input, dataDir = DATA_DIR$19) {
5584
5585
  text: JSON.stringify({ sequences: result }, null, 2)
5585
5586
  }] };
5586
5587
  }
5587
- function registerListSequences(server, dataDir = DATA_DIR$19) {
5588
+ function registerListSequences(server, dataDir = DATA_DIR$20) {
5588
5589
  server.registerTool("list_sequences", {
5589
5590
  description: `List all email sequences with step count and enrollment count.
5590
5591
  Returns: { sequences: Array<{ id, name, stepCount, enrollmentCount }> }`,
@@ -5719,8 +5720,8 @@ async function generateQuote(dataDir, input) {
5719
5720
  }
5720
5721
  //#endregion
5721
5722
  //#region src/mcp/tools/generate-quote.ts
5722
- const DATA_DIR$18 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5723
- async function handleGenerateQuote(input, dataDir = DATA_DIR$18) {
5723
+ const DATA_DIR$19 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5724
+ async function handleGenerateQuote(input, dataDir = DATA_DIR$19) {
5724
5725
  try {
5725
5726
  const quote = await generateQuote(dataDir, input);
5726
5727
  return { content: [{
@@ -5744,7 +5745,7 @@ async function handleGenerateQuote(input, dataDir = DATA_DIR$18) {
5744
5745
  }] };
5745
5746
  }
5746
5747
  }
5747
- function registerGenerateQuote(server, dataDir = DATA_DIR$18) {
5748
+ function registerGenerateQuote(server, dataDir = DATA_DIR$19) {
5748
5749
  server.registerTool("generate_quote", {
5749
5750
  description: `Generate a professional HTML quote/offer for a customer deal.
5750
5751
  Calculates subtotal, VAT, and total. Saves JSON + HTML to .agentic/quotes/.
@@ -5772,8 +5773,8 @@ Returns: { quoteNumber, htmlPath, total, currency, validUntil }`,
5772
5773
  }
5773
5774
  //#endregion
5774
5775
  //#region src/mcp/tools/get-quote-status.ts
5775
- const DATA_DIR$17 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5776
- async function handleGetQuoteStatus(input, dataDir = DATA_DIR$17) {
5776
+ const DATA_DIR$18 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5777
+ async function handleGetQuoteStatus(input, dataDir = DATA_DIR$18) {
5777
5778
  if (input.quoteNumber) {
5778
5779
  const quote = readQuote(dataDir, input.quoteNumber);
5779
5780
  if (!quote) return { content: [{
@@ -5791,7 +5792,7 @@ async function handleGetQuoteStatus(input, dataDir = DATA_DIR$17) {
5791
5792
  text: JSON.stringify({ quotes }, null, 2)
5792
5793
  }] };
5793
5794
  }
5794
- function registerGetQuoteStatus(server, dataDir = DATA_DIR$17) {
5795
+ function registerGetQuoteStatus(server, dataDir = DATA_DIR$18) {
5795
5796
  server.registerTool("get_quote_status", {
5796
5797
  description: `Get quote status and details. Filter by quoteNumber (single quote) or slug (all quotes for a customer).
5797
5798
  Returns quote with status: draft | sent | viewed | accepted | declined`,
@@ -5806,7 +5807,7 @@ Returns quote with status: draft | sent | viewed | accepted | declined`,
5806
5807
  }
5807
5808
  //#endregion
5808
5809
  //#region src/mcp/tools/get-booking-link.ts
5809
- const DATA_DIR$16 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5810
+ const DATA_DIR$17 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5810
5811
  function loadCalendlyConfig(dataDir) {
5811
5812
  const p = path.join(dataDir, ".agentic", "integrations", "calendly.yaml");
5812
5813
  if (!fs.existsSync(p)) return {};
@@ -5829,7 +5830,7 @@ function readCustomerFacts(dataDir, slug) {
5829
5830
  ...email ? { email } : {}
5830
5831
  };
5831
5832
  }
5832
- async function handleGetBookingLink(input, dataDir = DATA_DIR$16) {
5833
+ async function handleGetBookingLink(input, dataDir = DATA_DIR$17) {
5833
5834
  const config = loadCalendlyConfig(dataDir);
5834
5835
  const apiKey = config.apiKey ?? process.env["CALENDLY_API_KEY"] ?? "";
5835
5836
  if (!apiKey) return { content: [{
@@ -5857,7 +5858,7 @@ async function handleGetBookingLink(input, dataDir = DATA_DIR$16) {
5857
5858
  }] };
5858
5859
  }
5859
5860
  }
5860
- function registerGetBookingLink(server, dataDir = DATA_DIR$16) {
5861
+ function registerGetBookingLink(server, dataDir = DATA_DIR$17) {
5861
5862
  server.registerTool("get_booking_link", {
5862
5863
  description: `Get a Calendly booking link for a customer. Optionally pre-fills the customer's name/email.
5863
5864
  Requires CALENDLY_API_KEY env var or .agentic/integrations/calendly.yaml config.
@@ -6027,8 +6028,8 @@ function calcSlaDue(createdDate, priority, rules) {
6027
6028
  }
6028
6029
  //#endregion
6029
6030
  //#region src/mcp/tools/create-ticket.ts
6030
- const DATA_DIR$15 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6031
- async function handleCreateTicket(input, dataDir = DATA_DIR$15) {
6031
+ const DATA_DIR$16 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6032
+ async function handleCreateTicket(input, dataDir = DATA_DIR$16) {
6032
6033
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
6033
6034
  const rules = loadSlaRules(dataDir);
6034
6035
  const priority = input.priority ?? "normal";
@@ -6050,7 +6051,7 @@ async function handleCreateTicket(input, dataDir = DATA_DIR$15) {
6050
6051
  text: JSON.stringify({ ticket }, null, 2)
6051
6052
  }] };
6052
6053
  }
6053
- function registerCreateTicket(server, dataDir = DATA_DIR$15) {
6054
+ function registerCreateTicket(server, dataDir = DATA_DIR$16) {
6054
6055
  server.registerTool("create_ticket", {
6055
6056
  description: `Create a support ticket for a customer. Auto-calculates SLA due date based on priority.
6056
6057
  Returns: { ticket } with id T-NNN, status=open, slaDue`,
@@ -6076,8 +6077,8 @@ Returns: { ticket } with id T-NNN, status=open, slaDue`,
6076
6077
  }
6077
6078
  //#endregion
6078
6079
  //#region src/mcp/tools/update-ticket.ts
6079
- const DATA_DIR$14 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6080
- async function handleUpdateTicket(input, dataDir = DATA_DIR$14) {
6080
+ const DATA_DIR$15 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6081
+ async function handleUpdateTicket(input, dataDir = DATA_DIR$15) {
6081
6082
  const ticket = (await readTickets(dataDir, input.slug)).find((t) => t.id === input.ticketId);
6082
6083
  if (!ticket) return { content: [{
6083
6084
  type: "text",
@@ -6096,7 +6097,7 @@ async function handleUpdateTicket(input, dataDir = DATA_DIR$14) {
6096
6097
  text: JSON.stringify({ ticket: updated }, null, 2)
6097
6098
  }] };
6098
6099
  }
6099
- function registerUpdateTicket(server, dataDir = DATA_DIR$14) {
6100
+ function registerUpdateTicket(server, dataDir = DATA_DIR$15) {
6100
6101
  server.registerTool("update_ticket", {
6101
6102
  description: `Update a ticket's status or assignee. Setting status=resolved auto-sets resolved date.
6102
6103
  Returns: { ticket }`,
@@ -6121,8 +6122,8 @@ Returns: { ticket }`,
6121
6122
  }
6122
6123
  //#endregion
6123
6124
  //#region src/mcp/tools/list-tickets.ts
6124
- const DATA_DIR$13 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6125
- async function handleListTickets(input, dataDir = DATA_DIR$13) {
6125
+ const DATA_DIR$14 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6126
+ async function handleListTickets(input, dataDir = DATA_DIR$14) {
6126
6127
  const results = await listAllTickets(dataDir, {
6127
6128
  ...input.slug !== void 0 ? { slug: input.slug } : {},
6128
6129
  ...input.status !== void 0 ? { status: input.status } : {},
@@ -6134,7 +6135,7 @@ async function handleListTickets(input, dataDir = DATA_DIR$13) {
6134
6135
  text: JSON.stringify({ tickets: results }, null, 2)
6135
6136
  }] };
6136
6137
  }
6137
- function registerListTickets(server, dataDir = DATA_DIR$13) {
6138
+ function registerListTickets(server, dataDir = DATA_DIR$14) {
6138
6139
  server.registerTool("list_tickets", {
6139
6140
  description: `List support tickets. Filter by customer, status, priority, or assignee. Sorted by priority then date.
6140
6141
  Returns: { tickets: Array<{ slug, ticket }> }`,
@@ -6164,8 +6165,8 @@ Returns: { tickets: Array<{ slug, ticket }> }`,
6164
6165
  }
6165
6166
  //#endregion
6166
6167
  //#region src/mcp/tools/close-ticket.ts
6167
- const DATA_DIR$12 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6168
- async function handleCloseTicket(input, dataDir = DATA_DIR$12) {
6168
+ const DATA_DIR$13 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6169
+ async function handleCloseTicket(input, dataDir = DATA_DIR$13) {
6169
6170
  const ticket = (await readTickets(dataDir, input.slug)).find((t) => t.id === input.ticketId);
6170
6171
  if (!ticket) return { content: [{
6171
6172
  type: "text",
@@ -6192,7 +6193,7 @@ async function handleCloseTicket(input, dataDir = DATA_DIR$12) {
6192
6193
  text: JSON.stringify({ ticket: updated }, null, 2)
6193
6194
  }] };
6194
6195
  }
6195
- function registerCloseTicket(server, dataDir = DATA_DIR$12) {
6196
+ function registerCloseTicket(server, dataDir = DATA_DIR$13) {
6196
6197
  server.registerTool("close_ticket", {
6197
6198
  description: `Close a support ticket. Optionally logs the resolution as an interaction.
6198
6199
  Returns: { ticket } with status=closed`,
@@ -6346,8 +6347,8 @@ async function savePendingSurvey(dataDir, surveyId, slug, contactEmail, token) {
6346
6347
  }
6347
6348
  //#endregion
6348
6349
  //#region src/mcp/tools/send-nps-survey.ts
6349
- const DATA_DIR$11 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6350
- async function handleSendNpsSurvey(input, dataDir = DATA_DIR$11) {
6350
+ const DATA_DIR$12 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6351
+ async function handleSendNpsSurvey(input, dataDir = DATA_DIR$12) {
6351
6352
  const survey = getSurvey(dataDir, input.surveyId);
6352
6353
  if (!survey) return { content: [{
6353
6354
  type: "text",
@@ -6368,7 +6369,7 @@ async function handleSendNpsSurvey(input, dataDir = DATA_DIR$11) {
6368
6369
  }, null, 2)
6369
6370
  }] };
6370
6371
  }
6371
- function registerSendNpsSurvey(server, dataDir = DATA_DIR$11) {
6372
+ function registerSendNpsSurvey(server, dataDir = DATA_DIR$12) {
6372
6373
  server.registerTool("send_nps_survey", {
6373
6374
  description: `Generate an NPS/CSAT survey email for a customer contact. Returns subject, HTML body, and a token-based response URL.
6374
6375
  Does NOT send automatically — returns draft for review.
@@ -6388,8 +6389,8 @@ Returns: { token, subject, body, surveyUrl }`,
6388
6389
  }
6389
6390
  //#endregion
6390
6391
  //#region src/mcp/tools/get-survey-results.ts
6391
- const DATA_DIR$10 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6392
- async function handleGetSurveyResults(input, dataDir = DATA_DIR$10) {
6392
+ const DATA_DIR$11 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6393
+ async function handleGetSurveyResults(input, dataDir = DATA_DIR$11) {
6393
6394
  const responses = loadSurveyResponses(dataDir, input.surveyId, input.slug);
6394
6395
  const nps = calcNpsScore(responses);
6395
6396
  const promoters = responses.filter((r) => r.score >= 9).length;
@@ -6415,7 +6416,7 @@ async function handleGetSurveyResults(input, dataDir = DATA_DIR$10) {
6415
6416
  }, null, 2)
6416
6417
  }] };
6417
6418
  }
6418
- function registerGetSurveyResults(server, dataDir = DATA_DIR$10) {
6419
+ function registerGetSurveyResults(server, dataDir = DATA_DIR$11) {
6419
6420
  server.registerTool("get_survey_results", {
6420
6421
  description: `Get NPS/CSAT survey results with score breakdown. Calculates Net Promoter Score.
6421
6422
  Returns: { npsScore, totalResponses, promoters, passives, detractors, responses[] }`,
@@ -6516,8 +6517,8 @@ function getKbMetaForExport(article) {
6516
6517
  }
6517
6518
  //#endregion
6518
6519
  //#region src/mcp/tools/search-knowledge-base.ts
6519
- const DATA_DIR$9 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6520
- async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$9) {
6520
+ const DATA_DIR$10 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6521
+ async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$10) {
6521
6522
  const results = searchKbSimple(dataDir, input.query, { ...input.publicOnly ? { publicOnly: true } : {} });
6522
6523
  const limited = (input.category ? results.filter((a) => a.category === input.category) : results).slice(0, input.limit ?? 10);
6523
6524
  return { content: [{
@@ -6532,7 +6533,7 @@ async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$9) {
6532
6533
  }, null, 2)
6533
6534
  }] };
6534
6535
  }
6535
- function registerSearchKnowledgeBase(server, dataDir = DATA_DIR$9) {
6536
+ function registerSearchKnowledgeBase(server, dataDir = DATA_DIR$10) {
6536
6537
  server.registerTool("search_knowledge_base", {
6537
6538
  description: `Search the knowledge base for articles. Text search on title, body, and tags.
6538
6539
  Returns: { count, articles[] } with excerpts`,
@@ -6551,8 +6552,8 @@ Returns: { count, articles[] } with excerpts`,
6551
6552
  }
6552
6553
  //#endregion
6553
6554
  //#region src/mcp/tools/create-kb-article.ts
6554
- const DATA_DIR$8 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6555
- async function handleCreateKbArticle(input, dataDir = DATA_DIR$8) {
6555
+ const DATA_DIR$9 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6556
+ async function handleCreateKbArticle(input, dataDir = DATA_DIR$9) {
6556
6557
  if (getKbArticle(dataDir, input.id)) return { content: [{
6557
6558
  type: "text",
6558
6559
  text: JSON.stringify({ error: `Article '${input.id}' already exists` })
@@ -6580,7 +6581,7 @@ async function handleCreateKbArticle(input, dataDir = DATA_DIR$8) {
6580
6581
  }, null, 2)
6581
6582
  }] };
6582
6583
  }
6583
- function registerCreateKbArticle(server, dataDir = DATA_DIR$8) {
6584
+ function registerCreateKbArticle(server, dataDir = DATA_DIR$9) {
6584
6585
  server.registerTool("create_kb_article", {
6585
6586
  description: `Create a new knowledge base article. Articles are stored as Markdown files in .agentic/knowledge-base/.
6586
6587
  Returns: { id, title, category, path }`,
@@ -6605,8 +6606,8 @@ Returns: { id, title, category, path }`,
6605
6606
  }
6606
6607
  //#endregion
6607
6608
  //#region src/mcp/tools/backup-now.ts
6608
- const DATA_DIR$7 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6609
- async function handleBackupNow(input, dataDir = DATA_DIR$7) {
6609
+ const DATA_DIR$8 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6610
+ async function handleBackupNow(input, dataDir = DATA_DIR$8) {
6610
6611
  const zipPath = path.join(dataDir, `dxcrm-backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19)}.zip`);
6611
6612
  const manifest = await runBackup(zipPath, dataDir, { ...input.remote ? { remote: input.remote } : {} }).catch(() => null);
6612
6613
  if (!manifest) return { content: [{
@@ -6643,8 +6644,8 @@ function registerBackupNow(server) {
6643
6644
  }
6644
6645
  //#endregion
6645
6646
  //#region src/mcp/tools/list-backups.ts
6646
- const DATA_DIR$6 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6647
- async function handleListBackups(input, dataDir = DATA_DIR$6) {
6647
+ const DATA_DIR$7 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6648
+ async function handleListBackups(input, dataDir = DATA_DIR$7) {
6648
6649
  const logEntries = readBackupLog(dataDir);
6649
6650
  const fileEntries = listBackupsInDir(dataDir);
6650
6651
  const entries = logEntries.length > 0 ? logEntries : fileEntries;
@@ -6678,8 +6679,8 @@ function registerListBackups(server) {
6678
6679
  }
6679
6680
  //#endregion
6680
6681
  //#region src/mcp/tools/trigger-sync.ts
6681
- const DATA_DIR$5 = process.cwd();
6682
- async function handleTriggerSync(input, dataDir = DATA_DIR$5) {
6682
+ const DATA_DIR$6 = process.cwd();
6683
+ async function handleTriggerSync(input, dataDir = DATA_DIR$6) {
6683
6684
  const auth = getGmailAuth();
6684
6685
  if (!auth) return { content: [{
6685
6686
  type: "text",
@@ -6773,8 +6774,8 @@ Returns: { success: boolean, synced: number, skipped: number, customers: [...],
6773
6774
  }
6774
6775
  //#endregion
6775
6776
  //#region src/mcp/tools/get-audit-log.ts
6776
- const DATA_DIR$4 = process.cwd();
6777
- async function handleGetAuditLog(input, dataDir = DATA_DIR$4) {
6777
+ const DATA_DIR$5 = process.cwd();
6778
+ async function handleGetAuditLog(input, dataDir = DATA_DIR$5) {
6778
6779
  const entries = readAuditLog(dataDir);
6779
6780
  const filterOpts = { limit: input.limit ?? 50 };
6780
6781
  if (input.slug !== void 0) filterOpts.slug = input.slug;
@@ -6816,8 +6817,8 @@ Returns: { total: number, returned: number, entries: [{timestamp, actor, tool, s
6816
6817
  }
6817
6818
  //#endregion
6818
6819
  //#region src/mcp/tools/get-logs.ts
6819
- const DATA_DIR$3 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6820
- async function handleGetLogs(input, dataDir = DATA_DIR$3) {
6820
+ const DATA_DIR$4 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6821
+ async function handleGetLogs(input, dataDir = DATA_DIR$4) {
6821
6822
  const query = {
6822
6823
  ...input.level !== void 0 ? { level: input.level } : {},
6823
6824
  ...input.component !== void 0 ? { component: input.component } : {},
@@ -6979,8 +6980,8 @@ async function runDiagnostics(dataDir) {
6979
6980
  }
6980
6981
  //#endregion
6981
6982
  //#region src/mcp/tools/get-diagnostics.ts
6982
- const DATA_DIR$2 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6983
- async function handleGetDiagnostics(input, dataDir = DATA_DIR$2) {
6983
+ const DATA_DIR$3 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6984
+ async function handleGetDiagnostics(input, dataDir = DATA_DIR$3) {
6984
6985
  let cleaned = 0;
6985
6986
  if (input.fix) {
6986
6987
  const { cleanupTempFiles } = await Promise.resolve().then(() => doctor_exports);
@@ -7012,6 +7013,163 @@ Returns: { ok: boolean, tempFilesRemoved?: number, checks: [{ name, status: "ok"
7012
7013
  }, async ({ fix }) => handleGetDiagnostics(fix !== void 0 ? { fix } : {}));
7013
7014
  }
7014
7015
  //#endregion
7016
+ //#region src/core/snapshots.ts
7017
+ function snapshotsDir(dataDir) {
7018
+ return path.join(dataDir, ".agentic", "snapshots");
7019
+ }
7020
+ function snapshotPath(dataDir, id) {
7021
+ return path.join(snapshotsDir(dataDir), `${id}.json`);
7022
+ }
7023
+ function dealKey(d) {
7024
+ return `${d.slug}::${d.name}`;
7025
+ }
7026
+ function isOpen(stage) {
7027
+ return stage !== "won" && stage !== "lost";
7028
+ }
7029
+ function openValue(deals) {
7030
+ return deals.filter((d) => isOpen(d.stage)).reduce((sum, d) => sum + d.value, 0);
7031
+ }
7032
+ /** Build a live snapshot of the current pipeline across all customers. */
7033
+ function collectDeals(dataDir) {
7034
+ const deals = [];
7035
+ for (const slug of listCustomerSlugs(dataDir)) for (const d of readPipelineSync(dataDir, slug)) deals.push({
7036
+ slug,
7037
+ name: d.name,
7038
+ stage: d.stage,
7039
+ value: d.value ?? 0,
7040
+ probability: d.probability ?? 0
7041
+ });
7042
+ return deals;
7043
+ }
7044
+ function snapshotIds(dataDir) {
7045
+ const dir = snapshotsDir(dataDir);
7046
+ if (!fs.existsSync(dir)) return [];
7047
+ return fs.readdirSync(dir).filter((f) => /^\d{4}-\d{2}-\d{2}\.json$/.test(f)).map((f) => f.replace(/\.json$/, "")).sort();
7048
+ }
7049
+ function loadSnapshot(dataDir, id) {
7050
+ return readJsonFile(snapshotPath(dataDir, id), null);
7051
+ }
7052
+ /** The most recent snapshot whose id is at or before `iso` (YYYY-MM-DD). */
7053
+ function latestSnapshotAtOrBefore(dataDir, iso) {
7054
+ const id = snapshotIds(dataDir).filter((s) => s <= iso).pop();
7055
+ return id ? loadSnapshot(dataDir, id) : null;
7056
+ }
7057
+ /** Compute what changed between two snapshots (before → after). */
7058
+ function diffSnapshots(before, after) {
7059
+ const beforeByKey = new Map(before.deals.map((d) => [dealKey(d), d]));
7060
+ const afterByKey = new Map(after.deals.map((d) => [dealKey(d), d]));
7061
+ const added = [];
7062
+ const removed = [];
7063
+ const advanced = [];
7064
+ const won = [];
7065
+ const lost = [];
7066
+ const valueChanged = [];
7067
+ for (const [key, a] of afterByKey) {
7068
+ const b = beforeByKey.get(key);
7069
+ if (!b) {
7070
+ added.push({
7071
+ slug: a.slug,
7072
+ name: a.name
7073
+ });
7074
+ continue;
7075
+ }
7076
+ if (b.stage !== a.stage) {
7077
+ advanced.push({
7078
+ slug: a.slug,
7079
+ name: a.name,
7080
+ from: b.stage,
7081
+ to: a.stage
7082
+ });
7083
+ if (a.stage === "won") won.push({
7084
+ slug: a.slug,
7085
+ name: a.name
7086
+ });
7087
+ if (a.stage === "lost") lost.push({
7088
+ slug: a.slug,
7089
+ name: a.name
7090
+ });
7091
+ }
7092
+ if (b.value !== a.value) valueChanged.push({
7093
+ slug: a.slug,
7094
+ name: a.name,
7095
+ from: b.value,
7096
+ to: a.value
7097
+ });
7098
+ }
7099
+ for (const [key, b] of beforeByKey) if (!afterByKey.has(key)) removed.push({
7100
+ slug: b.slug,
7101
+ name: b.name
7102
+ });
7103
+ const openValueBefore = openValue(before.deals);
7104
+ const openValueAfter = openValue(after.deals);
7105
+ return {
7106
+ fromId: before.id,
7107
+ toId: after.id,
7108
+ added,
7109
+ removed,
7110
+ advanced,
7111
+ won,
7112
+ lost,
7113
+ valueChanged,
7114
+ openValueBefore,
7115
+ openValueAfter,
7116
+ openValueDelta: openValueAfter - openValueBefore
7117
+ };
7118
+ }
7119
+ /**
7120
+ * Diff the live pipeline against the latest snapshot at/before `since`.
7121
+ * Returns null when no baseline snapshot exists yet.
7122
+ */
7123
+ function diffAgainstNow(dataDir, since, today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)) {
7124
+ const baseline = latestSnapshotAtOrBefore(dataDir, since);
7125
+ if (!baseline) return null;
7126
+ return diffSnapshots(baseline, {
7127
+ id: today,
7128
+ takenAt: (/* @__PURE__ */ new Date()).toISOString(),
7129
+ deals: collectDeals(dataDir)
7130
+ });
7131
+ }
7132
+ //#endregion
7133
+ //#region src/mcp/tools/get-pipeline-changes.ts
7134
+ const DATA_DIR$2 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
7135
+ function daysAgoIso(days) {
7136
+ return (/* @__PURE__ */ new Date(Date.now() - days * 864e5)).toISOString().slice(0, 10);
7137
+ }
7138
+ async function handleGetPipelineChanges(input, dataDir = DATA_DIR$2) {
7139
+ const since = input.since ?? daysAgoIso(input.days ?? 7);
7140
+ const diff = diffAgainstNow(dataDir, since);
7141
+ const payload = diff ? diff : { error: `No pipeline snapshot at or before ${since}. Snapshots accrue daily via the daemon.` };
7142
+ return { content: [{
7143
+ type: "text",
7144
+ text: JSON.stringify(payload, null, 2)
7145
+ }] };
7146
+ }
7147
+ function registerGetPipelineChanges(server) {
7148
+ server.registerTool("get_pipeline_changes", {
7149
+ title: "Get Pipeline Changes",
7150
+ description: `Pipeline time-travel: what changed in the pipeline since a baseline date.
7151
+ Compares the live pipeline against the most recent daily snapshot at/before the
7152
+ baseline. Answers "what moved since last week?", "what did we win/lose?".
7153
+
7154
+ Args:
7155
+ since: Baseline date YYYY-MM-DD (optional)
7156
+ days: Look back this many days instead of a date (default 7)
7157
+
7158
+ Returns: { fromId, toId, added[], removed[], advanced[{from,to}], won[], lost[],
7159
+ valueChanged[{from,to}], openValueBefore, openValueAfter, openValueDelta }
7160
+ or { error } when no baseline snapshot exists yet.`,
7161
+ inputSchema: z.object({
7162
+ since: z.string().optional().describe("Baseline date YYYY-MM-DD"),
7163
+ days: z.number().int().min(1).max(365).optional().describe("Look-back window in days (default 7)")
7164
+ })
7165
+ }, async ({ since, days }) => {
7166
+ const input = {};
7167
+ if (since !== void 0) input.since = since;
7168
+ if (days !== void 0) input.days = days;
7169
+ return handleGetPipelineChanges(input);
7170
+ });
7171
+ }
7172
+ //#endregion
7015
7173
  //#region src/mcp/prompts.ts
7016
7174
  /**
7017
7175
  * CRM playbook prompts exposed via MCP `prompts/list` + `prompts/get`.
@@ -7429,6 +7587,7 @@ function createMcpServer() {
7429
7587
  registerGetAuditLog(server);
7430
7588
  registerGetLogs(server);
7431
7589
  registerGetDiagnostics(server);
7590
+ registerGetPipelineChanges(server);
7432
7591
  registerCustomObjectTools(server);
7433
7592
  registerPrompts(server);
7434
7593
  registerResources(server);