@datasynx/agentic-crm 1.8.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/cli.js +71 -8
  2. package/dist/cli.js.map +1 -1
  3. package/dist/daemon/worker.js +3 -3
  4. package/dist/funnel-B2mwpZE1.js +89 -0
  5. package/dist/funnel-B2mwpZE1.js.map +1 -0
  6. package/dist/funnel-CJ7fy7hG.js +2 -0
  7. package/dist/{index-Ewy4f1XW.d.cts → index-BAutNcAT.d.cts} +17 -17
  8. package/dist/index-BAutNcAT.d.cts.map +1 -0
  9. package/dist/{index-DoYT-azq.d.ts → index-BBAlKZg6.d.ts} +8 -8
  10. package/dist/index-BBAlKZg6.d.ts.map +1 -0
  11. package/dist/index.d.cts +17 -17
  12. package/dist/index.d.cts.map +1 -1
  13. package/dist/index.d.ts +8 -8
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/{knowledge-base-Byo0zwM5.js → knowledge-base-yo-BLUcB.js} +2 -1
  16. package/dist/knowledge-base-yo-BLUcB.js.map +1 -0
  17. package/dist/{login-yt9OOQQk.js → login-dc_Hqosw.js} +2 -2
  18. package/dist/{login-yt9OOQQk.js.map → login-dc_Hqosw.js.map} +1 -1
  19. package/dist/mailbox-config-BU3vib2T.js +2 -0
  20. package/dist/{mailbox-config-Dn2xTn9N.js → mailbox-config-trjLPHPG.js} +2 -2
  21. package/dist/{mailbox-config-Dn2xTn9N.js.map → mailbox-config-trjLPHPG.js.map} +1 -1
  22. package/dist/{mailbox-poll-B8dvFAXT.js → mailbox-poll-Ban7C3X0.js} +3 -3
  23. package/dist/{mailbox-poll-B8dvFAXT.js.map → mailbox-poll-Ban7C3X0.js.map} +1 -1
  24. package/dist/mcp-CdTJWTJf.d.cts.map +1 -1
  25. package/dist/mcp-CdTJWTJf.d.ts.map +1 -1
  26. package/dist/mcp.cjs +246 -134
  27. package/dist/mcp.cjs.map +1 -1
  28. package/dist/mcp.d.cts.map +1 -1
  29. package/dist/mcp.d.ts.map +1 -1
  30. package/dist/mcp.js +246 -134
  31. package/dist/mcp.js.map +1 -1
  32. package/dist/{server-C0XkJQBo.js → server-DAcwmRPE.js} +162 -135
  33. package/dist/server-DAcwmRPE.js.map +1 -0
  34. package/dist/{token-resolver-D98qPOOf.js → token-resolver-CL8-CSgZ.js} +2 -2
  35. package/dist/{token-resolver-D98qPOOf.js.map → token-resolver-CL8-CSgZ.js.map} +1 -1
  36. package/dist/{token-store-B0h0USqe.js → token-store-BPDwePNT.js} +13 -2
  37. package/dist/token-store-BPDwePNT.js.map +1 -0
  38. package/dist/token-store-D3HCeXmE.js +2 -0
  39. package/package.json +1 -1
  40. package/dist/index-DoYT-azq.d.ts.map +0 -1
  41. package/dist/index-Ewy4f1XW.d.cts.map +0 -1
  42. package/dist/knowledge-base-Byo0zwM5.js.map +0 -1
  43. package/dist/mailbox-config-Bu-J1O4I.js +0 -2
  44. package/dist/server-C0XkJQBo.js.map +0 -1
  45. package/dist/token-store-B0h0USqe.js.map +0 -1
  46. package/dist/token-store-CEmz8d-0.js +0 -2
package/dist/mcp.cjs CHANGED
@@ -453,6 +453,7 @@ Config: \`.agentic/rbac.json\` | Actor: \`DXCRM_ACTOR\` env var
453
453
  | get_diagnostics | Self-diagnostic health check (data integrity, temp files, log errors, backups) | admin |
454
454
  | get_pipeline_changes | Pipeline time-travel: what changed (won/lost/moved/value) since a date | any |
455
455
  | get_pipeline_velocity | Stage dwell times, sales cycle, and stalled deals from snapshot history | any |
456
+ | get_pipeline_funnel | Conversion funnel & win rate: where deals leak out of the pipeline | any |
456
457
  | define_custom_object | Define a runtime custom object type with typed fields (no migration) | admin |
457
458
  | create_record | Create a record of a custom object (validated against its schema) | rep+ |
458
459
  | list_records | List records of a custom object | any |
@@ -1431,7 +1432,7 @@ async function buildContext(dataDir, slug) {
1431
1432
  }
1432
1433
  //#endregion
1433
1434
  //#region src/mcp/tools/get-customer-context.ts
1434
- const DATA_DIR$55 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1435
+ const DATA_DIR$56 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1435
1436
  function triggerOnQuerySync(dataDir, slug) {
1436
1437
  const auth = getGmailAuth();
1437
1438
  if (!auth) return;
@@ -1452,7 +1453,7 @@ function triggerOnQuerySync(dataDir, slug) {
1452
1453
  }).then(() => updateSlugSyncState(dataDir, slug, { lastGmailSync: (/* @__PURE__ */ new Date()).toISOString() })).catch(() => {})).catch(() => {});
1453
1454
  } catch {}
1454
1455
  }
1455
- async function handleGetCustomerContext(input, dataDir = DATA_DIR$55) {
1456
+ async function handleGetCustomerContext(input, dataDir = DATA_DIR$56) {
1456
1457
  const targetSlug = input.slug ?? require_session_store.getSession()?.customerSlug;
1457
1458
  if (!targetSlug) return {
1458
1459
  content: [{
@@ -1588,8 +1589,8 @@ async function searchKnowledge(dataDir, slug, query, limit) {
1588
1589
  }
1589
1590
  //#endregion
1590
1591
  //#region src/mcp/tools/search-customer-knowledge.ts
1591
- const DATA_DIR$54 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1592
- async function handleSearchCustomerKnowledge(input, dataDir = DATA_DIR$54) {
1592
+ const DATA_DIR$55 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1593
+ async function handleSearchCustomerKnowledge(input, dataDir = DATA_DIR$55) {
1593
1594
  const limit = input.limit ?? 5;
1594
1595
  try {
1595
1596
  const results = await searchKnowledge(dataDir, input.slug, input.query, limit);
@@ -1637,14 +1638,14 @@ If no results: returns empty array with a helpful sync suggestion.`,
1637
1638
  }
1638
1639
  //#endregion
1639
1640
  //#region src/mcp/tools/list-customers.ts
1640
- const DATA_DIR$53 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1641
+ const DATA_DIR$54 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1641
1642
  function extractLastInteractionDate(interactionsPath) {
1642
1643
  if (!fs.default.existsSync(interactionsPath)) return void 0;
1643
1644
  const content = fs.default.readFileSync(interactionsPath, "utf-8");
1644
1645
  const match = /^## (\d{4}-\d{2}-\d{2})/m.exec(content);
1645
1646
  return match ? match[1] : void 0;
1646
1647
  }
1647
- async function handleListCustomers(input, dataDir = DATA_DIR$53) {
1648
+ async function handleListCustomers(input, dataDir = DATA_DIR$54) {
1648
1649
  const customersDir = path.default.join(dataDir, "customers");
1649
1650
  const customers = [];
1650
1651
  if (!fs.default.existsSync(customersDir)) return { content: [{
@@ -2157,8 +2158,8 @@ async function updateHealthFromInteraction(dataDir, slug) {
2157
2158
  }
2158
2159
  //#endregion
2159
2160
  //#region src/mcp/tools/log-interaction.ts
2160
- const DATA_DIR$52 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2161
- async function handleLogInteraction(input, dataDir = DATA_DIR$52) {
2161
+ const DATA_DIR$53 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2162
+ async function handleLogInteraction(input, dataDir = DATA_DIR$53) {
2162
2163
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
2163
2164
  const interactionDate = input.date ?? today;
2164
2165
  const sourceRef = input.source ?? `agent://log/${Date.now()}`;
@@ -2267,8 +2268,8 @@ var update_deal_exports = /* @__PURE__ */ require_chunk.__exportAll({
2267
2268
  handleUpdateDeal: () => handleUpdateDeal,
2268
2269
  registerUpdateDeal: () => registerUpdateDeal
2269
2270
  });
2270
- const DATA_DIR$51 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2271
- async function handleUpdateDeal(input, dataDir = DATA_DIR$51) {
2271
+ const DATA_DIR$52 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2272
+ async function handleUpdateDeal(input, dataDir = DATA_DIR$52) {
2272
2273
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
2273
2274
  const deal = {
2274
2275
  name: input.dealName,
@@ -2351,12 +2352,12 @@ Returns: { success: boolean, deal: object }`,
2351
2352
  }
2352
2353
  //#endregion
2353
2354
  //#region src/mcp/tools/export-customer.ts
2354
- const DATA_DIR$50 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2355
+ const DATA_DIR$51 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2355
2356
  function countInteractions(content) {
2356
2357
  const matches = content.match(/^## \d{4}-\d{2}-\d{2}/gm);
2357
2358
  return matches ? matches.length : 0;
2358
2359
  }
2359
- async function handleExportCustomer(input, dataDir = DATA_DIR$50) {
2360
+ async function handleExportCustomer(input, dataDir = DATA_DIR$51) {
2360
2361
  require_session_store.enforceRbac(dataDir, "export_customer");
2361
2362
  const customerDir = path.default.join(dataDir, "customers", input.slug);
2362
2363
  if (!fs.default.existsSync(customerDir)) return {
@@ -2469,8 +2470,8 @@ Returns:
2469
2470
  }
2470
2471
  //#endregion
2471
2472
  //#region src/mcp/tools/update-customer-facts.ts
2472
- const DATA_DIR$49 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2473
- async function handleUpdateCustomerFacts(input, dataDir = DATA_DIR$49) {
2473
+ const DATA_DIR$50 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2474
+ async function handleUpdateCustomerFacts(input, dataDir = DATA_DIR$50) {
2474
2475
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
2475
2476
  try {
2476
2477
  require_session_store.enforceRbac(dataDir, "update_customer_facts");
@@ -2648,8 +2649,8 @@ function scoreDealForToday(deal, todayDate) {
2648
2649
  }
2649
2650
  //#endregion
2650
2651
  //#region src/mcp/tools/get-deal-health.ts
2651
- const DATA_DIR$48 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2652
- async function handleGetDealHealth(input, dataDir = DATA_DIR$48) {
2652
+ const DATA_DIR$49 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2653
+ async function handleGetDealHealth(input, dataDir = DATA_DIR$49) {
2653
2654
  try {
2654
2655
  const deals = await require_pipeline_writer.readPipeline(dataDir, input.slug);
2655
2656
  const today = /* @__PURE__ */ new Date();
@@ -2698,8 +2699,8 @@ Returns: { slug, deals: [{ deal, stage, score, grade, signals, warnings }] }`,
2698
2699
  }
2699
2700
  //#endregion
2700
2701
  //#region src/mcp/tools/get-pipeline-forecast.ts
2701
- const DATA_DIR$47 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2702
- async function handleGetPipelineForecast(input, dataDir = DATA_DIR$47) {
2702
+ const DATA_DIR$48 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2703
+ async function handleGetPipelineForecast(input, dataDir = DATA_DIR$48) {
2703
2704
  try {
2704
2705
  const slugs = require_session_store.listCustomerSlugs(dataDir).filter((d) => !input.filter || d.includes(input.filter));
2705
2706
  const allDeals = [];
@@ -2760,8 +2761,8 @@ Returns: { deals: [...], totalWeightedValue: number, byStage: { stage: { count,
2760
2761
  }
2761
2762
  //#endregion
2762
2763
  //#region src/mcp/tools/summarize-meeting.ts
2763
- const DATA_DIR$46 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2764
- async function handleSummarizeMeeting(input, dataDir = DATA_DIR$46) {
2764
+ const DATA_DIR$47 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2765
+ async function handleSummarizeMeeting(input, dataDir = DATA_DIR$47) {
2765
2766
  try {
2766
2767
  let summary = input.transcript.slice(0, 400);
2767
2768
  let nextSteps = [];
@@ -2884,8 +2885,8 @@ function getPipelineStages(dataDir) {
2884
2885
  }
2885
2886
  //#endregion
2886
2887
  //#region src/mcp/tools/get-pipeline-stages.ts
2887
- const DATA_DIR$45 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2888
- async function handleGetPipelineStages(_input, dataDir = DATA_DIR$45) {
2888
+ const DATA_DIR$46 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2889
+ async function handleGetPipelineStages(_input, dataDir = DATA_DIR$46) {
2889
2890
  const stages = getPipelineStages(dataDir);
2890
2891
  return { content: [{
2891
2892
  type: "text",
@@ -2913,8 +2914,8 @@ async function searchAcrossCustomers(dataDir, query, limit = 5, excludeSlug) {
2913
2914
  }
2914
2915
  //#endregion
2915
2916
  //#region src/mcp/tools/get-market-intelligence.ts
2916
- const DATA_DIR$44 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2917
- async function handleGetMarketIntelligence(input, dataDir = DATA_DIR$44) {
2917
+ const DATA_DIR$45 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2918
+ async function handleGetMarketIntelligence(input, dataDir = DATA_DIR$45) {
2918
2919
  const excludeSlug = input.excludeCurrentCustomer ? input.slug : void 0;
2919
2920
  const all = require_session_store.listCustomerSlugs(dataDir);
2920
2921
  const totalCustomersSearched = excludeSlug ? all.filter((s) => s !== excludeSlug).length : all.length;
@@ -2945,7 +2946,7 @@ function registerGetMarketIntelligence(server) {
2945
2946
  }
2946
2947
  //#endregion
2947
2948
  //#region src/mcp/tools/get-relationship-graph.ts
2948
- const DATA_DIR$43 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2949
+ const DATA_DIR$44 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2949
2950
  function summarizeNode(n) {
2950
2951
  return {
2951
2952
  id: n.id,
@@ -2953,7 +2954,7 @@ function summarizeNode(n) {
2953
2954
  email: n.properties["email"]
2954
2955
  };
2955
2956
  }
2956
- async function handleGetRelationshipGraph(input, dataDir = DATA_DIR$43) {
2957
+ async function handleGetRelationshipGraph(input, dataDir = DATA_DIR$44) {
2957
2958
  try {
2958
2959
  const graph = readGraph(dataDir, input.slug);
2959
2960
  const stakeholders = getStakeholders(graph);
@@ -3021,9 +3022,9 @@ Returns: {
3021
3022
  }
3022
3023
  //#endregion
3023
3024
  //#region src/mcp/tools/get-relationship-health.ts
3024
- const DATA_DIR$42 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3025
+ const DATA_DIR$43 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3025
3026
  const MAX_HEALTH_AGE_MS = 3600 * 1e3;
3026
- async function handleGetRelationshipHealth(input, dataDir = DATA_DIR$42) {
3027
+ async function handleGetRelationshipHealth(input, dataDir = DATA_DIR$43) {
3027
3028
  try {
3028
3029
  let health = readHealth(dataDir, input.slug);
3029
3030
  if (health === null || Date.now() - new Date(health.updatedAt).getTime() > MAX_HEALTH_AGE_MS) {
@@ -3692,8 +3693,8 @@ async function runDealAgent(config, dataDir, llmFn = require_llm.callLlm) {
3692
3693
  }
3693
3694
  //#endregion
3694
3695
  //#region src/mcp/tools/run-deal-agent.ts
3695
- const DATA_DIR$41 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3696
- async function handleRunDealAgent(input, dataDir = DATA_DIR$41) {
3696
+ const DATA_DIR$42 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3697
+ async function handleRunDealAgent(input, dataDir = DATA_DIR$42) {
3697
3698
  try {
3698
3699
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
3699
3700
  const result = await runDealAgent({
@@ -3760,8 +3761,8 @@ Returns: { assessment, riskLevel, plan[], actionsQueued[], actionsExecuted[], tr
3760
3761
  }
3761
3762
  //#endregion
3762
3763
  //#region src/mcp/tools/approve-agent-action.ts
3763
- const DATA_DIR$40 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3764
- async function handleApproveAgentAction(input, dataDir = DATA_DIR$40) {
3764
+ const DATA_DIR$41 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3765
+ async function handleApproveAgentAction(input, dataDir = DATA_DIR$41) {
3765
3766
  try {
3766
3767
  const queue = readAgentQueue(dataDir, input.slug);
3767
3768
  const idx = queue.pendingActions.findIndex((a) => a.actionId === input.actionId);
@@ -4021,8 +4022,8 @@ async function buildSimulationInput(dataDir, horizon, today, externalSignals = [
4021
4022
  }
4022
4023
  //#endregion
4023
4024
  //#region src/mcp/tools/simulate-revenue.ts
4024
- const DATA_DIR$39 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4025
- async function handleSimulateRevenue(input, dataDir = DATA_DIR$39) {
4025
+ const DATA_DIR$40 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4026
+ async function handleSimulateRevenue(input, dataDir = DATA_DIR$40) {
4026
4027
  try {
4027
4028
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4028
4029
  const horizon = input.horizon ?? "quarter";
@@ -4080,8 +4081,8 @@ Returns: { forecast: { p10, p50, p90, expected, stdDev, atRiskRevenue, byCloseMo
4080
4081
  }
4081
4082
  //#endregion
4082
4083
  //#region src/mcp/tools/get-playbook.ts
4083
- const DATA_DIR$38 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4084
- async function handleGetPlaybook(input, dataDir = DATA_DIR$38) {
4084
+ const DATA_DIR$39 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4085
+ async function handleGetPlaybook(input, dataDir = DATA_DIR$39) {
4085
4086
  try {
4086
4087
  const playbooks = listPlaybooks(dataDir, input.slug);
4087
4088
  if (!(input.stage !== void 0 || input.value !== void 0 || input.healthScore !== void 0)) return { content: [{
@@ -4166,12 +4167,12 @@ Returns: { matches: [{ name, score, trigger, successRate, usedCount, content }],
4166
4167
  ...healthScore !== void 0 ? { healthScore } : {},
4167
4168
  ...daysSinceContact !== void 0 ? { daysSinceContact } : {},
4168
4169
  ...championPresent !== void 0 ? { championPresent } : {}
4169
- }, DATA_DIR$38));
4170
+ }, DATA_DIR$39));
4170
4171
  }
4171
4172
  //#endregion
4172
4173
  //#region src/mcp/tools/create-playbook.ts
4173
- const DATA_DIR$37 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4174
- async function handleCreatePlaybook(input, dataDir = DATA_DIR$37) {
4174
+ const DATA_DIR$38 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4175
+ async function handleCreatePlaybook(input, dataDir = DATA_DIR$38) {
4175
4176
  try {
4176
4177
  const name = toKebabCase(input.name);
4177
4178
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -4244,12 +4245,12 @@ Returns: { success: true, playbook: { name, trigger, successRate, path } }`,
4244
4245
  trigger,
4245
4246
  content,
4246
4247
  ...successRate !== void 0 ? { successRate } : {}
4247
- }, DATA_DIR$37));
4248
+ }, DATA_DIR$38));
4248
4249
  }
4249
4250
  //#endregion
4250
4251
  //#region src/mcp/tools/list-playbooks.ts
4251
- const DATA_DIR$36 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4252
- async function handleListPlaybooks(input, dataDir = DATA_DIR$36) {
4252
+ const DATA_DIR$37 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4253
+ async function handleListPlaybooks(input, dataDir = DATA_DIR$37) {
4253
4254
  try {
4254
4255
  const playbooks = listPlaybooks(dataDir, input.slug);
4255
4256
  return { content: [{
@@ -4288,12 +4289,12 @@ Args:
4288
4289
 
4289
4290
  Returns: { playbooks: [{ name, trigger, successRate, usedCount, lastUpdated }], count, slug }`,
4290
4291
  inputSchema: zod.z.object({ slug: zod.z.string().describe("Customer ID") })
4291
- }, async ({ slug }) => handleListPlaybooks({ slug }, DATA_DIR$36));
4292
+ }, async ({ slug }) => handleListPlaybooks({ slug }, DATA_DIR$37));
4292
4293
  }
4293
4294
  //#endregion
4294
4295
  //#region src/mcp/tools/distill-playbook.ts
4295
- const DATA_DIR$35 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4296
- async function handleDistillPlaybook(input, dataDir = DATA_DIR$35, llmFn = require_llm.callLlm) {
4296
+ const DATA_DIR$36 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4297
+ async function handleDistillPlaybook(input, dataDir = DATA_DIR$36, llmFn = require_llm.callLlm) {
4297
4298
  try {
4298
4299
  const result = await distillPlaybook(dataDir, input.slug, input.dealName, input.outcome, llmFn);
4299
4300
  if (!result.ok) {
@@ -4352,7 +4353,7 @@ Returns: { success: true, playbook: { name, trigger, successRate, path }, reason
4352
4353
  slug,
4353
4354
  dealName,
4354
4355
  outcome
4355
- }, DATA_DIR$35));
4356
+ }, DATA_DIR$36));
4356
4357
  }
4357
4358
  //#endregion
4358
4359
  //#region src/core/goal-engine.ts
@@ -4570,8 +4571,8 @@ function getActiveGoals(dataDir) {
4570
4571
  }
4571
4572
  //#endregion
4572
4573
  //#region src/mcp/tools/pursue-goal.ts
4573
- const DATA_DIR$34 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4574
- async function handlePursueGoal(input, dataDir = DATA_DIR$34, options = {}) {
4574
+ const DATA_DIR$35 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4575
+ async function handlePursueGoal(input, dataDir = DATA_DIR$35, options = {}) {
4575
4576
  try {
4576
4577
  require_session_store.enforceRbac(dataDir, "pursue_goal");
4577
4578
  const goal = await pursueGoal(dataDir, {
@@ -4634,12 +4635,12 @@ Returns: { goalId, description, target, deadline, decomposition: { analysis, cur
4634
4635
  goal,
4635
4636
  deadline,
4636
4637
  ...context !== void 0 ? { context } : {}
4637
- }, DATA_DIR$34));
4638
+ }, DATA_DIR$35));
4638
4639
  }
4639
4640
  //#endregion
4640
4641
  //#region src/mcp/tools/get-goal-status.ts
4641
- const DATA_DIR$33 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4642
- async function handleGetGoalStatus(input, dataDir = DATA_DIR$33) {
4642
+ const DATA_DIR$34 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4643
+ async function handleGetGoalStatus(input, dataDir = DATA_DIR$34) {
4643
4644
  try {
4644
4645
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4645
4646
  const allGoals = input.goalId ? readGoals(dataDir).filter((g) => g.id === input.goalId) : getActiveGoals(dataDir);
@@ -4698,17 +4699,17 @@ Args:
4698
4699
 
4699
4700
  Returns: { goals: [{ id, description, target, progress, status, deadline, daysRemaining, subGoals }], activeCount, completedCount }`,
4700
4701
  inputSchema: zod.z.object({ goalId: zod.z.string().optional().describe("Specific goal ID (omit for all active goals)") })
4701
- }, async ({ goalId }) => handleGetGoalStatus({ ...goalId !== void 0 ? { goalId } : {} }, DATA_DIR$33));
4702
+ }, async ({ goalId }) => handleGetGoalStatus({ ...goalId !== void 0 ? { goalId } : {} }, DATA_DIR$34));
4702
4703
  }
4703
4704
  //#endregion
4704
4705
  //#region src/mcp/tools/register-push-subscription.ts
4705
- const DATA_DIR$32 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4706
+ const DATA_DIR$33 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4706
4707
  const VALID_PROVIDERS = [
4707
4708
  "gmail",
4708
4709
  "microsoft-graph",
4709
4710
  "slack"
4710
4711
  ];
4711
- async function handleRegisterPushSubscription(input, dataDir = DATA_DIR$32) {
4712
+ async function handleRegisterPushSubscription(input, dataDir = DATA_DIR$33) {
4712
4713
  try {
4713
4714
  if (!VALID_PROVIDERS.includes(input.provider)) return { content: [{
4714
4715
  type: "text",
@@ -4794,12 +4795,12 @@ Returns: { subscriptionId, provider, slug, status, expiresAt, createdAt, warning
4794
4795
  ...microsoftResource !== void 0 ? { microsoftResource } : {},
4795
4796
  ...slackTeamId !== void 0 ? { slackTeamId } : {},
4796
4797
  ...slackChannelId !== void 0 ? { slackChannelId } : {}
4797
- }, DATA_DIR$32));
4798
+ }, DATA_DIR$33));
4798
4799
  }
4799
4800
  //#endregion
4800
4801
  //#region src/mcp/tools/get-push-status.ts
4801
- const DATA_DIR$31 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4802
- async function handleGetPushStatus(input, dataDir = DATA_DIR$31) {
4802
+ const DATA_DIR$32 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4803
+ async function handleGetPushStatus(input, dataDir = DATA_DIR$32) {
4803
4804
  try {
4804
4805
  let subs = await readSubscriptions(dataDir);
4805
4806
  if (input.slug) subs = subs.filter((s) => s.slug === input.slug);
@@ -4871,7 +4872,7 @@ Returns: { subscriptions: [{ id, provider, slug, status, expiresAt, expiresInHou
4871
4872
  }, async ({ slug, provider }) => handleGetPushStatus({
4872
4873
  ...slug !== void 0 ? { slug } : {},
4873
4874
  ...provider !== void 0 ? { provider } : {}
4874
- }, DATA_DIR$31));
4875
+ }, DATA_DIR$32));
4875
4876
  }
4876
4877
  //#endregion
4877
4878
  //#region src/core/org-intelligence.ts
@@ -4937,8 +4938,8 @@ function deriveRecommendation(people, missingRoles) {
4937
4938
  }
4938
4939
  //#endregion
4939
4940
  //#region src/mcp/tools/get-org-intelligence.ts
4940
- const DATA_DIR$30 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4941
- async function handleGetOrgIntelligence(input, dataDir = DATA_DIR$30) {
4941
+ const DATA_DIR$31 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4942
+ async function handleGetOrgIntelligence(input, dataDir = DATA_DIR$31) {
4942
4943
  try {
4943
4944
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4944
4945
  const map = buildStakeholderMap(dataDir, input.slug, today, input.dealName);
@@ -5071,8 +5072,8 @@ function buildExecutiveSummary(slug, dealName, stakeholders, overallHealth, sim,
5071
5072
  }
5072
5073
  //#endregion
5073
5074
  //#region src/mcp/tools/open-deal-room.ts
5074
- const DATA_DIR$29 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5075
- async function handleOpenDealRoom(input, dataDir = DATA_DIR$29) {
5075
+ const DATA_DIR$30 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5076
+ async function handleOpenDealRoom(input, dataDir = DATA_DIR$30) {
5076
5077
  try {
5077
5078
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
5078
5079
  const brief = await buildDealRoom(dataDir, input.slug, input.dealName, today);
@@ -5155,8 +5156,8 @@ async function buildDailyBriefing(dataDir, today) {
5155
5156
  }
5156
5157
  //#endregion
5157
5158
  //#region src/mcp/tools/get-proactive-briefing.ts
5158
- const DATA_DIR$28 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5159
- async function handleGetProactiveBriefing(input, dataDir = DATA_DIR$28) {
5159
+ const DATA_DIR$29 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5160
+ async function handleGetProactiveBriefing(input, dataDir = DATA_DIR$29) {
5160
5161
  try {
5161
5162
  const briefing = await buildDailyBriefing(dataDir, input.date ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10));
5162
5163
  return { content: [{
@@ -5256,15 +5257,15 @@ function getTemplate(dataDir, id) {
5256
5257
  }
5257
5258
  //#endregion
5258
5259
  //#region src/mcp/tools/list-email-templates.ts
5259
- const DATA_DIR$27 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5260
- async function handleListEmailTemplates(input, dataDir = DATA_DIR$27) {
5260
+ const DATA_DIR$28 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5261
+ async function handleListEmailTemplates(input, dataDir = DATA_DIR$28) {
5261
5262
  const summary = listTemplates(dataDir, input.category ? { category: input.category } : {}).map(({ body: _body, ...meta }) => meta);
5262
5263
  return { content: [{
5263
5264
  type: "text",
5264
5265
  text: JSON.stringify(summary, null, 2)
5265
5266
  }] };
5266
5267
  }
5267
- function registerListEmailTemplates(server, dataDir = DATA_DIR$27) {
5268
+ function registerListEmailTemplates(server, dataDir = DATA_DIR$28) {
5268
5269
  server.registerTool("list_email_templates", {
5269
5270
  description: "List available email templates. Optionally filter by category (e.g. 'outreach', 'followup', 'support').",
5270
5271
  inputSchema: zod.z.object({ category: zod.z.string().optional().describe("Filter by category") })
@@ -5298,8 +5299,8 @@ async function buildVariablesFromCustomer(dataDir, slug) {
5298
5299
  }
5299
5300
  //#endregion
5300
5301
  //#region src/mcp/tools/get-email-template.ts
5301
- const DATA_DIR$26 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5302
- async function handleGetEmailTemplate(input, dataDir = DATA_DIR$26) {
5302
+ const DATA_DIR$27 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5303
+ async function handleGetEmailTemplate(input, dataDir = DATA_DIR$27) {
5303
5304
  const tmpl = getTemplate(dataDir, input.id);
5304
5305
  if (!tmpl) return { content: [{
5305
5306
  type: "text",
@@ -5315,7 +5316,7 @@ async function handleGetEmailTemplate(input, dataDir = DATA_DIR$26) {
5315
5316
  }, null, 2)
5316
5317
  }] };
5317
5318
  }
5318
- function registerGetEmailTemplate(server, dataDir = DATA_DIR$26) {
5319
+ function registerGetEmailTemplate(server, dataDir = DATA_DIR$27) {
5319
5320
  server.registerTool("get_email_template", {
5320
5321
  description: "Get a specific email template by ID, including its body and detected variables.",
5321
5322
  inputSchema: zod.z.object({ id: zod.z.string().describe("Template ID (e.g. 'enterprise-intro')") })
@@ -5323,8 +5324,8 @@ function registerGetEmailTemplate(server, dataDir = DATA_DIR$26) {
5323
5324
  }
5324
5325
  //#endregion
5325
5326
  //#region src/mcp/tools/draft-email.ts
5326
- const DATA_DIR$25 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5327
- async function handleDraftEmail(input, dataDir = DATA_DIR$25) {
5327
+ const DATA_DIR$26 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5328
+ async function handleDraftEmail(input, dataDir = DATA_DIR$26) {
5328
5329
  const tmpl = getTemplate(dataDir, input.templateId);
5329
5330
  if (!tmpl) return { content: [{
5330
5331
  type: "text",
@@ -5368,7 +5369,7 @@ async function handleDraftEmail(input, dataDir = DATA_DIR$25) {
5368
5369
  }, null, 2)
5369
5370
  }] };
5370
5371
  }
5371
- function registerDraftEmail(server, dataDir = DATA_DIR$25) {
5372
+ function registerDraftEmail(server, dataDir = DATA_DIR$26) {
5372
5373
  server.registerTool("draft_email", {
5373
5374
  description: `Draft a personalized email for a customer using a stored template.
5374
5375
  Variables are auto-filled from the customer's main_facts.md. Override any variable manually.
@@ -5476,8 +5477,8 @@ async function updateEnrollment(dataDir, id, updates) {
5476
5477
  }
5477
5478
  //#endregion
5478
5479
  //#region src/mcp/tools/enroll-in-sequence.ts
5479
- const DATA_DIR$24 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5480
- async function handleEnrollInSequence(input, dataDir = DATA_DIR$24) {
5480
+ const DATA_DIR$25 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5481
+ async function handleEnrollInSequence(input, dataDir = DATA_DIR$25) {
5481
5482
  const sequence = getSequence(dataDir, input.sequenceId);
5482
5483
  if (!sequence) return { content: [{
5483
5484
  type: "text",
@@ -5509,7 +5510,7 @@ async function handleEnrollInSequence(input, dataDir = DATA_DIR$24) {
5509
5510
  })
5510
5511
  }] };
5511
5512
  }
5512
- function registerEnrollInSequence(server, dataDir = DATA_DIR$24) {
5513
+ function registerEnrollInSequence(server, dataDir = DATA_DIR$25) {
5513
5514
  server.registerTool("enroll_in_sequence", {
5514
5515
  description: `Enroll a contact in an email sequence. Validates that the sequence and its first template exist.
5515
5516
  Returns: { enrollmentId, sequenceName, totalSteps }`,
@@ -5526,8 +5527,8 @@ Returns: { enrollmentId, sequenceName, totalSteps }`,
5526
5527
  }
5527
5528
  //#endregion
5528
5529
  //#region src/mcp/tools/list-sequence-enrollments.ts
5529
- const DATA_DIR$23 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5530
- async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$23) {
5530
+ const DATA_DIR$24 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5531
+ async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$24) {
5531
5532
  let enrollments = readEnrollments(dataDir);
5532
5533
  if (input.slug !== void 0) enrollments = enrollments.filter((e) => e.slug === input.slug);
5533
5534
  if (input.status !== void 0) enrollments = enrollments.filter((e) => e.status === input.status);
@@ -5536,7 +5537,7 @@ async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$23) {
5536
5537
  text: JSON.stringify({ enrollments }, null, 2)
5537
5538
  }] };
5538
5539
  }
5539
- function registerListSequenceEnrollments(server, dataDir = DATA_DIR$23) {
5540
+ function registerListSequenceEnrollments(server, dataDir = DATA_DIR$24) {
5540
5541
  server.registerTool("list_sequence_enrollments", {
5541
5542
  description: `List email sequence enrollments. Filter by customer slug or status.
5542
5543
  Returns: { enrollments: SequenceEnrollment[] }`,
@@ -5555,8 +5556,8 @@ Returns: { enrollments: SequenceEnrollment[] }`,
5555
5556
  }
5556
5557
  //#endregion
5557
5558
  //#region src/mcp/tools/unenroll-from-sequence.ts
5558
- const DATA_DIR$22 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5559
- async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$22) {
5559
+ const DATA_DIR$23 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5560
+ async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$23) {
5560
5561
  if (!await updateEnrollment(dataDir, input.enrollmentId, { status: "paused" })) return { content: [{
5561
5562
  type: "text",
5562
5563
  text: JSON.stringify({
@@ -5569,7 +5570,7 @@ async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$22) {
5569
5570
  text: JSON.stringify({ success: true })
5570
5571
  }] };
5571
5572
  }
5572
- function registerUnenrollFromSequence(server, dataDir = DATA_DIR$22) {
5573
+ function registerUnenrollFromSequence(server, dataDir = DATA_DIR$23) {
5573
5574
  server.registerTool("unenroll_from_sequence", {
5574
5575
  description: `Unenroll (pause) a contact from an email sequence. Sets status to "paused" (soft delete).
5575
5576
  Returns: { success: boolean }`,
@@ -5578,8 +5579,8 @@ Returns: { success: boolean }`,
5578
5579
  }
5579
5580
  //#endregion
5580
5581
  //#region src/mcp/tools/list-sequences.ts
5581
- const DATA_DIR$21 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5582
- async function handleListSequences(_input, dataDir = DATA_DIR$21) {
5582
+ const DATA_DIR$22 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5583
+ async function handleListSequences(_input, dataDir = DATA_DIR$22) {
5583
5584
  const sequences = listSequences(dataDir);
5584
5585
  const enrollments = readEnrollments(dataDir);
5585
5586
  const result = sequences.map((seq) => ({
@@ -5593,7 +5594,7 @@ async function handleListSequences(_input, dataDir = DATA_DIR$21) {
5593
5594
  text: JSON.stringify({ sequences: result }, null, 2)
5594
5595
  }] };
5595
5596
  }
5596
- function registerListSequences(server, dataDir = DATA_DIR$21) {
5597
+ function registerListSequences(server, dataDir = DATA_DIR$22) {
5597
5598
  server.registerTool("list_sequences", {
5598
5599
  description: `List all email sequences with step count and enrollment count.
5599
5600
  Returns: { sequences: Array<{ id, name, stepCount, enrollmentCount }> }`,
@@ -5728,8 +5729,8 @@ async function generateQuote(dataDir, input) {
5728
5729
  }
5729
5730
  //#endregion
5730
5731
  //#region src/mcp/tools/generate-quote.ts
5731
- const DATA_DIR$20 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5732
- async function handleGenerateQuote(input, dataDir = DATA_DIR$20) {
5732
+ const DATA_DIR$21 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5733
+ async function handleGenerateQuote(input, dataDir = DATA_DIR$21) {
5733
5734
  try {
5734
5735
  const quote = await generateQuote(dataDir, input);
5735
5736
  return { content: [{
@@ -5753,7 +5754,7 @@ async function handleGenerateQuote(input, dataDir = DATA_DIR$20) {
5753
5754
  }] };
5754
5755
  }
5755
5756
  }
5756
- function registerGenerateQuote(server, dataDir = DATA_DIR$20) {
5757
+ function registerGenerateQuote(server, dataDir = DATA_DIR$21) {
5757
5758
  server.registerTool("generate_quote", {
5758
5759
  description: `Generate a professional HTML quote/offer for a customer deal.
5759
5760
  Calculates subtotal, VAT, and total. Saves JSON + HTML to .agentic/quotes/.
@@ -5781,8 +5782,8 @@ Returns: { quoteNumber, htmlPath, total, currency, validUntil }`,
5781
5782
  }
5782
5783
  //#endregion
5783
5784
  //#region src/mcp/tools/get-quote-status.ts
5784
- const DATA_DIR$19 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5785
- async function handleGetQuoteStatus(input, dataDir = DATA_DIR$19) {
5785
+ const DATA_DIR$20 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5786
+ async function handleGetQuoteStatus(input, dataDir = DATA_DIR$20) {
5786
5787
  if (input.quoteNumber) {
5787
5788
  const quote = readQuote(dataDir, input.quoteNumber);
5788
5789
  if (!quote) return { content: [{
@@ -5800,7 +5801,7 @@ async function handleGetQuoteStatus(input, dataDir = DATA_DIR$19) {
5800
5801
  text: JSON.stringify({ quotes }, null, 2)
5801
5802
  }] };
5802
5803
  }
5803
- function registerGetQuoteStatus(server, dataDir = DATA_DIR$19) {
5804
+ function registerGetQuoteStatus(server, dataDir = DATA_DIR$20) {
5804
5805
  server.registerTool("get_quote_status", {
5805
5806
  description: `Get quote status and details. Filter by quoteNumber (single quote) or slug (all quotes for a customer).
5806
5807
  Returns quote with status: draft | sent | viewed | accepted | declined`,
@@ -5815,7 +5816,7 @@ Returns quote with status: draft | sent | viewed | accepted | declined`,
5815
5816
  }
5816
5817
  //#endregion
5817
5818
  //#region src/mcp/tools/get-booking-link.ts
5818
- const DATA_DIR$18 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5819
+ const DATA_DIR$19 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
5819
5820
  function loadCalendlyConfig(dataDir) {
5820
5821
  const p = path.default.join(dataDir, ".agentic", "integrations", "calendly.yaml");
5821
5822
  if (!fs.default.existsSync(p)) return {};
@@ -5838,7 +5839,7 @@ function readCustomerFacts(dataDir, slug) {
5838
5839
  ...email ? { email } : {}
5839
5840
  };
5840
5841
  }
5841
- async function handleGetBookingLink(input, dataDir = DATA_DIR$18) {
5842
+ async function handleGetBookingLink(input, dataDir = DATA_DIR$19) {
5842
5843
  const config = loadCalendlyConfig(dataDir);
5843
5844
  const apiKey = config.apiKey ?? process.env["CALENDLY_API_KEY"] ?? "";
5844
5845
  if (!apiKey) return { content: [{
@@ -5866,7 +5867,7 @@ async function handleGetBookingLink(input, dataDir = DATA_DIR$18) {
5866
5867
  }] };
5867
5868
  }
5868
5869
  }
5869
- function registerGetBookingLink(server, dataDir = DATA_DIR$18) {
5870
+ function registerGetBookingLink(server, dataDir = DATA_DIR$19) {
5870
5871
  server.registerTool("get_booking_link", {
5871
5872
  description: `Get a Calendly booking link for a customer. Optionally pre-fills the customer's name/email.
5872
5873
  Requires CALENDLY_API_KEY env var or .agentic/integrations/calendly.yaml config.
@@ -6036,8 +6037,8 @@ function calcSlaDue(createdDate, priority, rules) {
6036
6037
  }
6037
6038
  //#endregion
6038
6039
  //#region src/mcp/tools/create-ticket.ts
6039
- const DATA_DIR$17 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6040
- async function handleCreateTicket(input, dataDir = DATA_DIR$17) {
6040
+ const DATA_DIR$18 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6041
+ async function handleCreateTicket(input, dataDir = DATA_DIR$18) {
6041
6042
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
6042
6043
  const rules = loadSlaRules(dataDir);
6043
6044
  const priority = input.priority ?? "normal";
@@ -6059,7 +6060,7 @@ async function handleCreateTicket(input, dataDir = DATA_DIR$17) {
6059
6060
  text: JSON.stringify({ ticket }, null, 2)
6060
6061
  }] };
6061
6062
  }
6062
- function registerCreateTicket(server, dataDir = DATA_DIR$17) {
6063
+ function registerCreateTicket(server, dataDir = DATA_DIR$18) {
6063
6064
  server.registerTool("create_ticket", {
6064
6065
  description: `Create a support ticket for a customer. Auto-calculates SLA due date based on priority.
6065
6066
  Returns: { ticket } with id T-NNN, status=open, slaDue`,
@@ -6085,8 +6086,8 @@ Returns: { ticket } with id T-NNN, status=open, slaDue`,
6085
6086
  }
6086
6087
  //#endregion
6087
6088
  //#region src/mcp/tools/update-ticket.ts
6088
- const DATA_DIR$16 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6089
- async function handleUpdateTicket(input, dataDir = DATA_DIR$16) {
6089
+ const DATA_DIR$17 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6090
+ async function handleUpdateTicket(input, dataDir = DATA_DIR$17) {
6090
6091
  const ticket = (await readTickets(dataDir, input.slug)).find((t) => t.id === input.ticketId);
6091
6092
  if (!ticket) return { content: [{
6092
6093
  type: "text",
@@ -6105,7 +6106,7 @@ async function handleUpdateTicket(input, dataDir = DATA_DIR$16) {
6105
6106
  text: JSON.stringify({ ticket: updated }, null, 2)
6106
6107
  }] };
6107
6108
  }
6108
- function registerUpdateTicket(server, dataDir = DATA_DIR$16) {
6109
+ function registerUpdateTicket(server, dataDir = DATA_DIR$17) {
6109
6110
  server.registerTool("update_ticket", {
6110
6111
  description: `Update a ticket's status or assignee. Setting status=resolved auto-sets resolved date.
6111
6112
  Returns: { ticket }`,
@@ -6130,8 +6131,8 @@ Returns: { ticket }`,
6130
6131
  }
6131
6132
  //#endregion
6132
6133
  //#region src/mcp/tools/list-tickets.ts
6133
- const DATA_DIR$15 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6134
- async function handleListTickets(input, dataDir = DATA_DIR$15) {
6134
+ const DATA_DIR$16 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6135
+ async function handleListTickets(input, dataDir = DATA_DIR$16) {
6135
6136
  const results = await listAllTickets(dataDir, {
6136
6137
  ...input.slug !== void 0 ? { slug: input.slug } : {},
6137
6138
  ...input.status !== void 0 ? { status: input.status } : {},
@@ -6143,7 +6144,7 @@ async function handleListTickets(input, dataDir = DATA_DIR$15) {
6143
6144
  text: JSON.stringify({ tickets: results }, null, 2)
6144
6145
  }] };
6145
6146
  }
6146
- function registerListTickets(server, dataDir = DATA_DIR$15) {
6147
+ function registerListTickets(server, dataDir = DATA_DIR$16) {
6147
6148
  server.registerTool("list_tickets", {
6148
6149
  description: `List support tickets. Filter by customer, status, priority, or assignee. Sorted by priority then date.
6149
6150
  Returns: { tickets: Array<{ slug, ticket }> }`,
@@ -6173,8 +6174,8 @@ Returns: { tickets: Array<{ slug, ticket }> }`,
6173
6174
  }
6174
6175
  //#endregion
6175
6176
  //#region src/mcp/tools/close-ticket.ts
6176
- const DATA_DIR$14 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6177
- async function handleCloseTicket(input, dataDir = DATA_DIR$14) {
6177
+ const DATA_DIR$15 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6178
+ async function handleCloseTicket(input, dataDir = DATA_DIR$15) {
6178
6179
  const ticket = (await readTickets(dataDir, input.slug)).find((t) => t.id === input.ticketId);
6179
6180
  if (!ticket) return { content: [{
6180
6181
  type: "text",
@@ -6201,7 +6202,7 @@ async function handleCloseTicket(input, dataDir = DATA_DIR$14) {
6201
6202
  text: JSON.stringify({ ticket: updated }, null, 2)
6202
6203
  }] };
6203
6204
  }
6204
- function registerCloseTicket(server, dataDir = DATA_DIR$14) {
6205
+ function registerCloseTicket(server, dataDir = DATA_DIR$15) {
6205
6206
  server.registerTool("close_ticket", {
6206
6207
  description: `Close a support ticket. Optionally logs the resolution as an interaction.
6207
6208
  Returns: { ticket } with status=closed`,
@@ -6355,8 +6356,8 @@ async function savePendingSurvey(dataDir, surveyId, slug, contactEmail, token) {
6355
6356
  }
6356
6357
  //#endregion
6357
6358
  //#region src/mcp/tools/send-nps-survey.ts
6358
- const DATA_DIR$13 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6359
- async function handleSendNpsSurvey(input, dataDir = DATA_DIR$13) {
6359
+ const DATA_DIR$14 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6360
+ async function handleSendNpsSurvey(input, dataDir = DATA_DIR$14) {
6360
6361
  const survey = getSurvey(dataDir, input.surveyId);
6361
6362
  if (!survey) return { content: [{
6362
6363
  type: "text",
@@ -6377,7 +6378,7 @@ async function handleSendNpsSurvey(input, dataDir = DATA_DIR$13) {
6377
6378
  }, null, 2)
6378
6379
  }] };
6379
6380
  }
6380
- function registerSendNpsSurvey(server, dataDir = DATA_DIR$13) {
6381
+ function registerSendNpsSurvey(server, dataDir = DATA_DIR$14) {
6381
6382
  server.registerTool("send_nps_survey", {
6382
6383
  description: `Generate an NPS/CSAT survey email for a customer contact. Returns subject, HTML body, and a token-based response URL.
6383
6384
  Does NOT send automatically — returns draft for review.
@@ -6397,8 +6398,8 @@ Returns: { token, subject, body, surveyUrl }`,
6397
6398
  }
6398
6399
  //#endregion
6399
6400
  //#region src/mcp/tools/get-survey-results.ts
6400
- const DATA_DIR$12 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6401
- async function handleGetSurveyResults(input, dataDir = DATA_DIR$12) {
6401
+ const DATA_DIR$13 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6402
+ async function handleGetSurveyResults(input, dataDir = DATA_DIR$13) {
6402
6403
  const responses = loadSurveyResponses(dataDir, input.surveyId, input.slug);
6403
6404
  const nps = calcNpsScore(responses);
6404
6405
  const promoters = responses.filter((r) => r.score >= 9).length;
@@ -6424,7 +6425,7 @@ async function handleGetSurveyResults(input, dataDir = DATA_DIR$12) {
6424
6425
  }, null, 2)
6425
6426
  }] };
6426
6427
  }
6427
- function registerGetSurveyResults(server, dataDir = DATA_DIR$12) {
6428
+ function registerGetSurveyResults(server, dataDir = DATA_DIR$13) {
6428
6429
  server.registerTool("get_survey_results", {
6429
6430
  description: `Get NPS/CSAT survey results with score breakdown. Calculates Net Promoter Score.
6430
6431
  Returns: { npsScore, totalResponses, promoters, passives, detractors, responses[] }`,
@@ -6525,8 +6526,8 @@ function getKbMetaForExport(article) {
6525
6526
  }
6526
6527
  //#endregion
6527
6528
  //#region src/mcp/tools/search-knowledge-base.ts
6528
- const DATA_DIR$11 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6529
- async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$11) {
6529
+ const DATA_DIR$12 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6530
+ async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$12) {
6530
6531
  const results = searchKbSimple(dataDir, input.query, { ...input.publicOnly ? { publicOnly: true } : {} });
6531
6532
  const limited = (input.category ? results.filter((a) => a.category === input.category) : results).slice(0, input.limit ?? 10);
6532
6533
  return { content: [{
@@ -6541,7 +6542,7 @@ async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$11) {
6541
6542
  }, null, 2)
6542
6543
  }] };
6543
6544
  }
6544
- function registerSearchKnowledgeBase(server, dataDir = DATA_DIR$11) {
6545
+ function registerSearchKnowledgeBase(server, dataDir = DATA_DIR$12) {
6545
6546
  server.registerTool("search_knowledge_base", {
6546
6547
  description: `Search the knowledge base for articles. Text search on title, body, and tags.
6547
6548
  Returns: { count, articles[] } with excerpts`,
@@ -6560,8 +6561,8 @@ Returns: { count, articles[] } with excerpts`,
6560
6561
  }
6561
6562
  //#endregion
6562
6563
  //#region src/mcp/tools/create-kb-article.ts
6563
- const DATA_DIR$10 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6564
- async function handleCreateKbArticle(input, dataDir = DATA_DIR$10) {
6564
+ const DATA_DIR$11 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6565
+ async function handleCreateKbArticle(input, dataDir = DATA_DIR$11) {
6565
6566
  if (getKbArticle(dataDir, input.id)) return { content: [{
6566
6567
  type: "text",
6567
6568
  text: JSON.stringify({ error: `Article '${input.id}' already exists` })
@@ -6589,7 +6590,7 @@ async function handleCreateKbArticle(input, dataDir = DATA_DIR$10) {
6589
6590
  }, null, 2)
6590
6591
  }] };
6591
6592
  }
6592
- function registerCreateKbArticle(server, dataDir = DATA_DIR$10) {
6593
+ function registerCreateKbArticle(server, dataDir = DATA_DIR$11) {
6593
6594
  server.registerTool("create_kb_article", {
6594
6595
  description: `Create a new knowledge base article. Articles are stored as Markdown files in .agentic/knowledge-base/.
6595
6596
  Returns: { id, title, category, path }`,
@@ -6614,8 +6615,8 @@ Returns: { id, title, category, path }`,
6614
6615
  }
6615
6616
  //#endregion
6616
6617
  //#region src/mcp/tools/backup-now.ts
6617
- const DATA_DIR$9 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6618
- async function handleBackupNow(input, dataDir = DATA_DIR$9) {
6618
+ const DATA_DIR$10 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6619
+ async function handleBackupNow(input, dataDir = DATA_DIR$10) {
6619
6620
  const zipPath = path.default.join(dataDir, `dxcrm-backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19)}.zip`);
6620
6621
  const manifest = await require_session_store.runBackup(zipPath, dataDir, { ...input.remote ? { remote: input.remote } : {} }).catch(() => null);
6621
6622
  if (!manifest) return { content: [{
@@ -6652,8 +6653,8 @@ function registerBackupNow(server) {
6652
6653
  }
6653
6654
  //#endregion
6654
6655
  //#region src/mcp/tools/list-backups.ts
6655
- const DATA_DIR$8 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6656
- async function handleListBackups(input, dataDir = DATA_DIR$8) {
6656
+ const DATA_DIR$9 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6657
+ async function handleListBackups(input, dataDir = DATA_DIR$9) {
6657
6658
  const logEntries = require_session_store.readBackupLog(dataDir);
6658
6659
  const fileEntries = require_session_store.listBackupsInDir(dataDir);
6659
6660
  const entries = logEntries.length > 0 ? logEntries : fileEntries;
@@ -6687,8 +6688,8 @@ function registerListBackups(server) {
6687
6688
  }
6688
6689
  //#endregion
6689
6690
  //#region src/mcp/tools/trigger-sync.ts
6690
- const DATA_DIR$7 = process.cwd();
6691
- async function handleTriggerSync(input, dataDir = DATA_DIR$7) {
6691
+ const DATA_DIR$8 = process.cwd();
6692
+ async function handleTriggerSync(input, dataDir = DATA_DIR$8) {
6692
6693
  const auth = getGmailAuth();
6693
6694
  if (!auth) return { content: [{
6694
6695
  type: "text",
@@ -6782,8 +6783,8 @@ Returns: { success: boolean, synced: number, skipped: number, customers: [...],
6782
6783
  }
6783
6784
  //#endregion
6784
6785
  //#region src/mcp/tools/get-audit-log.ts
6785
- const DATA_DIR$6 = process.cwd();
6786
- async function handleGetAuditLog(input, dataDir = DATA_DIR$6) {
6786
+ const DATA_DIR$7 = process.cwd();
6787
+ async function handleGetAuditLog(input, dataDir = DATA_DIR$7) {
6787
6788
  const entries = require_session_store.readAuditLog(dataDir);
6788
6789
  const filterOpts = { limit: input.limit ?? 50 };
6789
6790
  if (input.slug !== void 0) filterOpts.slug = input.slug;
@@ -6825,8 +6826,8 @@ Returns: { total: number, returned: number, entries: [{timestamp, actor, tool, s
6825
6826
  }
6826
6827
  //#endregion
6827
6828
  //#region src/mcp/tools/get-logs.ts
6828
- const DATA_DIR$5 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6829
- async function handleGetLogs(input, dataDir = DATA_DIR$5) {
6829
+ const DATA_DIR$6 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6830
+ async function handleGetLogs(input, dataDir = DATA_DIR$6) {
6830
6831
  const query = {
6831
6832
  ...input.level !== void 0 ? { level: input.level } : {},
6832
6833
  ...input.component !== void 0 ? { component: input.component } : {},
@@ -6988,8 +6989,8 @@ async function runDiagnostics(dataDir) {
6988
6989
  }
6989
6990
  //#endregion
6990
6991
  //#region src/mcp/tools/get-diagnostics.ts
6991
- const DATA_DIR$4 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6992
- async function handleGetDiagnostics(input, dataDir = DATA_DIR$4) {
6992
+ const DATA_DIR$5 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
6993
+ async function handleGetDiagnostics(input, dataDir = DATA_DIR$5) {
6993
6994
  let cleaned = 0;
6994
6995
  if (input.fix) {
6995
6996
  const { cleanupTempFiles } = await Promise.resolve().then(() => doctor_exports);
@@ -7151,11 +7152,11 @@ function diffAgainstNow(dataDir, since, today = (/* @__PURE__ */ new Date()).toI
7151
7152
  }
7152
7153
  //#endregion
7153
7154
  //#region src/mcp/tools/get-pipeline-changes.ts
7154
- const DATA_DIR$3 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
7155
+ const DATA_DIR$4 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
7155
7156
  function daysAgoIso(days) {
7156
7157
  return (/* @__PURE__ */ new Date(Date.now() - days * 864e5)).toISOString().slice(0, 10);
7157
7158
  }
7158
- async function handleGetPipelineChanges(input, dataDir = DATA_DIR$3) {
7159
+ async function handleGetPipelineChanges(input, dataDir = DATA_DIR$4) {
7159
7160
  const since = input.since ?? daysAgoIso(input.days ?? 7);
7160
7161
  const diff = diffAgainstNow(dataDir, since);
7161
7162
  const payload = diff ? diff : { error: `No pipeline snapshot at or before ${since}. Snapshots accrue daily via the daemon.` };
@@ -7310,8 +7311,8 @@ function analyzeVelocity(dataDir, opts) {
7310
7311
  }
7311
7312
  //#endregion
7312
7313
  //#region src/mcp/tools/get-pipeline-velocity.ts
7313
- const DATA_DIR$2 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
7314
- async function handleGetPipelineVelocity(input, dataDir = DATA_DIR$2) {
7314
+ const DATA_DIR$3 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
7315
+ async function handleGetPipelineVelocity(input, dataDir = DATA_DIR$3) {
7315
7316
  const opts = {};
7316
7317
  if (input.stalledDays !== void 0) opts.stalledDays = input.stalledDays;
7317
7318
  const report = analyzeVelocity(dataDir, opts);
@@ -7342,6 +7343,116 @@ stalledThresholdDays }. snapshotCount is 0 until the daemon has taken snapshots.
7342
7343
  });
7343
7344
  }
7344
7345
  //#endregion
7346
+ //#region src/core/funnel.ts
7347
+ const FUNNEL_STAGES = [
7348
+ "lead",
7349
+ "qualified",
7350
+ "proposal",
7351
+ "negotiation",
7352
+ "won"
7353
+ ];
7354
+ const STAGE_INDEX = Object.fromEntries(FUNNEL_STAGES.map((s, i) => [s, i]));
7355
+ function emptyReport(snapshotCount) {
7356
+ return {
7357
+ fromId: null,
7358
+ toId: null,
7359
+ snapshotCount,
7360
+ stages: [],
7361
+ wonCount: 0,
7362
+ lostCount: 0,
7363
+ winRatePct: null,
7364
+ biggestLeak: null
7365
+ };
7366
+ }
7367
+ function analyzeFunnel(dataDir) {
7368
+ const metas = listSnapshots(dataDir);
7369
+ if (metas.length === 0) return emptyReport(0);
7370
+ const snaps = metas.flatMap((m) => {
7371
+ const s = loadSnapshot(dataDir, m.id);
7372
+ return s ? [s] : [];
7373
+ });
7374
+ const progress = /* @__PURE__ */ new Map();
7375
+ for (const snap of snaps) for (const deal of snap.deals) {
7376
+ const key = `${deal.slug}::${deal.name}`;
7377
+ const p = progress.get(key) ?? {
7378
+ maxIndex: -1,
7379
+ won: false,
7380
+ lost: false
7381
+ };
7382
+ if (deal.stage === "lost") p.lost = true;
7383
+ else {
7384
+ const idx = STAGE_INDEX[deal.stage];
7385
+ if (idx !== void 0 && idx > p.maxIndex) p.maxIndex = idx;
7386
+ if (deal.stage === "won") p.won = true;
7387
+ }
7388
+ progress.set(key, p);
7389
+ }
7390
+ const reached = new Array(FUNNEL_STAGES.length).fill(0);
7391
+ let wonCount = 0;
7392
+ let lostCount = 0;
7393
+ for (const p of progress.values()) {
7394
+ for (let i = 0; i <= p.maxIndex; i++) reached[i] = (reached[i] ?? 0) + 1;
7395
+ if (p.won) wonCount += 1;
7396
+ else if (p.lost) lostCount += 1;
7397
+ }
7398
+ const stages = FUNNEL_STAGES.map((stage, i) => {
7399
+ const here = reached[i] ?? 0;
7400
+ const next = reached[i + 1];
7401
+ return {
7402
+ stage,
7403
+ reached: here,
7404
+ conversionPctToNext: next === void 0 || here === 0 ? null : Math.round(next / here * 100)
7405
+ };
7406
+ });
7407
+ let biggestLeak = null;
7408
+ for (let i = 0; i < FUNNEL_STAGES.length - 1; i++) {
7409
+ const conv = stages[i].conversionPctToNext;
7410
+ if (conv === null) continue;
7411
+ if (biggestLeak === null || conv < biggestLeak.conversionPct) biggestLeak = {
7412
+ from: FUNNEL_STAGES[i],
7413
+ to: FUNNEL_STAGES[i + 1],
7414
+ conversionPct: conv
7415
+ };
7416
+ }
7417
+ const closed = wonCount + lostCount;
7418
+ const winRatePct = closed > 0 ? Math.round(wonCount / closed * 100) : null;
7419
+ return {
7420
+ fromId: snaps[0].id,
7421
+ toId: snaps[snaps.length - 1].id,
7422
+ snapshotCount: snaps.length,
7423
+ stages,
7424
+ wonCount,
7425
+ lostCount,
7426
+ winRatePct,
7427
+ biggestLeak
7428
+ };
7429
+ }
7430
+ //#endregion
7431
+ //#region src/mcp/tools/get-pipeline-funnel.ts
7432
+ const DATA_DIR$2 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
7433
+ async function handleGetPipelineFunnel(_input, dataDir = DATA_DIR$2) {
7434
+ const report = analyzeFunnel(dataDir);
7435
+ return { content: [{
7436
+ type: "text",
7437
+ text: JSON.stringify(report, null, 2)
7438
+ }] };
7439
+ }
7440
+ function registerGetPipelineFunnel(server) {
7441
+ server.registerTool("get_pipeline_funnel", {
7442
+ title: "Get Pipeline Funnel",
7443
+ description: `Pipeline conversion funnel & win-rate from the daily snapshot history.
7444
+ For each deal it tracks the furthest stage reached and the win/lost outcome,
7445
+ then builds a cumulative funnel. Answers "where do deals leak out of my
7446
+ pipeline?" and "what's my win rate?".
7447
+
7448
+ Returns: { fromId, toId, snapshotCount,
7449
+ stages[{stage, reached, conversionPctToNext}], wonCount, lostCount, winRatePct,
7450
+ biggestLeak{from,to,conversionPct} }. snapshotCount is 0 until the daemon has
7451
+ taken snapshots.`,
7452
+ inputSchema: zod.z.object({})
7453
+ }, async () => handleGetPipelineFunnel({}));
7454
+ }
7455
+ //#endregion
7345
7456
  //#region src/mcp/prompts.ts
7346
7457
  /**
7347
7458
  * CRM playbook prompts exposed via MCP `prompts/list` + `prompts/get`.
@@ -7761,6 +7872,7 @@ function createMcpServer() {
7761
7872
  registerGetDiagnostics(server);
7762
7873
  registerGetPipelineChanges(server);
7763
7874
  registerGetPipelineVelocity(server);
7875
+ registerGetPipelineFunnel(server);
7764
7876
  registerCustomObjectTools(server);
7765
7877
  registerPrompts(server);
7766
7878
  registerResources(server);