@datasynx/agentic-crm 1.4.0 → 1.6.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.
package/dist/mcp.cjs CHANGED
@@ -451,6 +451,7 @@ Config: \`.agentic/rbac.json\` | Actor: \`DXCRM_ACTOR\` env var
451
451
  | get_audit_log | Read audit log — all write operations with actor, tool, customer | admin |
452
452
  | get_logs | Query/aggregate the structured application log (level, component, errors) | admin |
453
453
  | get_diagnostics | Self-diagnostic health check (data integrity, temp files, log errors, backups) | admin |
454
+ | get_pipeline_changes | Pipeline time-travel: what changed (won/lost/moved/value) since a date | any |
454
455
  | define_custom_object | Define a runtime custom object type with typed fields (no migration) | admin |
455
456
  | create_record | Create a record of a custom object (validated against its schema) | rep+ |
456
457
  | list_records | List records of a custom object | any |
@@ -1429,7 +1430,7 @@ async function buildContext(dataDir, slug) {
1429
1430
  }
1430
1431
  //#endregion
1431
1432
  //#region src/mcp/tools/get-customer-context.ts
1432
- const DATA_DIR$53 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1433
+ const DATA_DIR$54 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1433
1434
  function triggerOnQuerySync(dataDir, slug) {
1434
1435
  const auth = getGmailAuth();
1435
1436
  if (!auth) return;
@@ -1450,7 +1451,7 @@ function triggerOnQuerySync(dataDir, slug) {
1450
1451
  }).then(() => updateSlugSyncState(dataDir, slug, { lastGmailSync: (/* @__PURE__ */ new Date()).toISOString() })).catch(() => {})).catch(() => {});
1451
1452
  } catch {}
1452
1453
  }
1453
- async function handleGetCustomerContext(input, dataDir = DATA_DIR$53) {
1454
+ async function handleGetCustomerContext(input, dataDir = DATA_DIR$54) {
1454
1455
  const targetSlug = input.slug ?? require_session_store.getSession()?.customerSlug;
1455
1456
  if (!targetSlug) return {
1456
1457
  content: [{
@@ -1586,8 +1587,8 @@ async function searchKnowledge(dataDir, slug, query, limit) {
1586
1587
  }
1587
1588
  //#endregion
1588
1589
  //#region src/mcp/tools/search-customer-knowledge.ts
1589
- const DATA_DIR$52 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1590
- async function handleSearchCustomerKnowledge(input, dataDir = DATA_DIR$52) {
1590
+ const DATA_DIR$53 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1591
+ async function handleSearchCustomerKnowledge(input, dataDir = DATA_DIR$53) {
1591
1592
  const limit = input.limit ?? 5;
1592
1593
  try {
1593
1594
  const results = await searchKnowledge(dataDir, input.slug, input.query, limit);
@@ -1635,14 +1636,14 @@ If no results: returns empty array with a helpful sync suggestion.`,
1635
1636
  }
1636
1637
  //#endregion
1637
1638
  //#region src/mcp/tools/list-customers.ts
1638
- const DATA_DIR$51 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1639
+ const DATA_DIR$52 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1639
1640
  function extractLastInteractionDate(interactionsPath) {
1640
1641
  if (!fs.default.existsSync(interactionsPath)) return void 0;
1641
1642
  const content = fs.default.readFileSync(interactionsPath, "utf-8");
1642
1643
  const match = /^## (\d{4}-\d{2}-\d{2})/m.exec(content);
1643
1644
  return match ? match[1] : void 0;
1644
1645
  }
1645
- async function handleListCustomers(input, dataDir = DATA_DIR$51) {
1646
+ async function handleListCustomers(input, dataDir = DATA_DIR$52) {
1646
1647
  const customersDir = path.default.join(dataDir, "customers");
1647
1648
  const customers = [];
1648
1649
  if (!fs.default.existsSync(customersDir)) return { content: [{
@@ -2155,8 +2156,8 @@ async function updateHealthFromInteraction(dataDir, slug) {
2155
2156
  }
2156
2157
  //#endregion
2157
2158
  //#region src/mcp/tools/log-interaction.ts
2158
- const DATA_DIR$50 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2159
- async function handleLogInteraction(input, dataDir = DATA_DIR$50) {
2159
+ const DATA_DIR$51 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2160
+ async function handleLogInteraction(input, dataDir = DATA_DIR$51) {
2160
2161
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
2161
2162
  const interactionDate = input.date ?? today;
2162
2163
  const sourceRef = input.source ?? `agent://log/${Date.now()}`;
@@ -2265,8 +2266,8 @@ var update_deal_exports = /* @__PURE__ */ require_chunk.__exportAll({
2265
2266
  handleUpdateDeal: () => handleUpdateDeal,
2266
2267
  registerUpdateDeal: () => registerUpdateDeal
2267
2268
  });
2268
- const DATA_DIR$49 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2269
- async function handleUpdateDeal(input, dataDir = DATA_DIR$49) {
2269
+ const DATA_DIR$50 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2270
+ async function handleUpdateDeal(input, dataDir = DATA_DIR$50) {
2270
2271
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
2271
2272
  const deal = {
2272
2273
  name: input.dealName,
@@ -2349,12 +2350,12 @@ Returns: { success: boolean, deal: object }`,
2349
2350
  }
2350
2351
  //#endregion
2351
2352
  //#region src/mcp/tools/export-customer.ts
2352
- const DATA_DIR$48 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2353
+ const DATA_DIR$49 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2353
2354
  function countInteractions(content) {
2354
2355
  const matches = content.match(/^## \d{4}-\d{2}-\d{2}/gm);
2355
2356
  return matches ? matches.length : 0;
2356
2357
  }
2357
- async function handleExportCustomer(input, dataDir = DATA_DIR$48) {
2358
+ async function handleExportCustomer(input, dataDir = DATA_DIR$49) {
2358
2359
  require_session_store.enforceRbac(dataDir, "export_customer");
2359
2360
  const customerDir = path.default.join(dataDir, "customers", input.slug);
2360
2361
  if (!fs.default.existsSync(customerDir)) return {
@@ -2467,8 +2468,8 @@ Returns:
2467
2468
  }
2468
2469
  //#endregion
2469
2470
  //#region src/mcp/tools/update-customer-facts.ts
2470
- const DATA_DIR$47 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2471
- async function handleUpdateCustomerFacts(input, dataDir = DATA_DIR$47) {
2471
+ const DATA_DIR$48 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2472
+ async function handleUpdateCustomerFacts(input, dataDir = DATA_DIR$48) {
2472
2473
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
2473
2474
  try {
2474
2475
  require_session_store.enforceRbac(dataDir, "update_customer_facts");
@@ -2646,8 +2647,8 @@ function scoreDealForToday(deal, todayDate) {
2646
2647
  }
2647
2648
  //#endregion
2648
2649
  //#region src/mcp/tools/get-deal-health.ts
2649
- const DATA_DIR$46 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2650
- async function handleGetDealHealth(input, dataDir = DATA_DIR$46) {
2650
+ const DATA_DIR$47 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2651
+ async function handleGetDealHealth(input, dataDir = DATA_DIR$47) {
2651
2652
  try {
2652
2653
  const deals = await require_pipeline_writer.readPipeline(dataDir, input.slug);
2653
2654
  const today = /* @__PURE__ */ new Date();
@@ -2696,8 +2697,8 @@ Returns: { slug, deals: [{ deal, stage, score, grade, signals, warnings }] }`,
2696
2697
  }
2697
2698
  //#endregion
2698
2699
  //#region src/mcp/tools/get-pipeline-forecast.ts
2699
- const DATA_DIR$45 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2700
- async function handleGetPipelineForecast(input, dataDir = DATA_DIR$45) {
2700
+ const DATA_DIR$46 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2701
+ async function handleGetPipelineForecast(input, dataDir = DATA_DIR$46) {
2701
2702
  try {
2702
2703
  const slugs = require_session_store.listCustomerSlugs(dataDir).filter((d) => !input.filter || d.includes(input.filter));
2703
2704
  const allDeals = [];
@@ -2758,8 +2759,8 @@ Returns: { deals: [...], totalWeightedValue: number, byStage: { stage: { count,
2758
2759
  }
2759
2760
  //#endregion
2760
2761
  //#region src/mcp/tools/summarize-meeting.ts
2761
- const DATA_DIR$44 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2762
- async function handleSummarizeMeeting(input, dataDir = DATA_DIR$44) {
2762
+ const DATA_DIR$45 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2763
+ async function handleSummarizeMeeting(input, dataDir = DATA_DIR$45) {
2763
2764
  try {
2764
2765
  let summary = input.transcript.slice(0, 400);
2765
2766
  let nextSteps = [];
@@ -2882,8 +2883,8 @@ function getPipelineStages(dataDir) {
2882
2883
  }
2883
2884
  //#endregion
2884
2885
  //#region src/mcp/tools/get-pipeline-stages.ts
2885
- const DATA_DIR$43 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2886
- async function handleGetPipelineStages(_input, dataDir = DATA_DIR$43) {
2886
+ const DATA_DIR$44 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2887
+ async function handleGetPipelineStages(_input, dataDir = DATA_DIR$44) {
2887
2888
  const stages = getPipelineStages(dataDir);
2888
2889
  return { content: [{
2889
2890
  type: "text",
@@ -2911,8 +2912,8 @@ async function searchAcrossCustomers(dataDir, query, limit = 5, excludeSlug) {
2911
2912
  }
2912
2913
  //#endregion
2913
2914
  //#region src/mcp/tools/get-market-intelligence.ts
2914
- const DATA_DIR$42 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2915
- async function handleGetMarketIntelligence(input, dataDir = DATA_DIR$42) {
2915
+ const DATA_DIR$43 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2916
+ async function handleGetMarketIntelligence(input, dataDir = DATA_DIR$43) {
2916
2917
  const excludeSlug = input.excludeCurrentCustomer ? input.slug : void 0;
2917
2918
  const all = require_session_store.listCustomerSlugs(dataDir);
2918
2919
  const totalCustomersSearched = excludeSlug ? all.filter((s) => s !== excludeSlug).length : all.length;
@@ -2943,7 +2944,7 @@ function registerGetMarketIntelligence(server) {
2943
2944
  }
2944
2945
  //#endregion
2945
2946
  //#region src/mcp/tools/get-relationship-graph.ts
2946
- const DATA_DIR$41 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2947
+ const DATA_DIR$42 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2947
2948
  function summarizeNode(n) {
2948
2949
  return {
2949
2950
  id: n.id,
@@ -2951,7 +2952,7 @@ function summarizeNode(n) {
2951
2952
  email: n.properties["email"]
2952
2953
  };
2953
2954
  }
2954
- async function handleGetRelationshipGraph(input, dataDir = DATA_DIR$41) {
2955
+ async function handleGetRelationshipGraph(input, dataDir = DATA_DIR$42) {
2955
2956
  try {
2956
2957
  const graph = readGraph(dataDir, input.slug);
2957
2958
  const stakeholders = getStakeholders(graph);
@@ -3019,9 +3020,9 @@ Returns: {
3019
3020
  }
3020
3021
  //#endregion
3021
3022
  //#region src/mcp/tools/get-relationship-health.ts
3022
- const DATA_DIR$40 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3023
+ const DATA_DIR$41 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3023
3024
  const MAX_HEALTH_AGE_MS = 3600 * 1e3;
3024
- async function handleGetRelationshipHealth(input, dataDir = DATA_DIR$40) {
3025
+ async function handleGetRelationshipHealth(input, dataDir = DATA_DIR$41) {
3025
3026
  try {
3026
3027
  let health = readHealth(dataDir, input.slug);
3027
3028
  if (health === null || Date.now() - new Date(health.updatedAt).getTime() > MAX_HEALTH_AGE_MS) {
@@ -3690,8 +3691,8 @@ async function runDealAgent(config, dataDir, llmFn = require_llm.callLlm) {
3690
3691
  }
3691
3692
  //#endregion
3692
3693
  //#region src/mcp/tools/run-deal-agent.ts
3693
- const DATA_DIR$39 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3694
- async function handleRunDealAgent(input, dataDir = DATA_DIR$39) {
3694
+ const DATA_DIR$40 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3695
+ async function handleRunDealAgent(input, dataDir = DATA_DIR$40) {
3695
3696
  try {
3696
3697
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
3697
3698
  const result = await runDealAgent({
@@ -3758,8 +3759,8 @@ Returns: { assessment, riskLevel, plan[], actionsQueued[], actionsExecuted[], tr
3758
3759
  }
3759
3760
  //#endregion
3760
3761
  //#region src/mcp/tools/approve-agent-action.ts
3761
- const DATA_DIR$38 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3762
- async function handleApproveAgentAction(input, dataDir = DATA_DIR$38) {
3762
+ const DATA_DIR$39 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3763
+ async function handleApproveAgentAction(input, dataDir = DATA_DIR$39) {
3763
3764
  try {
3764
3765
  const queue = readAgentQueue(dataDir, input.slug);
3765
3766
  const idx = queue.pendingActions.findIndex((a) => a.actionId === input.actionId);
@@ -4019,8 +4020,8 @@ async function buildSimulationInput(dataDir, horizon, today, externalSignals = [
4019
4020
  }
4020
4021
  //#endregion
4021
4022
  //#region src/mcp/tools/simulate-revenue.ts
4022
- const DATA_DIR$37 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4023
- async function handleSimulateRevenue(input, dataDir = DATA_DIR$37) {
4023
+ const DATA_DIR$38 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4024
+ async function handleSimulateRevenue(input, dataDir = DATA_DIR$38) {
4024
4025
  try {
4025
4026
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4026
4027
  const horizon = input.horizon ?? "quarter";
@@ -4078,8 +4079,8 @@ Returns: { forecast: { p10, p50, p90, expected, stdDev, atRiskRevenue, byCloseMo
4078
4079
  }
4079
4080
  //#endregion
4080
4081
  //#region src/mcp/tools/get-playbook.ts
4081
- const DATA_DIR$36 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4082
- async function handleGetPlaybook(input, dataDir = DATA_DIR$36) {
4082
+ const DATA_DIR$37 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4083
+ async function handleGetPlaybook(input, dataDir = DATA_DIR$37) {
4083
4084
  try {
4084
4085
  const playbooks = listPlaybooks(dataDir, input.slug);
4085
4086
  if (!(input.stage !== void 0 || input.value !== void 0 || input.healthScore !== void 0)) return { content: [{
@@ -4164,12 +4165,12 @@ Returns: { matches: [{ name, score, trigger, successRate, usedCount, content }],
4164
4165
  ...healthScore !== void 0 ? { healthScore } : {},
4165
4166
  ...daysSinceContact !== void 0 ? { daysSinceContact } : {},
4166
4167
  ...championPresent !== void 0 ? { championPresent } : {}
4167
- }, DATA_DIR$36));
4168
+ }, DATA_DIR$37));
4168
4169
  }
4169
4170
  //#endregion
4170
4171
  //#region src/mcp/tools/create-playbook.ts
4171
- const DATA_DIR$35 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4172
- async function handleCreatePlaybook(input, dataDir = DATA_DIR$35) {
4172
+ const DATA_DIR$36 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4173
+ async function handleCreatePlaybook(input, dataDir = DATA_DIR$36) {
4173
4174
  try {
4174
4175
  const name = toKebabCase(input.name);
4175
4176
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -4242,12 +4243,12 @@ Returns: { success: true, playbook: { name, trigger, successRate, path } }`,
4242
4243
  trigger,
4243
4244
  content,
4244
4245
  ...successRate !== void 0 ? { successRate } : {}
4245
- }, DATA_DIR$35));
4246
+ }, DATA_DIR$36));
4246
4247
  }
4247
4248
  //#endregion
4248
4249
  //#region src/mcp/tools/list-playbooks.ts
4249
- const DATA_DIR$34 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4250
- async function handleListPlaybooks(input, dataDir = DATA_DIR$34) {
4250
+ const DATA_DIR$35 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4251
+ async function handleListPlaybooks(input, dataDir = DATA_DIR$35) {
4251
4252
  try {
4252
4253
  const playbooks = listPlaybooks(dataDir, input.slug);
4253
4254
  return { content: [{
@@ -4286,12 +4287,12 @@ Args:
4286
4287
 
4287
4288
  Returns: { playbooks: [{ name, trigger, successRate, usedCount, lastUpdated }], count, slug }`,
4288
4289
  inputSchema: zod.z.object({ slug: zod.z.string().describe("Customer ID") })
4289
- }, async ({ slug }) => handleListPlaybooks({ slug }, DATA_DIR$34));
4290
+ }, async ({ slug }) => handleListPlaybooks({ slug }, DATA_DIR$35));
4290
4291
  }
4291
4292
  //#endregion
4292
4293
  //#region src/mcp/tools/distill-playbook.ts
4293
- const DATA_DIR$33 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4294
- async function handleDistillPlaybook(input, dataDir = DATA_DIR$33, llmFn = require_llm.callLlm) {
4294
+ const DATA_DIR$34 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4295
+ async function handleDistillPlaybook(input, dataDir = DATA_DIR$34, llmFn = require_llm.callLlm) {
4295
4296
  try {
4296
4297
  const result = await distillPlaybook(dataDir, input.slug, input.dealName, input.outcome, llmFn);
4297
4298
  if (!result.ok) {
@@ -4350,7 +4351,7 @@ Returns: { success: true, playbook: { name, trigger, successRate, path }, reason
4350
4351
  slug,
4351
4352
  dealName,
4352
4353
  outcome
4353
- }, DATA_DIR$33));
4354
+ }, DATA_DIR$34));
4354
4355
  }
4355
4356
  //#endregion
4356
4357
  //#region src/core/goal-engine.ts
@@ -4568,8 +4569,8 @@ function getActiveGoals(dataDir) {
4568
4569
  }
4569
4570
  //#endregion
4570
4571
  //#region src/mcp/tools/pursue-goal.ts
4571
- const DATA_DIR$32 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4572
- async function handlePursueGoal(input, dataDir = DATA_DIR$32, options = {}) {
4572
+ const DATA_DIR$33 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4573
+ async function handlePursueGoal(input, dataDir = DATA_DIR$33, options = {}) {
4573
4574
  try {
4574
4575
  require_session_store.enforceRbac(dataDir, "pursue_goal");
4575
4576
  const goal = await pursueGoal(dataDir, {
@@ -4632,12 +4633,12 @@ Returns: { goalId, description, target, deadline, decomposition: { analysis, cur
4632
4633
  goal,
4633
4634
  deadline,
4634
4635
  ...context !== void 0 ? { context } : {}
4635
- }, DATA_DIR$32));
4636
+ }, DATA_DIR$33));
4636
4637
  }
4637
4638
  //#endregion
4638
4639
  //#region src/mcp/tools/get-goal-status.ts
4639
- const DATA_DIR$31 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4640
- async function handleGetGoalStatus(input, dataDir = DATA_DIR$31) {
4640
+ const DATA_DIR$32 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4641
+ async function handleGetGoalStatus(input, dataDir = DATA_DIR$32) {
4641
4642
  try {
4642
4643
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4643
4644
  const allGoals = input.goalId ? readGoals(dataDir).filter((g) => g.id === input.goalId) : getActiveGoals(dataDir);
@@ -4696,17 +4697,17 @@ Args:
4696
4697
 
4697
4698
  Returns: { goals: [{ id, description, target, progress, status, deadline, daysRemaining, subGoals }], activeCount, completedCount }`,
4698
4699
  inputSchema: zod.z.object({ goalId: zod.z.string().optional().describe("Specific goal ID (omit for all active goals)") })
4699
- }, async ({ goalId }) => handleGetGoalStatus({ ...goalId !== void 0 ? { goalId } : {} }, DATA_DIR$31));
4700
+ }, async ({ goalId }) => handleGetGoalStatus({ ...goalId !== void 0 ? { goalId } : {} }, DATA_DIR$32));
4700
4701
  }
4701
4702
  //#endregion
4702
4703
  //#region src/mcp/tools/register-push-subscription.ts
4703
- const DATA_DIR$30 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4704
+ const DATA_DIR$31 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4704
4705
  const VALID_PROVIDERS = [
4705
4706
  "gmail",
4706
4707
  "microsoft-graph",
4707
4708
  "slack"
4708
4709
  ];
4709
- async function handleRegisterPushSubscription(input, dataDir = DATA_DIR$30) {
4710
+ async function handleRegisterPushSubscription(input, dataDir = DATA_DIR$31) {
4710
4711
  try {
4711
4712
  if (!VALID_PROVIDERS.includes(input.provider)) return { content: [{
4712
4713
  type: "text",
@@ -4792,12 +4793,12 @@ Returns: { subscriptionId, provider, slug, status, expiresAt, createdAt, warning
4792
4793
  ...microsoftResource !== void 0 ? { microsoftResource } : {},
4793
4794
  ...slackTeamId !== void 0 ? { slackTeamId } : {},
4794
4795
  ...slackChannelId !== void 0 ? { slackChannelId } : {}
4795
- }, DATA_DIR$30));
4796
+ }, DATA_DIR$31));
4796
4797
  }
4797
4798
  //#endregion
4798
4799
  //#region src/mcp/tools/get-push-status.ts
4799
- const DATA_DIR$29 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4800
- async function handleGetPushStatus(input, dataDir = DATA_DIR$29) {
4800
+ const DATA_DIR$30 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4801
+ async function handleGetPushStatus(input, dataDir = DATA_DIR$30) {
4801
4802
  try {
4802
4803
  let subs = await readSubscriptions(dataDir);
4803
4804
  if (input.slug) subs = subs.filter((s) => s.slug === input.slug);
@@ -4869,7 +4870,7 @@ Returns: { subscriptions: [{ id, provider, slug, status, expiresAt, expiresInHou
4869
4870
  }, async ({ slug, provider }) => handleGetPushStatus({
4870
4871
  ...slug !== void 0 ? { slug } : {},
4871
4872
  ...provider !== void 0 ? { provider } : {}
4872
- }, DATA_DIR$29));
4873
+ }, DATA_DIR$30));
4873
4874
  }
4874
4875
  //#endregion
4875
4876
  //#region src/core/org-intelligence.ts
@@ -4935,8 +4936,8 @@ function deriveRecommendation(people, missingRoles) {
4935
4936
  }
4936
4937
  //#endregion
4937
4938
  //#region src/mcp/tools/get-org-intelligence.ts
4938
- const DATA_DIR$28 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4939
- async function handleGetOrgIntelligence(input, dataDir = DATA_DIR$28) {
4939
+ const DATA_DIR$29 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4940
+ async function handleGetOrgIntelligence(input, dataDir = DATA_DIR$29) {
4940
4941
  try {
4941
4942
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4942
4943
  const map = buildStakeholderMap(dataDir, input.slug, today, input.dealName);
@@ -5069,8 +5070,8 @@ function buildExecutiveSummary(slug, dealName, stakeholders, overallHealth, sim,
5069
5070
  }
5070
5071
  //#endregion
5071
5072
  //#region src/mcp/tools/open-deal-room.ts
5072
- const DATA_DIR$27 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5073
- async function handleOpenDealRoom(input, dataDir = DATA_DIR$27) {
5073
+ const DATA_DIR$28 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5074
+ async function handleOpenDealRoom(input, dataDir = DATA_DIR$28) {
5074
5075
  try {
5075
5076
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
5076
5077
  const brief = await buildDealRoom(dataDir, input.slug, input.dealName, today);
@@ -5153,8 +5154,8 @@ async function buildDailyBriefing(dataDir, today) {
5153
5154
  }
5154
5155
  //#endregion
5155
5156
  //#region src/mcp/tools/get-proactive-briefing.ts
5156
- const DATA_DIR$26 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5157
- async function handleGetProactiveBriefing(input, dataDir = DATA_DIR$26) {
5157
+ const DATA_DIR$27 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5158
+ async function handleGetProactiveBriefing(input, dataDir = DATA_DIR$27) {
5158
5159
  try {
5159
5160
  const briefing = await buildDailyBriefing(dataDir, input.date ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10));
5160
5161
  return { content: [{
@@ -5254,15 +5255,15 @@ function getTemplate(dataDir, id) {
5254
5255
  }
5255
5256
  //#endregion
5256
5257
  //#region src/mcp/tools/list-email-templates.ts
5257
- const DATA_DIR$25 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5258
- async function handleListEmailTemplates(input, dataDir = DATA_DIR$25) {
5258
+ const DATA_DIR$26 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5259
+ async function handleListEmailTemplates(input, dataDir = DATA_DIR$26) {
5259
5260
  const summary = listTemplates(dataDir, input.category ? { category: input.category } : {}).map(({ body: _body, ...meta }) => meta);
5260
5261
  return { content: [{
5261
5262
  type: "text",
5262
5263
  text: JSON.stringify(summary, null, 2)
5263
5264
  }] };
5264
5265
  }
5265
- function registerListEmailTemplates(server, dataDir = DATA_DIR$25) {
5266
+ function registerListEmailTemplates(server, dataDir = DATA_DIR$26) {
5266
5267
  server.registerTool("list_email_templates", {
5267
5268
  description: "List available email templates. Optionally filter by category (e.g. 'outreach', 'followup', 'support').",
5268
5269
  inputSchema: zod.z.object({ category: zod.z.string().optional().describe("Filter by category") })
@@ -5296,8 +5297,8 @@ async function buildVariablesFromCustomer(dataDir, slug) {
5296
5297
  }
5297
5298
  //#endregion
5298
5299
  //#region src/mcp/tools/get-email-template.ts
5299
- const DATA_DIR$24 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5300
- async function handleGetEmailTemplate(input, dataDir = DATA_DIR$24) {
5300
+ const DATA_DIR$25 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5301
+ async function handleGetEmailTemplate(input, dataDir = DATA_DIR$25) {
5301
5302
  const tmpl = getTemplate(dataDir, input.id);
5302
5303
  if (!tmpl) return { content: [{
5303
5304
  type: "text",
@@ -5313,7 +5314,7 @@ async function handleGetEmailTemplate(input, dataDir = DATA_DIR$24) {
5313
5314
  }, null, 2)
5314
5315
  }] };
5315
5316
  }
5316
- function registerGetEmailTemplate(server, dataDir = DATA_DIR$24) {
5317
+ function registerGetEmailTemplate(server, dataDir = DATA_DIR$25) {
5317
5318
  server.registerTool("get_email_template", {
5318
5319
  description: "Get a specific email template by ID, including its body and detected variables.",
5319
5320
  inputSchema: zod.z.object({ id: zod.z.string().describe("Template ID (e.g. 'enterprise-intro')") })
@@ -5321,8 +5322,8 @@ function registerGetEmailTemplate(server, dataDir = DATA_DIR$24) {
5321
5322
  }
5322
5323
  //#endregion
5323
5324
  //#region src/mcp/tools/draft-email.ts
5324
- const DATA_DIR$23 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5325
- async function handleDraftEmail(input, dataDir = DATA_DIR$23) {
5325
+ const DATA_DIR$24 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5326
+ async function handleDraftEmail(input, dataDir = DATA_DIR$24) {
5326
5327
  const tmpl = getTemplate(dataDir, input.templateId);
5327
5328
  if (!tmpl) return { content: [{
5328
5329
  type: "text",
@@ -5366,7 +5367,7 @@ async function handleDraftEmail(input, dataDir = DATA_DIR$23) {
5366
5367
  }, null, 2)
5367
5368
  }] };
5368
5369
  }
5369
- function registerDraftEmail(server, dataDir = DATA_DIR$23) {
5370
+ function registerDraftEmail(server, dataDir = DATA_DIR$24) {
5370
5371
  server.registerTool("draft_email", {
5371
5372
  description: `Draft a personalized email for a customer using a stored template.
5372
5373
  Variables are auto-filled from the customer's main_facts.md. Override any variable manually.
@@ -5474,8 +5475,8 @@ async function updateEnrollment(dataDir, id, updates) {
5474
5475
  }
5475
5476
  //#endregion
5476
5477
  //#region src/mcp/tools/enroll-in-sequence.ts
5477
- const DATA_DIR$22 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5478
- async function handleEnrollInSequence(input, dataDir = DATA_DIR$22) {
5478
+ const DATA_DIR$23 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5479
+ async function handleEnrollInSequence(input, dataDir = DATA_DIR$23) {
5479
5480
  const sequence = getSequence(dataDir, input.sequenceId);
5480
5481
  if (!sequence) return { content: [{
5481
5482
  type: "text",
@@ -5507,7 +5508,7 @@ async function handleEnrollInSequence(input, dataDir = DATA_DIR$22) {
5507
5508
  })
5508
5509
  }] };
5509
5510
  }
5510
- function registerEnrollInSequence(server, dataDir = DATA_DIR$22) {
5511
+ function registerEnrollInSequence(server, dataDir = DATA_DIR$23) {
5511
5512
  server.registerTool("enroll_in_sequence", {
5512
5513
  description: `Enroll a contact in an email sequence. Validates that the sequence and its first template exist.
5513
5514
  Returns: { enrollmentId, sequenceName, totalSteps }`,
@@ -5524,8 +5525,8 @@ Returns: { enrollmentId, sequenceName, totalSteps }`,
5524
5525
  }
5525
5526
  //#endregion
5526
5527
  //#region src/mcp/tools/list-sequence-enrollments.ts
5527
- const DATA_DIR$21 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5528
- async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$21) {
5528
+ const DATA_DIR$22 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5529
+ async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$22) {
5529
5530
  let enrollments = readEnrollments(dataDir);
5530
5531
  if (input.slug !== void 0) enrollments = enrollments.filter((e) => e.slug === input.slug);
5531
5532
  if (input.status !== void 0) enrollments = enrollments.filter((e) => e.status === input.status);
@@ -5534,7 +5535,7 @@ async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$21) {
5534
5535
  text: JSON.stringify({ enrollments }, null, 2)
5535
5536
  }] };
5536
5537
  }
5537
- function registerListSequenceEnrollments(server, dataDir = DATA_DIR$21) {
5538
+ function registerListSequenceEnrollments(server, dataDir = DATA_DIR$22) {
5538
5539
  server.registerTool("list_sequence_enrollments", {
5539
5540
  description: `List email sequence enrollments. Filter by customer slug or status.
5540
5541
  Returns: { enrollments: SequenceEnrollment[] }`,
@@ -5553,8 +5554,8 @@ Returns: { enrollments: SequenceEnrollment[] }`,
5553
5554
  }
5554
5555
  //#endregion
5555
5556
  //#region src/mcp/tools/unenroll-from-sequence.ts
5556
- const DATA_DIR$20 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5557
- async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$20) {
5557
+ const DATA_DIR$21 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5558
+ async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$21) {
5558
5559
  if (!await updateEnrollment(dataDir, input.enrollmentId, { status: "paused" })) return { content: [{
5559
5560
  type: "text",
5560
5561
  text: JSON.stringify({
@@ -5567,7 +5568,7 @@ async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$20) {
5567
5568
  text: JSON.stringify({ success: true })
5568
5569
  }] };
5569
5570
  }
5570
- function registerUnenrollFromSequence(server, dataDir = DATA_DIR$20) {
5571
+ function registerUnenrollFromSequence(server, dataDir = DATA_DIR$21) {
5571
5572
  server.registerTool("unenroll_from_sequence", {
5572
5573
  description: `Unenroll (pause) a contact from an email sequence. Sets status to "paused" (soft delete).
5573
5574
  Returns: { success: boolean }`,
@@ -5576,8 +5577,8 @@ Returns: { success: boolean }`,
5576
5577
  }
5577
5578
  //#endregion
5578
5579
  //#region src/mcp/tools/list-sequences.ts
5579
- const DATA_DIR$19 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5580
- async function handleListSequences(_input, dataDir = DATA_DIR$19) {
5580
+ const DATA_DIR$20 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5581
+ async function handleListSequences(_input, dataDir = DATA_DIR$20) {
5581
5582
  const sequences = listSequences(dataDir);
5582
5583
  const enrollments = readEnrollments(dataDir);
5583
5584
  const result = sequences.map((seq) => ({
@@ -5591,7 +5592,7 @@ async function handleListSequences(_input, dataDir = DATA_DIR$19) {
5591
5592
  text: JSON.stringify({ sequences: result }, null, 2)
5592
5593
  }] };
5593
5594
  }
5594
- function registerListSequences(server, dataDir = DATA_DIR$19) {
5595
+ function registerListSequences(server, dataDir = DATA_DIR$20) {
5595
5596
  server.registerTool("list_sequences", {
5596
5597
  description: `List all email sequences with step count and enrollment count.
5597
5598
  Returns: { sequences: Array<{ id, name, stepCount, enrollmentCount }> }`,
@@ -5726,8 +5727,8 @@ async function generateQuote(dataDir, input) {
5726
5727
  }
5727
5728
  //#endregion
5728
5729
  //#region src/mcp/tools/generate-quote.ts
5729
- const DATA_DIR$18 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5730
- async function handleGenerateQuote(input, dataDir = DATA_DIR$18) {
5730
+ const DATA_DIR$19 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5731
+ async function handleGenerateQuote(input, dataDir = DATA_DIR$19) {
5731
5732
  try {
5732
5733
  const quote = await generateQuote(dataDir, input);
5733
5734
  return { content: [{
@@ -5751,7 +5752,7 @@ async function handleGenerateQuote(input, dataDir = DATA_DIR$18) {
5751
5752
  }] };
5752
5753
  }
5753
5754
  }
5754
- function registerGenerateQuote(server, dataDir = DATA_DIR$18) {
5755
+ function registerGenerateQuote(server, dataDir = DATA_DIR$19) {
5755
5756
  server.registerTool("generate_quote", {
5756
5757
  description: `Generate a professional HTML quote/offer for a customer deal.
5757
5758
  Calculates subtotal, VAT, and total. Saves JSON + HTML to .agentic/quotes/.
@@ -5779,8 +5780,8 @@ Returns: { quoteNumber, htmlPath, total, currency, validUntil }`,
5779
5780
  }
5780
5781
  //#endregion
5781
5782
  //#region src/mcp/tools/get-quote-status.ts
5782
- const DATA_DIR$17 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5783
- async function handleGetQuoteStatus(input, dataDir = DATA_DIR$17) {
5783
+ const DATA_DIR$18 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5784
+ async function handleGetQuoteStatus(input, dataDir = DATA_DIR$18) {
5784
5785
  if (input.quoteNumber) {
5785
5786
  const quote = readQuote(dataDir, input.quoteNumber);
5786
5787
  if (!quote) return { content: [{
@@ -5798,7 +5799,7 @@ async function handleGetQuoteStatus(input, dataDir = DATA_DIR$17) {
5798
5799
  text: JSON.stringify({ quotes }, null, 2)
5799
5800
  }] };
5800
5801
  }
5801
- function registerGetQuoteStatus(server, dataDir = DATA_DIR$17) {
5802
+ function registerGetQuoteStatus(server, dataDir = DATA_DIR$18) {
5802
5803
  server.registerTool("get_quote_status", {
5803
5804
  description: `Get quote status and details. Filter by quoteNumber (single quote) or slug (all quotes for a customer).
5804
5805
  Returns quote with status: draft | sent | viewed | accepted | declined`,
@@ -5813,7 +5814,7 @@ Returns quote with status: draft | sent | viewed | accepted | declined`,
5813
5814
  }
5814
5815
  //#endregion
5815
5816
  //#region src/mcp/tools/get-booking-link.ts
5816
- const DATA_DIR$16 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5817
+ const DATA_DIR$17 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5817
5818
  function loadCalendlyConfig(dataDir) {
5818
5819
  const p = path.default.join(dataDir, ".agentic", "integrations", "calendly.yaml");
5819
5820
  if (!fs.default.existsSync(p)) return {};
@@ -5836,7 +5837,7 @@ function readCustomerFacts(dataDir, slug) {
5836
5837
  ...email ? { email } : {}
5837
5838
  };
5838
5839
  }
5839
- async function handleGetBookingLink(input, dataDir = DATA_DIR$16) {
5840
+ async function handleGetBookingLink(input, dataDir = DATA_DIR$17) {
5840
5841
  const config = loadCalendlyConfig(dataDir);
5841
5842
  const apiKey = config.apiKey ?? process.env["CALENDLY_API_KEY"] ?? "";
5842
5843
  if (!apiKey) return { content: [{
@@ -5864,7 +5865,7 @@ async function handleGetBookingLink(input, dataDir = DATA_DIR$16) {
5864
5865
  }] };
5865
5866
  }
5866
5867
  }
5867
- function registerGetBookingLink(server, dataDir = DATA_DIR$16) {
5868
+ function registerGetBookingLink(server, dataDir = DATA_DIR$17) {
5868
5869
  server.registerTool("get_booking_link", {
5869
5870
  description: `Get a Calendly booking link for a customer. Optionally pre-fills the customer's name/email.
5870
5871
  Requires CALENDLY_API_KEY env var or .agentic/integrations/calendly.yaml config.
@@ -6034,8 +6035,8 @@ function calcSlaDue(createdDate, priority, rules) {
6034
6035
  }
6035
6036
  //#endregion
6036
6037
  //#region src/mcp/tools/create-ticket.ts
6037
- const DATA_DIR$15 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6038
- async function handleCreateTicket(input, dataDir = DATA_DIR$15) {
6038
+ const DATA_DIR$16 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6039
+ async function handleCreateTicket(input, dataDir = DATA_DIR$16) {
6039
6040
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
6040
6041
  const rules = loadSlaRules(dataDir);
6041
6042
  const priority = input.priority ?? "normal";
@@ -6057,7 +6058,7 @@ async function handleCreateTicket(input, dataDir = DATA_DIR$15) {
6057
6058
  text: JSON.stringify({ ticket }, null, 2)
6058
6059
  }] };
6059
6060
  }
6060
- function registerCreateTicket(server, dataDir = DATA_DIR$15) {
6061
+ function registerCreateTicket(server, dataDir = DATA_DIR$16) {
6061
6062
  server.registerTool("create_ticket", {
6062
6063
  description: `Create a support ticket for a customer. Auto-calculates SLA due date based on priority.
6063
6064
  Returns: { ticket } with id T-NNN, status=open, slaDue`,
@@ -6083,8 +6084,8 @@ Returns: { ticket } with id T-NNN, status=open, slaDue`,
6083
6084
  }
6084
6085
  //#endregion
6085
6086
  //#region src/mcp/tools/update-ticket.ts
6086
- const DATA_DIR$14 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6087
- async function handleUpdateTicket(input, dataDir = DATA_DIR$14) {
6087
+ const DATA_DIR$15 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6088
+ async function handleUpdateTicket(input, dataDir = DATA_DIR$15) {
6088
6089
  const ticket = (await readTickets(dataDir, input.slug)).find((t) => t.id === input.ticketId);
6089
6090
  if (!ticket) return { content: [{
6090
6091
  type: "text",
@@ -6103,7 +6104,7 @@ async function handleUpdateTicket(input, dataDir = DATA_DIR$14) {
6103
6104
  text: JSON.stringify({ ticket: updated }, null, 2)
6104
6105
  }] };
6105
6106
  }
6106
- function registerUpdateTicket(server, dataDir = DATA_DIR$14) {
6107
+ function registerUpdateTicket(server, dataDir = DATA_DIR$15) {
6107
6108
  server.registerTool("update_ticket", {
6108
6109
  description: `Update a ticket's status or assignee. Setting status=resolved auto-sets resolved date.
6109
6110
  Returns: { ticket }`,
@@ -6128,8 +6129,8 @@ Returns: { ticket }`,
6128
6129
  }
6129
6130
  //#endregion
6130
6131
  //#region src/mcp/tools/list-tickets.ts
6131
- const DATA_DIR$13 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6132
- async function handleListTickets(input, dataDir = DATA_DIR$13) {
6132
+ const DATA_DIR$14 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6133
+ async function handleListTickets(input, dataDir = DATA_DIR$14) {
6133
6134
  const results = await listAllTickets(dataDir, {
6134
6135
  ...input.slug !== void 0 ? { slug: input.slug } : {},
6135
6136
  ...input.status !== void 0 ? { status: input.status } : {},
@@ -6141,7 +6142,7 @@ async function handleListTickets(input, dataDir = DATA_DIR$13) {
6141
6142
  text: JSON.stringify({ tickets: results }, null, 2)
6142
6143
  }] };
6143
6144
  }
6144
- function registerListTickets(server, dataDir = DATA_DIR$13) {
6145
+ function registerListTickets(server, dataDir = DATA_DIR$14) {
6145
6146
  server.registerTool("list_tickets", {
6146
6147
  description: `List support tickets. Filter by customer, status, priority, or assignee. Sorted by priority then date.
6147
6148
  Returns: { tickets: Array<{ slug, ticket }> }`,
@@ -6171,8 +6172,8 @@ Returns: { tickets: Array<{ slug, ticket }> }`,
6171
6172
  }
6172
6173
  //#endregion
6173
6174
  //#region src/mcp/tools/close-ticket.ts
6174
- const DATA_DIR$12 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6175
- async function handleCloseTicket(input, dataDir = DATA_DIR$12) {
6175
+ const DATA_DIR$13 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6176
+ async function handleCloseTicket(input, dataDir = DATA_DIR$13) {
6176
6177
  const ticket = (await readTickets(dataDir, input.slug)).find((t) => t.id === input.ticketId);
6177
6178
  if (!ticket) return { content: [{
6178
6179
  type: "text",
@@ -6199,7 +6200,7 @@ async function handleCloseTicket(input, dataDir = DATA_DIR$12) {
6199
6200
  text: JSON.stringify({ ticket: updated }, null, 2)
6200
6201
  }] };
6201
6202
  }
6202
- function registerCloseTicket(server, dataDir = DATA_DIR$12) {
6203
+ function registerCloseTicket(server, dataDir = DATA_DIR$13) {
6203
6204
  server.registerTool("close_ticket", {
6204
6205
  description: `Close a support ticket. Optionally logs the resolution as an interaction.
6205
6206
  Returns: { ticket } with status=closed`,
@@ -6353,8 +6354,8 @@ async function savePendingSurvey(dataDir, surveyId, slug, contactEmail, token) {
6353
6354
  }
6354
6355
  //#endregion
6355
6356
  //#region src/mcp/tools/send-nps-survey.ts
6356
- const DATA_DIR$11 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6357
- async function handleSendNpsSurvey(input, dataDir = DATA_DIR$11) {
6357
+ const DATA_DIR$12 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6358
+ async function handleSendNpsSurvey(input, dataDir = DATA_DIR$12) {
6358
6359
  const survey = getSurvey(dataDir, input.surveyId);
6359
6360
  if (!survey) return { content: [{
6360
6361
  type: "text",
@@ -6375,7 +6376,7 @@ async function handleSendNpsSurvey(input, dataDir = DATA_DIR$11) {
6375
6376
  }, null, 2)
6376
6377
  }] };
6377
6378
  }
6378
- function registerSendNpsSurvey(server, dataDir = DATA_DIR$11) {
6379
+ function registerSendNpsSurvey(server, dataDir = DATA_DIR$12) {
6379
6380
  server.registerTool("send_nps_survey", {
6380
6381
  description: `Generate an NPS/CSAT survey email for a customer contact. Returns subject, HTML body, and a token-based response URL.
6381
6382
  Does NOT send automatically — returns draft for review.
@@ -6395,8 +6396,8 @@ Returns: { token, subject, body, surveyUrl }`,
6395
6396
  }
6396
6397
  //#endregion
6397
6398
  //#region src/mcp/tools/get-survey-results.ts
6398
- const DATA_DIR$10 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6399
- async function handleGetSurveyResults(input, dataDir = DATA_DIR$10) {
6399
+ const DATA_DIR$11 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6400
+ async function handleGetSurveyResults(input, dataDir = DATA_DIR$11) {
6400
6401
  const responses = loadSurveyResponses(dataDir, input.surveyId, input.slug);
6401
6402
  const nps = calcNpsScore(responses);
6402
6403
  const promoters = responses.filter((r) => r.score >= 9).length;
@@ -6422,7 +6423,7 @@ async function handleGetSurveyResults(input, dataDir = DATA_DIR$10) {
6422
6423
  }, null, 2)
6423
6424
  }] };
6424
6425
  }
6425
- function registerGetSurveyResults(server, dataDir = DATA_DIR$10) {
6426
+ function registerGetSurveyResults(server, dataDir = DATA_DIR$11) {
6426
6427
  server.registerTool("get_survey_results", {
6427
6428
  description: `Get NPS/CSAT survey results with score breakdown. Calculates Net Promoter Score.
6428
6429
  Returns: { npsScore, totalResponses, promoters, passives, detractors, responses[] }`,
@@ -6523,8 +6524,8 @@ function getKbMetaForExport(article) {
6523
6524
  }
6524
6525
  //#endregion
6525
6526
  //#region src/mcp/tools/search-knowledge-base.ts
6526
- const DATA_DIR$9 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6527
- async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$9) {
6527
+ const DATA_DIR$10 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6528
+ async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$10) {
6528
6529
  const results = searchKbSimple(dataDir, input.query, { ...input.publicOnly ? { publicOnly: true } : {} });
6529
6530
  const limited = (input.category ? results.filter((a) => a.category === input.category) : results).slice(0, input.limit ?? 10);
6530
6531
  return { content: [{
@@ -6539,7 +6540,7 @@ async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$9) {
6539
6540
  }, null, 2)
6540
6541
  }] };
6541
6542
  }
6542
- function registerSearchKnowledgeBase(server, dataDir = DATA_DIR$9) {
6543
+ function registerSearchKnowledgeBase(server, dataDir = DATA_DIR$10) {
6543
6544
  server.registerTool("search_knowledge_base", {
6544
6545
  description: `Search the knowledge base for articles. Text search on title, body, and tags.
6545
6546
  Returns: { count, articles[] } with excerpts`,
@@ -6558,8 +6559,8 @@ Returns: { count, articles[] } with excerpts`,
6558
6559
  }
6559
6560
  //#endregion
6560
6561
  //#region src/mcp/tools/create-kb-article.ts
6561
- const DATA_DIR$8 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6562
- async function handleCreateKbArticle(input, dataDir = DATA_DIR$8) {
6562
+ const DATA_DIR$9 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6563
+ async function handleCreateKbArticle(input, dataDir = DATA_DIR$9) {
6563
6564
  if (getKbArticle(dataDir, input.id)) return { content: [{
6564
6565
  type: "text",
6565
6566
  text: JSON.stringify({ error: `Article '${input.id}' already exists` })
@@ -6587,7 +6588,7 @@ async function handleCreateKbArticle(input, dataDir = DATA_DIR$8) {
6587
6588
  }, null, 2)
6588
6589
  }] };
6589
6590
  }
6590
- function registerCreateKbArticle(server, dataDir = DATA_DIR$8) {
6591
+ function registerCreateKbArticle(server, dataDir = DATA_DIR$9) {
6591
6592
  server.registerTool("create_kb_article", {
6592
6593
  description: `Create a new knowledge base article. Articles are stored as Markdown files in .agentic/knowledge-base/.
6593
6594
  Returns: { id, title, category, path }`,
@@ -6612,8 +6613,8 @@ Returns: { id, title, category, path }`,
6612
6613
  }
6613
6614
  //#endregion
6614
6615
  //#region src/mcp/tools/backup-now.ts
6615
- const DATA_DIR$7 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6616
- async function handleBackupNow(input, dataDir = DATA_DIR$7) {
6616
+ const DATA_DIR$8 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6617
+ async function handleBackupNow(input, dataDir = DATA_DIR$8) {
6617
6618
  const zipPath = path.default.join(dataDir, `dxcrm-backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19)}.zip`);
6618
6619
  const manifest = await require_session_store.runBackup(zipPath, dataDir, { ...input.remote ? { remote: input.remote } : {} }).catch(() => null);
6619
6620
  if (!manifest) return { content: [{
@@ -6650,8 +6651,8 @@ function registerBackupNow(server) {
6650
6651
  }
6651
6652
  //#endregion
6652
6653
  //#region src/mcp/tools/list-backups.ts
6653
- const DATA_DIR$6 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6654
- async function handleListBackups(input, dataDir = DATA_DIR$6) {
6654
+ const DATA_DIR$7 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6655
+ async function handleListBackups(input, dataDir = DATA_DIR$7) {
6655
6656
  const logEntries = require_session_store.readBackupLog(dataDir);
6656
6657
  const fileEntries = require_session_store.listBackupsInDir(dataDir);
6657
6658
  const entries = logEntries.length > 0 ? logEntries : fileEntries;
@@ -6685,8 +6686,8 @@ function registerListBackups(server) {
6685
6686
  }
6686
6687
  //#endregion
6687
6688
  //#region src/mcp/tools/trigger-sync.ts
6688
- const DATA_DIR$5 = process.cwd();
6689
- async function handleTriggerSync(input, dataDir = DATA_DIR$5) {
6689
+ const DATA_DIR$6 = process.cwd();
6690
+ async function handleTriggerSync(input, dataDir = DATA_DIR$6) {
6690
6691
  const auth = getGmailAuth();
6691
6692
  if (!auth) return { content: [{
6692
6693
  type: "text",
@@ -6780,8 +6781,8 @@ Returns: { success: boolean, synced: number, skipped: number, customers: [...],
6780
6781
  }
6781
6782
  //#endregion
6782
6783
  //#region src/mcp/tools/get-audit-log.ts
6783
- const DATA_DIR$4 = process.cwd();
6784
- async function handleGetAuditLog(input, dataDir = DATA_DIR$4) {
6784
+ const DATA_DIR$5 = process.cwd();
6785
+ async function handleGetAuditLog(input, dataDir = DATA_DIR$5) {
6785
6786
  const entries = require_session_store.readAuditLog(dataDir);
6786
6787
  const filterOpts = { limit: input.limit ?? 50 };
6787
6788
  if (input.slug !== void 0) filterOpts.slug = input.slug;
@@ -6823,8 +6824,8 @@ Returns: { total: number, returned: number, entries: [{timestamp, actor, tool, s
6823
6824
  }
6824
6825
  //#endregion
6825
6826
  //#region src/mcp/tools/get-logs.ts
6826
- const DATA_DIR$3 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6827
- async function handleGetLogs(input, dataDir = DATA_DIR$3) {
6827
+ const DATA_DIR$4 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6828
+ async function handleGetLogs(input, dataDir = DATA_DIR$4) {
6828
6829
  const query = {
6829
6830
  ...input.level !== void 0 ? { level: input.level } : {},
6830
6831
  ...input.component !== void 0 ? { component: input.component } : {},
@@ -6986,8 +6987,8 @@ async function runDiagnostics(dataDir) {
6986
6987
  }
6987
6988
  //#endregion
6988
6989
  //#region src/mcp/tools/get-diagnostics.ts
6989
- const DATA_DIR$2 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6990
- async function handleGetDiagnostics(input, dataDir = DATA_DIR$2) {
6990
+ const DATA_DIR$3 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6991
+ async function handleGetDiagnostics(input, dataDir = DATA_DIR$3) {
6991
6992
  let cleaned = 0;
6992
6993
  if (input.fix) {
6993
6994
  const { cleanupTempFiles } = await Promise.resolve().then(() => doctor_exports);
@@ -7019,6 +7020,163 @@ Returns: { ok: boolean, tempFilesRemoved?: number, checks: [{ name, status: "ok"
7019
7020
  }, async ({ fix }) => handleGetDiagnostics(fix !== void 0 ? { fix } : {}));
7020
7021
  }
7021
7022
  //#endregion
7023
+ //#region src/core/snapshots.ts
7024
+ function snapshotsDir(dataDir) {
7025
+ return path.default.join(dataDir, ".agentic", "snapshots");
7026
+ }
7027
+ function snapshotPath(dataDir, id) {
7028
+ return path.default.join(snapshotsDir(dataDir), `${id}.json`);
7029
+ }
7030
+ function dealKey(d) {
7031
+ return `${d.slug}::${d.name}`;
7032
+ }
7033
+ function isOpen(stage) {
7034
+ return stage !== "won" && stage !== "lost";
7035
+ }
7036
+ function openValue(deals) {
7037
+ return deals.filter((d) => isOpen(d.stage)).reduce((sum, d) => sum + d.value, 0);
7038
+ }
7039
+ /** Build a live snapshot of the current pipeline across all customers. */
7040
+ function collectDeals(dataDir) {
7041
+ const deals = [];
7042
+ for (const slug of require_session_store.listCustomerSlugs(dataDir)) for (const d of require_pipeline_writer.readPipelineSync(dataDir, slug)) deals.push({
7043
+ slug,
7044
+ name: d.name,
7045
+ stage: d.stage,
7046
+ value: d.value ?? 0,
7047
+ probability: d.probability ?? 0
7048
+ });
7049
+ return deals;
7050
+ }
7051
+ function snapshotIds(dataDir) {
7052
+ const dir = snapshotsDir(dataDir);
7053
+ if (!fs.default.existsSync(dir)) return [];
7054
+ return fs.default.readdirSync(dir).filter((f) => /^\d{4}-\d{2}-\d{2}\.json$/.test(f)).map((f) => f.replace(/\.json$/, "")).sort();
7055
+ }
7056
+ function loadSnapshot(dataDir, id) {
7057
+ return require_session_store.readJsonFile(snapshotPath(dataDir, id), null);
7058
+ }
7059
+ /** The most recent snapshot whose id is at or before `iso` (YYYY-MM-DD). */
7060
+ function latestSnapshotAtOrBefore(dataDir, iso) {
7061
+ const id = snapshotIds(dataDir).filter((s) => s <= iso).pop();
7062
+ return id ? loadSnapshot(dataDir, id) : null;
7063
+ }
7064
+ /** Compute what changed between two snapshots (before → after). */
7065
+ function diffSnapshots(before, after) {
7066
+ const beforeByKey = new Map(before.deals.map((d) => [dealKey(d), d]));
7067
+ const afterByKey = new Map(after.deals.map((d) => [dealKey(d), d]));
7068
+ const added = [];
7069
+ const removed = [];
7070
+ const advanced = [];
7071
+ const won = [];
7072
+ const lost = [];
7073
+ const valueChanged = [];
7074
+ for (const [key, a] of afterByKey) {
7075
+ const b = beforeByKey.get(key);
7076
+ if (!b) {
7077
+ added.push({
7078
+ slug: a.slug,
7079
+ name: a.name
7080
+ });
7081
+ continue;
7082
+ }
7083
+ if (b.stage !== a.stage) {
7084
+ advanced.push({
7085
+ slug: a.slug,
7086
+ name: a.name,
7087
+ from: b.stage,
7088
+ to: a.stage
7089
+ });
7090
+ if (a.stage === "won") won.push({
7091
+ slug: a.slug,
7092
+ name: a.name
7093
+ });
7094
+ if (a.stage === "lost") lost.push({
7095
+ slug: a.slug,
7096
+ name: a.name
7097
+ });
7098
+ }
7099
+ if (b.value !== a.value) valueChanged.push({
7100
+ slug: a.slug,
7101
+ name: a.name,
7102
+ from: b.value,
7103
+ to: a.value
7104
+ });
7105
+ }
7106
+ for (const [key, b] of beforeByKey) if (!afterByKey.has(key)) removed.push({
7107
+ slug: b.slug,
7108
+ name: b.name
7109
+ });
7110
+ const openValueBefore = openValue(before.deals);
7111
+ const openValueAfter = openValue(after.deals);
7112
+ return {
7113
+ fromId: before.id,
7114
+ toId: after.id,
7115
+ added,
7116
+ removed,
7117
+ advanced,
7118
+ won,
7119
+ lost,
7120
+ valueChanged,
7121
+ openValueBefore,
7122
+ openValueAfter,
7123
+ openValueDelta: openValueAfter - openValueBefore
7124
+ };
7125
+ }
7126
+ /**
7127
+ * Diff the live pipeline against the latest snapshot at/before `since`.
7128
+ * Returns null when no baseline snapshot exists yet.
7129
+ */
7130
+ function diffAgainstNow(dataDir, since, today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)) {
7131
+ const baseline = latestSnapshotAtOrBefore(dataDir, since);
7132
+ if (!baseline) return null;
7133
+ return diffSnapshots(baseline, {
7134
+ id: today,
7135
+ takenAt: (/* @__PURE__ */ new Date()).toISOString(),
7136
+ deals: collectDeals(dataDir)
7137
+ });
7138
+ }
7139
+ //#endregion
7140
+ //#region src/mcp/tools/get-pipeline-changes.ts
7141
+ const DATA_DIR$2 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
7142
+ function daysAgoIso(days) {
7143
+ return (/* @__PURE__ */ new Date(Date.now() - days * 864e5)).toISOString().slice(0, 10);
7144
+ }
7145
+ async function handleGetPipelineChanges(input, dataDir = DATA_DIR$2) {
7146
+ const since = input.since ?? daysAgoIso(input.days ?? 7);
7147
+ const diff = diffAgainstNow(dataDir, since);
7148
+ const payload = diff ? diff : { error: `No pipeline snapshot at or before ${since}. Snapshots accrue daily via the daemon.` };
7149
+ return { content: [{
7150
+ type: "text",
7151
+ text: JSON.stringify(payload, null, 2)
7152
+ }] };
7153
+ }
7154
+ function registerGetPipelineChanges(server) {
7155
+ server.registerTool("get_pipeline_changes", {
7156
+ title: "Get Pipeline Changes",
7157
+ description: `Pipeline time-travel: what changed in the pipeline since a baseline date.
7158
+ Compares the live pipeline against the most recent daily snapshot at/before the
7159
+ baseline. Answers "what moved since last week?", "what did we win/lose?".
7160
+
7161
+ Args:
7162
+ since: Baseline date YYYY-MM-DD (optional)
7163
+ days: Look back this many days instead of a date (default 7)
7164
+
7165
+ Returns: { fromId, toId, added[], removed[], advanced[{from,to}], won[], lost[],
7166
+ valueChanged[{from,to}], openValueBefore, openValueAfter, openValueDelta }
7167
+ or { error } when no baseline snapshot exists yet.`,
7168
+ inputSchema: zod.z.object({
7169
+ since: zod.z.string().optional().describe("Baseline date YYYY-MM-DD"),
7170
+ days: zod.z.number().int().min(1).max(365).optional().describe("Look-back window in days (default 7)")
7171
+ })
7172
+ }, async ({ since, days }) => {
7173
+ const input = {};
7174
+ if (since !== void 0) input.since = since;
7175
+ if (days !== void 0) input.days = days;
7176
+ return handleGetPipelineChanges(input);
7177
+ });
7178
+ }
7179
+ //#endregion
7022
7180
  //#region src/mcp/prompts.ts
7023
7181
  /**
7024
7182
  * CRM playbook prompts exposed via MCP `prompts/list` + `prompts/get`.
@@ -7436,6 +7594,7 @@ function createMcpServer() {
7436
7594
  registerGetAuditLog(server);
7437
7595
  registerGetLogs(server);
7438
7596
  registerGetDiagnostics(server);
7597
+ registerGetPipelineChanges(server);
7439
7598
  registerCustomObjectTools(server);
7440
7599
  registerPrompts(server);
7441
7600
  registerResources(server);