@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
@@ -2,7 +2,7 @@ import { a as readMainFacts, i as listCustomerSlugs, n as customerExists, o as w
2
2
  import { t as writeFileAtomic } from "./atomic-write-8yjqqLtS.js";
3
3
  import { i as writeJsonFile } from "./json-store-WWsFzXub.js";
4
4
  import { n as getSession } from "./session-store-CEa39Dxs.js";
5
- import { a as searchKbSimple, n as getKbArticle, o as writeKbArticle, r as getKbMetaForExport, s as CAPABILITIES_TEXT } from "./knowledge-base-Byo0zwM5.js";
5
+ import { a as searchKbSimple, n as getKbArticle, o as writeKbArticle, r as getKbMetaForExport, s as CAPABILITIES_TEXT } from "./knowledge-base-yo-BLUcB.js";
6
6
  import { i as readBackupLog, n as listBackupsInDir, o as runBackup } from "./backup-CTlIxUdO.js";
7
7
  import { r as updateSlugSyncState, t as getLastGmailSync } from "./sync-state-DMZgzpez.js";
8
8
  import { t as withFileQueue } from "./write-queue-IbsAjUnh.js";
@@ -24,9 +24,10 @@ import { i as getSurvey, l as savePendingSurvey, n as calcNpsScore, o as loadSur
24
24
  import { t as buildContext } from "./context-builder-7Uab5-G4.js";
25
25
  import { a as loadCustomObjects, i as listRecords, n as defineCustomObject, t as createRecord } from "./custom-objects-CxW1gHwJ.js";
26
26
  import { n as runDiagnostics } from "./doctor-BFeelnq8.js";
27
+ import { n as diffAgainstNow } from "./snapshots-CQSOaIMs.js";
28
+ import { t as analyzeFunnel } from "./funnel-B2mwpZE1.js";
27
29
  import { r as searchKnowledge } from "./lancedb-CuHKNsNZ.js";
28
30
  import { t as buildDailyBriefing } from "./proactive-agent-B7u3Bj_l.js";
29
- import { n as diffAgainstNow } from "./snapshots-CQSOaIMs.js";
30
31
  import { t as analyzeVelocity } from "./velocity-C2l4cW0K.js";
31
32
  import { a as protectedResourceMetadata, o as verifyBearer, r as isAuthRequired, s as wwwAuthenticateHeader } from "./auth-DDXZTwS0.js";
32
33
  import { i as verifyGmailPubSubSignature, n as decodeGmailPubSubPayload, r as handleGmailPushEvent } from "./gmail-webhook-handler-BzOFbvgh.js";
@@ -257,7 +258,7 @@ function registerGetActiveSession(server) {
257
258
  }
258
259
  //#endregion
259
260
  //#region src/mcp/tools/get-customer-context.ts
260
- const DATA_DIR$54 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
261
+ const DATA_DIR$55 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
261
262
  function triggerOnQuerySync(dataDir, slug) {
262
263
  const auth = getGmailAuth();
263
264
  if (!auth) return;
@@ -278,7 +279,7 @@ function triggerOnQuerySync(dataDir, slug) {
278
279
  }).then(() => updateSlugSyncState(dataDir, slug, { lastGmailSync: (/* @__PURE__ */ new Date()).toISOString() })).catch(() => {})).catch(() => {});
279
280
  } catch {}
280
281
  }
281
- async function handleGetCustomerContext(input, dataDir = DATA_DIR$54) {
282
+ async function handleGetCustomerContext(input, dataDir = DATA_DIR$55) {
282
283
  const targetSlug = input.slug ?? getSession()?.customerSlug;
283
284
  if (!targetSlug) return {
284
285
  content: [{
@@ -330,8 +331,8 @@ Performance: <3 seconds. Token budget: <3000.`,
330
331
  }
331
332
  //#endregion
332
333
  //#region src/mcp/tools/search-customer-knowledge.ts
333
- const DATA_DIR$53 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
334
- async function handleSearchCustomerKnowledge(input, dataDir = DATA_DIR$53) {
334
+ const DATA_DIR$54 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
335
+ async function handleSearchCustomerKnowledge(input, dataDir = DATA_DIR$54) {
335
336
  const limit = input.limit ?? 5;
336
337
  try {
337
338
  const results = await searchKnowledge(dataDir, input.slug, input.query, limit);
@@ -379,14 +380,14 @@ If no results: returns empty array with a helpful sync suggestion.`,
379
380
  }
380
381
  //#endregion
381
382
  //#region src/mcp/tools/list-customers.ts
382
- const DATA_DIR$52 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
383
+ const DATA_DIR$53 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
383
384
  function extractLastInteractionDate(interactionsPath) {
384
385
  if (!fs.existsSync(interactionsPath)) return void 0;
385
386
  const content = fs.readFileSync(interactionsPath, "utf-8");
386
387
  const match = /^## (\d{4}-\d{2}-\d{2})/m.exec(content);
387
388
  return match ? match[1] : void 0;
388
389
  }
389
- async function handleListCustomers(input, dataDir = DATA_DIR$52) {
390
+ async function handleListCustomers(input, dataDir = DATA_DIR$53) {
390
391
  const customersDir = path.join(dataDir, "customers");
391
392
  const customers = [];
392
393
  if (!fs.existsSync(customersDir)) return { content: [{
@@ -447,8 +448,8 @@ Returns: Array of { slug, name, stage, lastInteraction?, dealValue? }`,
447
448
  }
448
449
  //#endregion
449
450
  //#region src/mcp/tools/log-interaction.ts
450
- const DATA_DIR$51 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
451
- async function handleLogInteraction(input, dataDir = DATA_DIR$51) {
451
+ const DATA_DIR$52 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
452
+ async function handleLogInteraction(input, dataDir = DATA_DIR$52) {
452
453
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
453
454
  const interactionDate = input.date ?? today;
454
455
  const sourceRef = input.source ?? `agent://log/${Date.now()}`;
@@ -553,12 +554,12 @@ Returns: { success: boolean, path: string, entry: string }`,
553
554
  }
554
555
  //#endregion
555
556
  //#region src/mcp/tools/export-customer.ts
556
- const DATA_DIR$50 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
557
+ const DATA_DIR$51 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
557
558
  function countInteractions(content) {
558
559
  const matches = content.match(/^## \d{4}-\d{2}-\d{2}/gm);
559
560
  return matches ? matches.length : 0;
560
561
  }
561
- async function handleExportCustomer(input, dataDir = DATA_DIR$50) {
562
+ async function handleExportCustomer(input, dataDir = DATA_DIR$51) {
562
563
  enforceRbac(dataDir, "export_customer");
563
564
  const customerDir = path.join(dataDir, "customers", input.slug);
564
565
  if (!fs.existsSync(customerDir)) return {
@@ -671,8 +672,8 @@ Returns:
671
672
  }
672
673
  //#endregion
673
674
  //#region src/mcp/tools/update-customer-facts.ts
674
- const DATA_DIR$49 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
675
- async function handleUpdateCustomerFacts(input, dataDir = DATA_DIR$49) {
675
+ const DATA_DIR$50 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
676
+ async function handleUpdateCustomerFacts(input, dataDir = DATA_DIR$50) {
676
677
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
677
678
  try {
678
679
  enforceRbac(dataDir, "update_customer_facts");
@@ -850,8 +851,8 @@ function scoreDealForToday(deal, todayDate) {
850
851
  }
851
852
  //#endregion
852
853
  //#region src/mcp/tools/get-deal-health.ts
853
- const DATA_DIR$48 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
854
- async function handleGetDealHealth(input, dataDir = DATA_DIR$48) {
854
+ const DATA_DIR$49 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
855
+ async function handleGetDealHealth(input, dataDir = DATA_DIR$49) {
855
856
  try {
856
857
  const deals = await readPipeline(dataDir, input.slug);
857
858
  const today = /* @__PURE__ */ new Date();
@@ -900,8 +901,8 @@ Returns: { slug, deals: [{ deal, stage, score, grade, signals, warnings }] }`,
900
901
  }
901
902
  //#endregion
902
903
  //#region src/mcp/tools/get-pipeline-forecast.ts
903
- const DATA_DIR$47 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
904
- async function handleGetPipelineForecast(input, dataDir = DATA_DIR$47) {
904
+ const DATA_DIR$48 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
905
+ async function handleGetPipelineForecast(input, dataDir = DATA_DIR$48) {
905
906
  try {
906
907
  const slugs = listCustomerSlugs(dataDir).filter((d) => !input.filter || d.includes(input.filter));
907
908
  const allDeals = [];
@@ -962,8 +963,8 @@ Returns: { deals: [...], totalWeightedValue: number, byStage: { stage: { count,
962
963
  }
963
964
  //#endregion
964
965
  //#region src/mcp/tools/summarize-meeting.ts
965
- const DATA_DIR$46 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
966
- async function handleSummarizeMeeting(input, dataDir = DATA_DIR$46) {
966
+ const DATA_DIR$47 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
967
+ async function handleSummarizeMeeting(input, dataDir = DATA_DIR$47) {
967
968
  try {
968
969
  let summary = input.transcript.slice(0, 400);
969
970
  let nextSteps = [];
@@ -1038,8 +1039,8 @@ Returns: { success, summary, nextSteps, sourceRef }`,
1038
1039
  }
1039
1040
  //#endregion
1040
1041
  //#region src/mcp/tools/get-pipeline-stages.ts
1041
- const DATA_DIR$45 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1042
- async function handleGetPipelineStages(_input, dataDir = DATA_DIR$45) {
1042
+ const DATA_DIR$46 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1043
+ async function handleGetPipelineStages(_input, dataDir = DATA_DIR$46) {
1043
1044
  const stages = getPipelineStages(dataDir);
1044
1045
  return { content: [{
1045
1046
  type: "text",
@@ -1067,8 +1068,8 @@ async function searchAcrossCustomers(dataDir, query, limit = 5, excludeSlug) {
1067
1068
  }
1068
1069
  //#endregion
1069
1070
  //#region src/mcp/tools/get-market-intelligence.ts
1070
- const DATA_DIR$44 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1071
- async function handleGetMarketIntelligence(input, dataDir = DATA_DIR$44) {
1071
+ const DATA_DIR$45 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1072
+ async function handleGetMarketIntelligence(input, dataDir = DATA_DIR$45) {
1072
1073
  const excludeSlug = input.excludeCurrentCustomer ? input.slug : void 0;
1073
1074
  const all = listCustomerSlugs(dataDir);
1074
1075
  const totalCustomersSearched = excludeSlug ? all.filter((s) => s !== excludeSlug).length : all.length;
@@ -1099,7 +1100,7 @@ function registerGetMarketIntelligence(server) {
1099
1100
  }
1100
1101
  //#endregion
1101
1102
  //#region src/mcp/tools/get-relationship-graph.ts
1102
- const DATA_DIR$43 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1103
+ const DATA_DIR$44 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1103
1104
  function summarizeNode(n) {
1104
1105
  return {
1105
1106
  id: n.id,
@@ -1107,7 +1108,7 @@ function summarizeNode(n) {
1107
1108
  email: n.properties["email"]
1108
1109
  };
1109
1110
  }
1110
- async function handleGetRelationshipGraph(input, dataDir = DATA_DIR$43) {
1111
+ async function handleGetRelationshipGraph(input, dataDir = DATA_DIR$44) {
1111
1112
  try {
1112
1113
  const graph = readGraph(dataDir, input.slug);
1113
1114
  const stakeholders = getStakeholders(graph);
@@ -1175,9 +1176,9 @@ Returns: {
1175
1176
  }
1176
1177
  //#endregion
1177
1178
  //#region src/mcp/tools/get-relationship-health.ts
1178
- const DATA_DIR$42 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1179
+ const DATA_DIR$43 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1179
1180
  const MAX_HEALTH_AGE_MS = 3600 * 1e3;
1180
- async function handleGetRelationshipHealth(input, dataDir = DATA_DIR$42) {
1181
+ async function handleGetRelationshipHealth(input, dataDir = DATA_DIR$43) {
1181
1182
  try {
1182
1183
  let health = readHealth(dataDir, input.slug);
1183
1184
  if (health === null || Date.now() - new Date(health.updatedAt).getTime() > MAX_HEALTH_AGE_MS) {
@@ -1846,8 +1847,8 @@ async function runDealAgent(config, dataDir, llmFn = callLlm) {
1846
1847
  }
1847
1848
  //#endregion
1848
1849
  //#region src/mcp/tools/run-deal-agent.ts
1849
- const DATA_DIR$41 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1850
- async function handleRunDealAgent(input, dataDir = DATA_DIR$41) {
1850
+ const DATA_DIR$42 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1851
+ async function handleRunDealAgent(input, dataDir = DATA_DIR$42) {
1851
1852
  try {
1852
1853
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
1853
1854
  const result = await runDealAgent({
@@ -1914,8 +1915,8 @@ Returns: { assessment, riskLevel, plan[], actionsQueued[], actionsExecuted[], tr
1914
1915
  }
1915
1916
  //#endregion
1916
1917
  //#region src/mcp/tools/approve-agent-action.ts
1917
- const DATA_DIR$40 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1918
- async function handleApproveAgentAction(input, dataDir = DATA_DIR$40) {
1918
+ const DATA_DIR$41 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1919
+ async function handleApproveAgentAction(input, dataDir = DATA_DIR$41) {
1919
1920
  try {
1920
1921
  const queue = readAgentQueue(dataDir, input.slug);
1921
1922
  const idx = queue.pendingActions.findIndex((a) => a.actionId === input.actionId);
@@ -1992,8 +1993,8 @@ Returns: { success, actionId, status }`,
1992
1993
  }
1993
1994
  //#endregion
1994
1995
  //#region src/mcp/tools/simulate-revenue.ts
1995
- const DATA_DIR$39 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1996
- async function handleSimulateRevenue(input, dataDir = DATA_DIR$39) {
1996
+ const DATA_DIR$40 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1997
+ async function handleSimulateRevenue(input, dataDir = DATA_DIR$40) {
1997
1998
  try {
1998
1999
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
1999
2000
  const horizon = input.horizon ?? "quarter";
@@ -2051,8 +2052,8 @@ Returns: { forecast: { p10, p50, p90, expected, stdDev, atRiskRevenue, byCloseMo
2051
2052
  }
2052
2053
  //#endregion
2053
2054
  //#region src/mcp/tools/get-playbook.ts
2054
- const DATA_DIR$38 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2055
- async function handleGetPlaybook(input, dataDir = DATA_DIR$38) {
2055
+ const DATA_DIR$39 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2056
+ async function handleGetPlaybook(input, dataDir = DATA_DIR$39) {
2056
2057
  try {
2057
2058
  const playbooks = listPlaybooks(dataDir, input.slug);
2058
2059
  if (!(input.stage !== void 0 || input.value !== void 0 || input.healthScore !== void 0)) return { content: [{
@@ -2137,12 +2138,12 @@ Returns: { matches: [{ name, score, trigger, successRate, usedCount, content }],
2137
2138
  ...healthScore !== void 0 ? { healthScore } : {},
2138
2139
  ...daysSinceContact !== void 0 ? { daysSinceContact } : {},
2139
2140
  ...championPresent !== void 0 ? { championPresent } : {}
2140
- }, DATA_DIR$38));
2141
+ }, DATA_DIR$39));
2141
2142
  }
2142
2143
  //#endregion
2143
2144
  //#region src/mcp/tools/create-playbook.ts
2144
- const DATA_DIR$37 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2145
- async function handleCreatePlaybook(input, dataDir = DATA_DIR$37) {
2145
+ const DATA_DIR$38 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2146
+ async function handleCreatePlaybook(input, dataDir = DATA_DIR$38) {
2146
2147
  try {
2147
2148
  const name = toKebabCase(input.name);
2148
2149
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -2215,12 +2216,12 @@ Returns: { success: true, playbook: { name, trigger, successRate, path } }`,
2215
2216
  trigger,
2216
2217
  content,
2217
2218
  ...successRate !== void 0 ? { successRate } : {}
2218
- }, DATA_DIR$37));
2219
+ }, DATA_DIR$38));
2219
2220
  }
2220
2221
  //#endregion
2221
2222
  //#region src/mcp/tools/list-playbooks.ts
2222
- const DATA_DIR$36 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2223
- async function handleListPlaybooks(input, dataDir = DATA_DIR$36) {
2223
+ const DATA_DIR$37 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2224
+ async function handleListPlaybooks(input, dataDir = DATA_DIR$37) {
2224
2225
  try {
2225
2226
  const playbooks = listPlaybooks(dataDir, input.slug);
2226
2227
  return { content: [{
@@ -2259,12 +2260,12 @@ Args:
2259
2260
 
2260
2261
  Returns: { playbooks: [{ name, trigger, successRate, usedCount, lastUpdated }], count, slug }`,
2261
2262
  inputSchema: z.object({ slug: z.string().describe("Customer ID") })
2262
- }, async ({ slug }) => handleListPlaybooks({ slug }, DATA_DIR$36));
2263
+ }, async ({ slug }) => handleListPlaybooks({ slug }, DATA_DIR$37));
2263
2264
  }
2264
2265
  //#endregion
2265
2266
  //#region src/mcp/tools/distill-playbook.ts
2266
- const DATA_DIR$35 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2267
- async function handleDistillPlaybook(input, dataDir = DATA_DIR$35, llmFn = callLlm) {
2267
+ const DATA_DIR$36 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2268
+ async function handleDistillPlaybook(input, dataDir = DATA_DIR$36, llmFn = callLlm) {
2268
2269
  try {
2269
2270
  const result = await distillPlaybook(dataDir, input.slug, input.dealName, input.outcome, llmFn);
2270
2271
  if (!result.ok) {
@@ -2323,12 +2324,12 @@ Returns: { success: true, playbook: { name, trigger, successRate, path }, reason
2323
2324
  slug,
2324
2325
  dealName,
2325
2326
  outcome
2326
- }, DATA_DIR$35));
2327
+ }, DATA_DIR$36));
2327
2328
  }
2328
2329
  //#endregion
2329
2330
  //#region src/mcp/tools/pursue-goal.ts
2330
- const DATA_DIR$34 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2331
- async function handlePursueGoal(input, dataDir = DATA_DIR$34, options = {}) {
2331
+ const DATA_DIR$35 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2332
+ async function handlePursueGoal(input, dataDir = DATA_DIR$35, options = {}) {
2332
2333
  try {
2333
2334
  enforceRbac(dataDir, "pursue_goal");
2334
2335
  const goal = await pursueGoal(dataDir, {
@@ -2391,12 +2392,12 @@ Returns: { goalId, description, target, deadline, decomposition: { analysis, cur
2391
2392
  goal,
2392
2393
  deadline,
2393
2394
  ...context !== void 0 ? { context } : {}
2394
- }, DATA_DIR$34));
2395
+ }, DATA_DIR$35));
2395
2396
  }
2396
2397
  //#endregion
2397
2398
  //#region src/mcp/tools/get-goal-status.ts
2398
- const DATA_DIR$33 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2399
- async function handleGetGoalStatus(input, dataDir = DATA_DIR$33) {
2399
+ const DATA_DIR$34 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2400
+ async function handleGetGoalStatus(input, dataDir = DATA_DIR$34) {
2400
2401
  try {
2401
2402
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
2402
2403
  const allGoals = input.goalId ? readGoals(dataDir).filter((g) => g.id === input.goalId) : getActiveGoals(dataDir);
@@ -2455,17 +2456,17 @@ Args:
2455
2456
 
2456
2457
  Returns: { goals: [{ id, description, target, progress, status, deadline, daysRemaining, subGoals }], activeCount, completedCount }`,
2457
2458
  inputSchema: z.object({ goalId: z.string().optional().describe("Specific goal ID (omit for all active goals)") })
2458
- }, async ({ goalId }) => handleGetGoalStatus({ ...goalId !== void 0 ? { goalId } : {} }, DATA_DIR$33));
2459
+ }, async ({ goalId }) => handleGetGoalStatus({ ...goalId !== void 0 ? { goalId } : {} }, DATA_DIR$34));
2459
2460
  }
2460
2461
  //#endregion
2461
2462
  //#region src/mcp/tools/register-push-subscription.ts
2462
- const DATA_DIR$32 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2463
+ const DATA_DIR$33 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2463
2464
  const VALID_PROVIDERS = [
2464
2465
  "gmail",
2465
2466
  "microsoft-graph",
2466
2467
  "slack"
2467
2468
  ];
2468
- async function handleRegisterPushSubscription(input, dataDir = DATA_DIR$32) {
2469
+ async function handleRegisterPushSubscription(input, dataDir = DATA_DIR$33) {
2469
2470
  try {
2470
2471
  if (!VALID_PROVIDERS.includes(input.provider)) return { content: [{
2471
2472
  type: "text",
@@ -2551,12 +2552,12 @@ Returns: { subscriptionId, provider, slug, status, expiresAt, createdAt, warning
2551
2552
  ...microsoftResource !== void 0 ? { microsoftResource } : {},
2552
2553
  ...slackTeamId !== void 0 ? { slackTeamId } : {},
2553
2554
  ...slackChannelId !== void 0 ? { slackChannelId } : {}
2554
- }, DATA_DIR$32));
2555
+ }, DATA_DIR$33));
2555
2556
  }
2556
2557
  //#endregion
2557
2558
  //#region src/mcp/tools/get-push-status.ts
2558
- const DATA_DIR$31 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2559
- async function handleGetPushStatus(input, dataDir = DATA_DIR$31) {
2559
+ const DATA_DIR$32 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2560
+ async function handleGetPushStatus(input, dataDir = DATA_DIR$32) {
2560
2561
  try {
2561
2562
  let subs = await readSubscriptions(dataDir);
2562
2563
  if (input.slug) subs = subs.filter((s) => s.slug === input.slug);
@@ -2628,7 +2629,7 @@ Returns: { subscriptions: [{ id, provider, slug, status, expiresAt, expiresInHou
2628
2629
  }, async ({ slug, provider }) => handleGetPushStatus({
2629
2630
  ...slug !== void 0 ? { slug } : {},
2630
2631
  ...provider !== void 0 ? { provider } : {}
2631
- }, DATA_DIR$31));
2632
+ }, DATA_DIR$32));
2632
2633
  }
2633
2634
  //#endregion
2634
2635
  //#region src/core/org-intelligence.ts
@@ -2694,8 +2695,8 @@ function deriveRecommendation(people, missingRoles) {
2694
2695
  }
2695
2696
  //#endregion
2696
2697
  //#region src/mcp/tools/get-org-intelligence.ts
2697
- const DATA_DIR$30 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2698
- async function handleGetOrgIntelligence(input, dataDir = DATA_DIR$30) {
2698
+ const DATA_DIR$31 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2699
+ async function handleGetOrgIntelligence(input, dataDir = DATA_DIR$31) {
2699
2700
  try {
2700
2701
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
2701
2702
  const map = buildStakeholderMap(dataDir, input.slug, today, input.dealName);
@@ -2828,8 +2829,8 @@ function buildExecutiveSummary(slug, dealName, stakeholders, overallHealth, sim,
2828
2829
  }
2829
2830
  //#endregion
2830
2831
  //#region src/mcp/tools/open-deal-room.ts
2831
- const DATA_DIR$29 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2832
- async function handleOpenDealRoom(input, dataDir = DATA_DIR$29) {
2832
+ const DATA_DIR$30 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2833
+ async function handleOpenDealRoom(input, dataDir = DATA_DIR$30) {
2833
2834
  try {
2834
2835
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
2835
2836
  const brief = await buildDealRoom(dataDir, input.slug, input.dealName, today);
@@ -2864,8 +2865,8 @@ Returns: { slug, dealName, generatedAt, stakeholders, relationshipHealth, dealHe
2864
2865
  }
2865
2866
  //#endregion
2866
2867
  //#region src/mcp/tools/get-proactive-briefing.ts
2867
- const DATA_DIR$28 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2868
- async function handleGetProactiveBriefing(input, dataDir = DATA_DIR$28) {
2868
+ const DATA_DIR$29 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2869
+ async function handleGetProactiveBriefing(input, dataDir = DATA_DIR$29) {
2869
2870
  try {
2870
2871
  const briefing = await buildDailyBriefing(dataDir, input.date ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10));
2871
2872
  return { content: [{
@@ -2893,15 +2894,15 @@ Returns: { date, generatedAt, urgent: string[], opportunities: string[], forecas
2893
2894
  }
2894
2895
  //#endregion
2895
2896
  //#region src/mcp/tools/list-email-templates.ts
2896
- const DATA_DIR$27 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2897
- async function handleListEmailTemplates(input, dataDir = DATA_DIR$27) {
2897
+ const DATA_DIR$28 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2898
+ async function handleListEmailTemplates(input, dataDir = DATA_DIR$28) {
2898
2899
  const summary = listTemplates(dataDir, input.category ? { category: input.category } : {}).map(({ body: _body, ...meta }) => meta);
2899
2900
  return { content: [{
2900
2901
  type: "text",
2901
2902
  text: JSON.stringify(summary, null, 2)
2902
2903
  }] };
2903
2904
  }
2904
- function registerListEmailTemplates(server, dataDir = DATA_DIR$27) {
2905
+ function registerListEmailTemplates(server, dataDir = DATA_DIR$28) {
2905
2906
  server.registerTool("list_email_templates", {
2906
2907
  description: "List available email templates. Optionally filter by category (e.g. 'outreach', 'followup', 'support').",
2907
2908
  inputSchema: z.object({ category: z.string().optional().describe("Filter by category") })
@@ -2909,8 +2910,8 @@ function registerListEmailTemplates(server, dataDir = DATA_DIR$27) {
2909
2910
  }
2910
2911
  //#endregion
2911
2912
  //#region src/mcp/tools/get-email-template.ts
2912
- const DATA_DIR$26 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2913
- async function handleGetEmailTemplate(input, dataDir = DATA_DIR$26) {
2913
+ const DATA_DIR$27 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2914
+ async function handleGetEmailTemplate(input, dataDir = DATA_DIR$27) {
2914
2915
  const tmpl = getTemplate(dataDir, input.id);
2915
2916
  if (!tmpl) return { content: [{
2916
2917
  type: "text",
@@ -2926,7 +2927,7 @@ async function handleGetEmailTemplate(input, dataDir = DATA_DIR$26) {
2926
2927
  }, null, 2)
2927
2928
  }] };
2928
2929
  }
2929
- function registerGetEmailTemplate(server, dataDir = DATA_DIR$26) {
2930
+ function registerGetEmailTemplate(server, dataDir = DATA_DIR$27) {
2930
2931
  server.registerTool("get_email_template", {
2931
2932
  description: "Get a specific email template by ID, including its body and detected variables.",
2932
2933
  inputSchema: z.object({ id: z.string().describe("Template ID (e.g. 'enterprise-intro')") })
@@ -2934,8 +2935,8 @@ function registerGetEmailTemplate(server, dataDir = DATA_DIR$26) {
2934
2935
  }
2935
2936
  //#endregion
2936
2937
  //#region src/mcp/tools/draft-email.ts
2937
- const DATA_DIR$25 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2938
- async function handleDraftEmail(input, dataDir = DATA_DIR$25) {
2938
+ const DATA_DIR$26 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2939
+ async function handleDraftEmail(input, dataDir = DATA_DIR$26) {
2939
2940
  const tmpl = getTemplate(dataDir, input.templateId);
2940
2941
  if (!tmpl) return { content: [{
2941
2942
  type: "text",
@@ -2979,7 +2980,7 @@ async function handleDraftEmail(input, dataDir = DATA_DIR$25) {
2979
2980
  }, null, 2)
2980
2981
  }] };
2981
2982
  }
2982
- function registerDraftEmail(server, dataDir = DATA_DIR$25) {
2983
+ function registerDraftEmail(server, dataDir = DATA_DIR$26) {
2983
2984
  server.registerTool("draft_email", {
2984
2985
  description: `Draft a personalized email for a customer using a stored template.
2985
2986
  Variables are auto-filled from the customer's main_facts.md. Override any variable manually.
@@ -3001,8 +3002,8 @@ Returns: { subject, body, to, tone, polished, resolvedVariables } — does NOT s
3001
3002
  }
3002
3003
  //#endregion
3003
3004
  //#region src/mcp/tools/enroll-in-sequence.ts
3004
- const DATA_DIR$24 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3005
- async function handleEnrollInSequence(input, dataDir = DATA_DIR$24) {
3005
+ const DATA_DIR$25 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3006
+ async function handleEnrollInSequence(input, dataDir = DATA_DIR$25) {
3006
3007
  const sequence = getSequence(dataDir, input.sequenceId);
3007
3008
  if (!sequence) return { content: [{
3008
3009
  type: "text",
@@ -3034,7 +3035,7 @@ async function handleEnrollInSequence(input, dataDir = DATA_DIR$24) {
3034
3035
  })
3035
3036
  }] };
3036
3037
  }
3037
- function registerEnrollInSequence(server, dataDir = DATA_DIR$24) {
3038
+ function registerEnrollInSequence(server, dataDir = DATA_DIR$25) {
3038
3039
  server.registerTool("enroll_in_sequence", {
3039
3040
  description: `Enroll a contact in an email sequence. Validates that the sequence and its first template exist.
3040
3041
  Returns: { enrollmentId, sequenceName, totalSteps }`,
@@ -3051,8 +3052,8 @@ Returns: { enrollmentId, sequenceName, totalSteps }`,
3051
3052
  }
3052
3053
  //#endregion
3053
3054
  //#region src/mcp/tools/list-sequence-enrollments.ts
3054
- const DATA_DIR$23 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3055
- async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$23) {
3055
+ const DATA_DIR$24 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3056
+ async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$24) {
3056
3057
  let enrollments = readEnrollments(dataDir);
3057
3058
  if (input.slug !== void 0) enrollments = enrollments.filter((e) => e.slug === input.slug);
3058
3059
  if (input.status !== void 0) enrollments = enrollments.filter((e) => e.status === input.status);
@@ -3061,7 +3062,7 @@ async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$23) {
3061
3062
  text: JSON.stringify({ enrollments }, null, 2)
3062
3063
  }] };
3063
3064
  }
3064
- function registerListSequenceEnrollments(server, dataDir = DATA_DIR$23) {
3065
+ function registerListSequenceEnrollments(server, dataDir = DATA_DIR$24) {
3065
3066
  server.registerTool("list_sequence_enrollments", {
3066
3067
  description: `List email sequence enrollments. Filter by customer slug or status.
3067
3068
  Returns: { enrollments: SequenceEnrollment[] }`,
@@ -3080,8 +3081,8 @@ Returns: { enrollments: SequenceEnrollment[] }`,
3080
3081
  }
3081
3082
  //#endregion
3082
3083
  //#region src/mcp/tools/unenroll-from-sequence.ts
3083
- const DATA_DIR$22 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3084
- async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$22) {
3084
+ const DATA_DIR$23 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3085
+ async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$23) {
3085
3086
  if (!await updateEnrollment(dataDir, input.enrollmentId, { status: "paused" })) return { content: [{
3086
3087
  type: "text",
3087
3088
  text: JSON.stringify({
@@ -3094,7 +3095,7 @@ async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$22) {
3094
3095
  text: JSON.stringify({ success: true })
3095
3096
  }] };
3096
3097
  }
3097
- function registerUnenrollFromSequence(server, dataDir = DATA_DIR$22) {
3098
+ function registerUnenrollFromSequence(server, dataDir = DATA_DIR$23) {
3098
3099
  server.registerTool("unenroll_from_sequence", {
3099
3100
  description: `Unenroll (pause) a contact from an email sequence. Sets status to "paused" (soft delete).
3100
3101
  Returns: { success: boolean }`,
@@ -3103,8 +3104,8 @@ Returns: { success: boolean }`,
3103
3104
  }
3104
3105
  //#endregion
3105
3106
  //#region src/mcp/tools/list-sequences.ts
3106
- const DATA_DIR$21 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3107
- async function handleListSequences(_input, dataDir = DATA_DIR$21) {
3107
+ const DATA_DIR$22 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3108
+ async function handleListSequences(_input, dataDir = DATA_DIR$22) {
3108
3109
  const sequences = listSequences(dataDir);
3109
3110
  const enrollments = readEnrollments(dataDir);
3110
3111
  const result = sequences.map((seq) => ({
@@ -3118,7 +3119,7 @@ async function handleListSequences(_input, dataDir = DATA_DIR$21) {
3118
3119
  text: JSON.stringify({ sequences: result }, null, 2)
3119
3120
  }] };
3120
3121
  }
3121
- function registerListSequences(server, dataDir = DATA_DIR$21) {
3122
+ function registerListSequences(server, dataDir = DATA_DIR$22) {
3122
3123
  server.registerTool("list_sequences", {
3123
3124
  description: `List all email sequences with step count and enrollment count.
3124
3125
  Returns: { sequences: Array<{ id, name, stepCount, enrollmentCount }> }`,
@@ -3127,8 +3128,8 @@ Returns: { sequences: Array<{ id, name, stepCount, enrollmentCount }> }`,
3127
3128
  }
3128
3129
  //#endregion
3129
3130
  //#region src/mcp/tools/generate-quote.ts
3130
- const DATA_DIR$20 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3131
- async function handleGenerateQuote(input, dataDir = DATA_DIR$20) {
3131
+ const DATA_DIR$21 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3132
+ async function handleGenerateQuote(input, dataDir = DATA_DIR$21) {
3132
3133
  try {
3133
3134
  const quote = await generateQuote(dataDir, input);
3134
3135
  return { content: [{
@@ -3152,7 +3153,7 @@ async function handleGenerateQuote(input, dataDir = DATA_DIR$20) {
3152
3153
  }] };
3153
3154
  }
3154
3155
  }
3155
- function registerGenerateQuote(server, dataDir = DATA_DIR$20) {
3156
+ function registerGenerateQuote(server, dataDir = DATA_DIR$21) {
3156
3157
  server.registerTool("generate_quote", {
3157
3158
  description: `Generate a professional HTML quote/offer for a customer deal.
3158
3159
  Calculates subtotal, VAT, and total. Saves JSON + HTML to .agentic/quotes/.
@@ -3180,8 +3181,8 @@ Returns: { quoteNumber, htmlPath, total, currency, validUntil }`,
3180
3181
  }
3181
3182
  //#endregion
3182
3183
  //#region src/mcp/tools/get-quote-status.ts
3183
- const DATA_DIR$19 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3184
- async function handleGetQuoteStatus(input, dataDir = DATA_DIR$19) {
3184
+ const DATA_DIR$20 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3185
+ async function handleGetQuoteStatus(input, dataDir = DATA_DIR$20) {
3185
3186
  if (input.quoteNumber) {
3186
3187
  const quote = readQuote(dataDir, input.quoteNumber);
3187
3188
  if (!quote) return { content: [{
@@ -3199,7 +3200,7 @@ async function handleGetQuoteStatus(input, dataDir = DATA_DIR$19) {
3199
3200
  text: JSON.stringify({ quotes }, null, 2)
3200
3201
  }] };
3201
3202
  }
3202
- function registerGetQuoteStatus(server, dataDir = DATA_DIR$19) {
3203
+ function registerGetQuoteStatus(server, dataDir = DATA_DIR$20) {
3203
3204
  server.registerTool("get_quote_status", {
3204
3205
  description: `Get quote status and details. Filter by quoteNumber (single quote) or slug (all quotes for a customer).
3205
3206
  Returns quote with status: draft | sent | viewed | accepted | declined`,
@@ -3214,7 +3215,7 @@ Returns quote with status: draft | sent | viewed | accepted | declined`,
3214
3215
  }
3215
3216
  //#endregion
3216
3217
  //#region src/mcp/tools/get-booking-link.ts
3217
- const DATA_DIR$18 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3218
+ const DATA_DIR$19 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3218
3219
  function loadCalendlyConfig(dataDir) {
3219
3220
  const p = path.join(dataDir, ".agentic", "integrations", "calendly.yaml");
3220
3221
  if (!fs.existsSync(p)) return {};
@@ -3237,7 +3238,7 @@ function readCustomerFacts(dataDir, slug) {
3237
3238
  ...email ? { email } : {}
3238
3239
  };
3239
3240
  }
3240
- async function handleGetBookingLink(input, dataDir = DATA_DIR$18) {
3241
+ async function handleGetBookingLink(input, dataDir = DATA_DIR$19) {
3241
3242
  const config = loadCalendlyConfig(dataDir);
3242
3243
  const apiKey = config.apiKey ?? process.env["CALENDLY_API_KEY"] ?? "";
3243
3244
  if (!apiKey) return { content: [{
@@ -3265,7 +3266,7 @@ async function handleGetBookingLink(input, dataDir = DATA_DIR$18) {
3265
3266
  }] };
3266
3267
  }
3267
3268
  }
3268
- function registerGetBookingLink(server, dataDir = DATA_DIR$18) {
3269
+ function registerGetBookingLink(server, dataDir = DATA_DIR$19) {
3269
3270
  server.registerTool("get_booking_link", {
3270
3271
  description: `Get a Calendly booking link for a customer. Optionally pre-fills the customer's name/email.
3271
3272
  Requires CALENDLY_API_KEY env var or .agentic/integrations/calendly.yaml config.
@@ -3283,8 +3284,8 @@ Returns: { bookingUrl, eventType, duration }`,
3283
3284
  }
3284
3285
  //#endregion
3285
3286
  //#region src/mcp/tools/create-ticket.ts
3286
- const DATA_DIR$17 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3287
- async function handleCreateTicket(input, dataDir = DATA_DIR$17) {
3287
+ const DATA_DIR$18 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3288
+ async function handleCreateTicket(input, dataDir = DATA_DIR$18) {
3288
3289
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
3289
3290
  const rules = loadSlaRules(dataDir);
3290
3291
  const priority = input.priority ?? "normal";
@@ -3306,7 +3307,7 @@ async function handleCreateTicket(input, dataDir = DATA_DIR$17) {
3306
3307
  text: JSON.stringify({ ticket }, null, 2)
3307
3308
  }] };
3308
3309
  }
3309
- function registerCreateTicket(server, dataDir = DATA_DIR$17) {
3310
+ function registerCreateTicket(server, dataDir = DATA_DIR$18) {
3310
3311
  server.registerTool("create_ticket", {
3311
3312
  description: `Create a support ticket for a customer. Auto-calculates SLA due date based on priority.
3312
3313
  Returns: { ticket } with id T-NNN, status=open, slaDue`,
@@ -3332,8 +3333,8 @@ Returns: { ticket } with id T-NNN, status=open, slaDue`,
3332
3333
  }
3333
3334
  //#endregion
3334
3335
  //#region src/mcp/tools/update-ticket.ts
3335
- const DATA_DIR$16 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3336
- async function handleUpdateTicket(input, dataDir = DATA_DIR$16) {
3336
+ const DATA_DIR$17 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3337
+ async function handleUpdateTicket(input, dataDir = DATA_DIR$17) {
3337
3338
  const ticket = (await readTickets(dataDir, input.slug)).find((t) => t.id === input.ticketId);
3338
3339
  if (!ticket) return { content: [{
3339
3340
  type: "text",
@@ -3352,7 +3353,7 @@ async function handleUpdateTicket(input, dataDir = DATA_DIR$16) {
3352
3353
  text: JSON.stringify({ ticket: updated }, null, 2)
3353
3354
  }] };
3354
3355
  }
3355
- function registerUpdateTicket(server, dataDir = DATA_DIR$16) {
3356
+ function registerUpdateTicket(server, dataDir = DATA_DIR$17) {
3356
3357
  server.registerTool("update_ticket", {
3357
3358
  description: `Update a ticket's status or assignee. Setting status=resolved auto-sets resolved date.
3358
3359
  Returns: { ticket }`,
@@ -3377,8 +3378,8 @@ Returns: { ticket }`,
3377
3378
  }
3378
3379
  //#endregion
3379
3380
  //#region src/mcp/tools/list-tickets.ts
3380
- const DATA_DIR$15 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3381
- async function handleListTickets(input, dataDir = DATA_DIR$15) {
3381
+ const DATA_DIR$16 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3382
+ async function handleListTickets(input, dataDir = DATA_DIR$16) {
3382
3383
  const results = await listAllTickets(dataDir, {
3383
3384
  ...input.slug !== void 0 ? { slug: input.slug } : {},
3384
3385
  ...input.status !== void 0 ? { status: input.status } : {},
@@ -3390,7 +3391,7 @@ async function handleListTickets(input, dataDir = DATA_DIR$15) {
3390
3391
  text: JSON.stringify({ tickets: results }, null, 2)
3391
3392
  }] };
3392
3393
  }
3393
- function registerListTickets(server, dataDir = DATA_DIR$15) {
3394
+ function registerListTickets(server, dataDir = DATA_DIR$16) {
3394
3395
  server.registerTool("list_tickets", {
3395
3396
  description: `List support tickets. Filter by customer, status, priority, or assignee. Sorted by priority then date.
3396
3397
  Returns: { tickets: Array<{ slug, ticket }> }`,
@@ -3420,8 +3421,8 @@ Returns: { tickets: Array<{ slug, ticket }> }`,
3420
3421
  }
3421
3422
  //#endregion
3422
3423
  //#region src/mcp/tools/close-ticket.ts
3423
- const DATA_DIR$14 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3424
- async function handleCloseTicket(input, dataDir = DATA_DIR$14) {
3424
+ const DATA_DIR$15 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3425
+ async function handleCloseTicket(input, dataDir = DATA_DIR$15) {
3425
3426
  const ticket = (await readTickets(dataDir, input.slug)).find((t) => t.id === input.ticketId);
3426
3427
  if (!ticket) return { content: [{
3427
3428
  type: "text",
@@ -3448,7 +3449,7 @@ async function handleCloseTicket(input, dataDir = DATA_DIR$14) {
3448
3449
  text: JSON.stringify({ ticket: updated }, null, 2)
3449
3450
  }] };
3450
3451
  }
3451
- function registerCloseTicket(server, dataDir = DATA_DIR$14) {
3452
+ function registerCloseTicket(server, dataDir = DATA_DIR$15) {
3452
3453
  server.registerTool("close_ticket", {
3453
3454
  description: `Close a support ticket. Optionally logs the resolution as an interaction.
3454
3455
  Returns: { ticket } with status=closed`,
@@ -3465,8 +3466,8 @@ Returns: { ticket } with status=closed`,
3465
3466
  }
3466
3467
  //#endregion
3467
3468
  //#region src/mcp/tools/send-nps-survey.ts
3468
- const DATA_DIR$13 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3469
- async function handleSendNpsSurvey(input, dataDir = DATA_DIR$13) {
3469
+ const DATA_DIR$14 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3470
+ async function handleSendNpsSurvey(input, dataDir = DATA_DIR$14) {
3470
3471
  const survey = getSurvey(dataDir, input.surveyId);
3471
3472
  if (!survey) return { content: [{
3472
3473
  type: "text",
@@ -3487,7 +3488,7 @@ async function handleSendNpsSurvey(input, dataDir = DATA_DIR$13) {
3487
3488
  }, null, 2)
3488
3489
  }] };
3489
3490
  }
3490
- function registerSendNpsSurvey(server, dataDir = DATA_DIR$13) {
3491
+ function registerSendNpsSurvey(server, dataDir = DATA_DIR$14) {
3491
3492
  server.registerTool("send_nps_survey", {
3492
3493
  description: `Generate an NPS/CSAT survey email for a customer contact. Returns subject, HTML body, and a token-based response URL.
3493
3494
  Does NOT send automatically — returns draft for review.
@@ -3507,8 +3508,8 @@ Returns: { token, subject, body, surveyUrl }`,
3507
3508
  }
3508
3509
  //#endregion
3509
3510
  //#region src/mcp/tools/get-survey-results.ts
3510
- const DATA_DIR$12 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3511
- async function handleGetSurveyResults(input, dataDir = DATA_DIR$12) {
3511
+ const DATA_DIR$13 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3512
+ async function handleGetSurveyResults(input, dataDir = DATA_DIR$13) {
3512
3513
  const responses = loadSurveyResponses(dataDir, input.surveyId, input.slug);
3513
3514
  const nps = calcNpsScore(responses);
3514
3515
  const promoters = responses.filter((r) => r.score >= 9).length;
@@ -3534,7 +3535,7 @@ async function handleGetSurveyResults(input, dataDir = DATA_DIR$12) {
3534
3535
  }, null, 2)
3535
3536
  }] };
3536
3537
  }
3537
- function registerGetSurveyResults(server, dataDir = DATA_DIR$12) {
3538
+ function registerGetSurveyResults(server, dataDir = DATA_DIR$13) {
3538
3539
  server.registerTool("get_survey_results", {
3539
3540
  description: `Get NPS/CSAT survey results with score breakdown. Calculates Net Promoter Score.
3540
3541
  Returns: { npsScore, totalResponses, promoters, passives, detractors, responses[] }`,
@@ -3549,8 +3550,8 @@ Returns: { npsScore, totalResponses, promoters, passives, detractors, responses[
3549
3550
  }
3550
3551
  //#endregion
3551
3552
  //#region src/mcp/tools/search-knowledge-base.ts
3552
- const DATA_DIR$11 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3553
- async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$11) {
3553
+ const DATA_DIR$12 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3554
+ async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$12) {
3554
3555
  const results = searchKbSimple(dataDir, input.query, { ...input.publicOnly ? { publicOnly: true } : {} });
3555
3556
  const limited = (input.category ? results.filter((a) => a.category === input.category) : results).slice(0, input.limit ?? 10);
3556
3557
  return { content: [{
@@ -3565,7 +3566,7 @@ async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$11) {
3565
3566
  }, null, 2)
3566
3567
  }] };
3567
3568
  }
3568
- function registerSearchKnowledgeBase(server, dataDir = DATA_DIR$11) {
3569
+ function registerSearchKnowledgeBase(server, dataDir = DATA_DIR$12) {
3569
3570
  server.registerTool("search_knowledge_base", {
3570
3571
  description: `Search the knowledge base for articles. Text search on title, body, and tags.
3571
3572
  Returns: { count, articles[] } with excerpts`,
@@ -3584,8 +3585,8 @@ Returns: { count, articles[] } with excerpts`,
3584
3585
  }
3585
3586
  //#endregion
3586
3587
  //#region src/mcp/tools/create-kb-article.ts
3587
- const DATA_DIR$10 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3588
- async function handleCreateKbArticle(input, dataDir = DATA_DIR$10) {
3588
+ const DATA_DIR$11 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3589
+ async function handleCreateKbArticle(input, dataDir = DATA_DIR$11) {
3589
3590
  if (getKbArticle(dataDir, input.id)) return { content: [{
3590
3591
  type: "text",
3591
3592
  text: JSON.stringify({ error: `Article '${input.id}' already exists` })
@@ -3613,7 +3614,7 @@ async function handleCreateKbArticle(input, dataDir = DATA_DIR$10) {
3613
3614
  }, null, 2)
3614
3615
  }] };
3615
3616
  }
3616
- function registerCreateKbArticle(server, dataDir = DATA_DIR$10) {
3617
+ function registerCreateKbArticle(server, dataDir = DATA_DIR$11) {
3617
3618
  server.registerTool("create_kb_article", {
3618
3619
  description: `Create a new knowledge base article. Articles are stored as Markdown files in .agentic/knowledge-base/.
3619
3620
  Returns: { id, title, category, path }`,
@@ -3638,8 +3639,8 @@ Returns: { id, title, category, path }`,
3638
3639
  }
3639
3640
  //#endregion
3640
3641
  //#region src/mcp/tools/backup-now.ts
3641
- const DATA_DIR$9 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3642
- async function handleBackupNow(input, dataDir = DATA_DIR$9) {
3642
+ const DATA_DIR$10 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3643
+ async function handleBackupNow(input, dataDir = DATA_DIR$10) {
3643
3644
  const zipPath = path.join(dataDir, `dxcrm-backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19)}.zip`);
3644
3645
  const manifest = await runBackup(zipPath, dataDir, { ...input.remote ? { remote: input.remote } : {} }).catch(() => null);
3645
3646
  if (!manifest) return { content: [{
@@ -3676,8 +3677,8 @@ function registerBackupNow(server) {
3676
3677
  }
3677
3678
  //#endregion
3678
3679
  //#region src/mcp/tools/list-backups.ts
3679
- const DATA_DIR$8 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3680
- async function handleListBackups(input, dataDir = DATA_DIR$8) {
3680
+ const DATA_DIR$9 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3681
+ async function handleListBackups(input, dataDir = DATA_DIR$9) {
3681
3682
  const logEntries = readBackupLog(dataDir);
3682
3683
  const fileEntries = listBackupsInDir(dataDir);
3683
3684
  const entries = logEntries.length > 0 ? logEntries : fileEntries;
@@ -3711,8 +3712,8 @@ function registerListBackups(server) {
3711
3712
  }
3712
3713
  //#endregion
3713
3714
  //#region src/mcp/tools/trigger-sync.ts
3714
- const DATA_DIR$7 = process.cwd();
3715
- async function handleTriggerSync(input, dataDir = DATA_DIR$7) {
3715
+ const DATA_DIR$8 = process.cwd();
3716
+ async function handleTriggerSync(input, dataDir = DATA_DIR$8) {
3716
3717
  const auth = getGmailAuth();
3717
3718
  if (!auth) return { content: [{
3718
3719
  type: "text",
@@ -3806,8 +3807,8 @@ Returns: { success: boolean, synced: number, skipped: number, customers: [...],
3806
3807
  }
3807
3808
  //#endregion
3808
3809
  //#region src/mcp/tools/get-audit-log.ts
3809
- const DATA_DIR$6 = process.cwd();
3810
- async function handleGetAuditLog(input, dataDir = DATA_DIR$6) {
3810
+ const DATA_DIR$7 = process.cwd();
3811
+ async function handleGetAuditLog(input, dataDir = DATA_DIR$7) {
3811
3812
  const entries = readAuditLog(dataDir);
3812
3813
  const filterOpts = { limit: input.limit ?? 50 };
3813
3814
  if (input.slug !== void 0) filterOpts.slug = input.slug;
@@ -3849,8 +3850,8 @@ Returns: { total: number, returned: number, entries: [{timestamp, actor, tool, s
3849
3850
  }
3850
3851
  //#endregion
3851
3852
  //#region src/mcp/tools/get-logs.ts
3852
- const DATA_DIR$5 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3853
- async function handleGetLogs(input, dataDir = DATA_DIR$5) {
3853
+ const DATA_DIR$6 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3854
+ async function handleGetLogs(input, dataDir = DATA_DIR$6) {
3854
3855
  const query = {
3855
3856
  ...input.level !== void 0 ? { level: input.level } : {},
3856
3857
  ...input.component !== void 0 ? { component: input.component } : {},
@@ -3912,8 +3913,8 @@ Returns (summary): { total, byLevel, byComponent, firstTs, lastTs, recentErrors
3912
3913
  }
3913
3914
  //#endregion
3914
3915
  //#region src/mcp/tools/get-diagnostics.ts
3915
- const DATA_DIR$4 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3916
- async function handleGetDiagnostics(input, dataDir = DATA_DIR$4) {
3916
+ const DATA_DIR$5 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3917
+ async function handleGetDiagnostics(input, dataDir = DATA_DIR$5) {
3917
3918
  let cleaned = 0;
3918
3919
  if (input.fix) {
3919
3920
  const { cleanupTempFiles } = await import("./doctor-CYDaNmFn.js");
@@ -3946,11 +3947,11 @@ Returns: { ok: boolean, tempFilesRemoved?: number, checks: [{ name, status: "ok"
3946
3947
  }
3947
3948
  //#endregion
3948
3949
  //#region src/mcp/tools/get-pipeline-changes.ts
3949
- const DATA_DIR$3 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3950
+ const DATA_DIR$4 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3950
3951
  function daysAgoIso(days) {
3951
3952
  return (/* @__PURE__ */ new Date(Date.now() - days * 864e5)).toISOString().slice(0, 10);
3952
3953
  }
3953
- async function handleGetPipelineChanges(input, dataDir = DATA_DIR$3) {
3954
+ async function handleGetPipelineChanges(input, dataDir = DATA_DIR$4) {
3954
3955
  const since = input.since ?? daysAgoIso(input.days ?? 7);
3955
3956
  const diff = diffAgainstNow(dataDir, since);
3956
3957
  const payload = diff ? diff : { error: `No pipeline snapshot at or before ${since}. Snapshots accrue daily via the daemon.` };
@@ -3986,8 +3987,8 @@ or { error } when no baseline snapshot exists yet.`,
3986
3987
  }
3987
3988
  //#endregion
3988
3989
  //#region src/mcp/tools/get-pipeline-velocity.ts
3989
- const DATA_DIR$2 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3990
- async function handleGetPipelineVelocity(input, dataDir = DATA_DIR$2) {
3990
+ const DATA_DIR$3 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3991
+ async function handleGetPipelineVelocity(input, dataDir = DATA_DIR$3) {
3991
3992
  const opts = {};
3992
3993
  if (input.stalledDays !== void 0) opts.stalledDays = input.stalledDays;
3993
3994
  const report = analyzeVelocity(dataDir, opts);
@@ -4018,6 +4019,31 @@ stalledThresholdDays }. snapshotCount is 0 until the daemon has taken snapshots.
4018
4019
  });
4019
4020
  }
4020
4021
  //#endregion
4022
+ //#region src/mcp/tools/get-pipeline-funnel.ts
4023
+ const DATA_DIR$2 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
4024
+ async function handleGetPipelineFunnel(_input, dataDir = DATA_DIR$2) {
4025
+ const report = analyzeFunnel(dataDir);
4026
+ return { content: [{
4027
+ type: "text",
4028
+ text: JSON.stringify(report, null, 2)
4029
+ }] };
4030
+ }
4031
+ function registerGetPipelineFunnel(server) {
4032
+ server.registerTool("get_pipeline_funnel", {
4033
+ title: "Get Pipeline Funnel",
4034
+ description: `Pipeline conversion funnel & win-rate from the daily snapshot history.
4035
+ For each deal it tracks the furthest stage reached and the win/lost outcome,
4036
+ then builds a cumulative funnel. Answers "where do deals leak out of my
4037
+ pipeline?" and "what's my win rate?".
4038
+
4039
+ Returns: { fromId, toId, snapshotCount,
4040
+ stages[{stage, reached, conversionPctToNext}], wonCount, lostCount, winRatePct,
4041
+ biggestLeak{from,to,conversionPct} }. snapshotCount is 0 until the daemon has
4042
+ taken snapshots.`,
4043
+ inputSchema: z.object({})
4044
+ }, async () => handleGetPipelineFunnel({}));
4045
+ }
4046
+ //#endregion
4021
4047
  //#region src/mcp/prompts.ts
4022
4048
  /**
4023
4049
  * CRM playbook prompts exposed via MCP `prompts/list` + `prompts/get`.
@@ -4277,6 +4303,7 @@ function createMcpServer() {
4277
4303
  registerGetDiagnostics(server);
4278
4304
  registerGetPipelineChanges(server);
4279
4305
  registerGetPipelineVelocity(server);
4306
+ registerGetPipelineFunnel(server);
4280
4307
  registerCustomObjectTools(server);
4281
4308
  registerPrompts(server);
4282
4309
  registerResources(server);
@@ -4475,4 +4502,4 @@ else startStdio().catch((err) => {
4475
4502
  //#endregion
4476
4503
  export { startHttp, startStdio };
4477
4504
 
4478
- //# sourceMappingURL=server-C0XkJQBo.js.map
4505
+ //# sourceMappingURL=server-DAcwmRPE.js.map