@datasynx/agentic-crm 1.7.0 → 1.8.0

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