@datasynx/agentic-crm 1.1.0 → 1.3.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--063Kpa3.js";
5
+ import { a as searchKbSimple, n as getKbArticle, o as writeKbArticle, r as getKbMetaForExport, s as CAPABILITIES_TEXT } from "./knowledge-base-Bx2PKQR2.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";
@@ -23,6 +23,7 @@ import { i as loadSlaRules, t as calcSlaDue } from "./sla-engine-O-A1ntu_.js";
23
23
  import { i as getSurvey, l as savePendingSurvey, n as calcNpsScore, o as loadSurveyResponses, r as generateSurveyToken, t as buildSurveyEmail } from "./survey-engine-DngXBv47.js";
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
+ import { n as runDiagnostics } from "./doctor-BFeelnq8.js";
26
27
  import { r as searchKnowledge } from "./lancedb-CuHKNsNZ.js";
27
28
  import { t as buildDailyBriefing } from "./proactive-agent-B7u3Bj_l.js";
28
29
  import { a as protectedResourceMetadata, o as verifyBearer, r as isAuthRequired, s as wwwAuthenticateHeader } from "./auth-DDXZTwS0.js";
@@ -254,7 +255,7 @@ function registerGetActiveSession(server) {
254
255
  }
255
256
  //#endregion
256
257
  //#region src/mcp/tools/get-customer-context.ts
257
- const DATA_DIR$51 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
258
+ const DATA_DIR$52 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
258
259
  function triggerOnQuerySync(dataDir, slug) {
259
260
  const auth = getGmailAuth();
260
261
  if (!auth) return;
@@ -275,7 +276,7 @@ function triggerOnQuerySync(dataDir, slug) {
275
276
  }).then(() => updateSlugSyncState(dataDir, slug, { lastGmailSync: (/* @__PURE__ */ new Date()).toISOString() })).catch(() => {})).catch(() => {});
276
277
  } catch {}
277
278
  }
278
- async function handleGetCustomerContext(input, dataDir = DATA_DIR$51) {
279
+ async function handleGetCustomerContext(input, dataDir = DATA_DIR$52) {
279
280
  const targetSlug = input.slug ?? getSession()?.customerSlug;
280
281
  if (!targetSlug) return {
281
282
  content: [{
@@ -327,8 +328,8 @@ Performance: <3 seconds. Token budget: <3000.`,
327
328
  }
328
329
  //#endregion
329
330
  //#region src/mcp/tools/search-customer-knowledge.ts
330
- const DATA_DIR$50 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
331
- async function handleSearchCustomerKnowledge(input, dataDir = DATA_DIR$50) {
331
+ const DATA_DIR$51 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
332
+ async function handleSearchCustomerKnowledge(input, dataDir = DATA_DIR$51) {
332
333
  const limit = input.limit ?? 5;
333
334
  try {
334
335
  const results = await searchKnowledge(dataDir, input.slug, input.query, limit);
@@ -376,14 +377,14 @@ If no results: returns empty array with a helpful sync suggestion.`,
376
377
  }
377
378
  //#endregion
378
379
  //#region src/mcp/tools/list-customers.ts
379
- const DATA_DIR$49 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
380
+ const DATA_DIR$50 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
380
381
  function extractLastInteractionDate(interactionsPath) {
381
382
  if (!fs.existsSync(interactionsPath)) return void 0;
382
383
  const content = fs.readFileSync(interactionsPath, "utf-8");
383
384
  const match = /^## (\d{4}-\d{2}-\d{2})/m.exec(content);
384
385
  return match ? match[1] : void 0;
385
386
  }
386
- async function handleListCustomers(input, dataDir = DATA_DIR$49) {
387
+ async function handleListCustomers(input, dataDir = DATA_DIR$50) {
387
388
  const customersDir = path.join(dataDir, "customers");
388
389
  const customers = [];
389
390
  if (!fs.existsSync(customersDir)) return { content: [{
@@ -444,8 +445,8 @@ Returns: Array of { slug, name, stage, lastInteraction?, dealValue? }`,
444
445
  }
445
446
  //#endregion
446
447
  //#region src/mcp/tools/log-interaction.ts
447
- const DATA_DIR$48 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
448
- async function handleLogInteraction(input, dataDir = DATA_DIR$48) {
448
+ const DATA_DIR$49 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
449
+ async function handleLogInteraction(input, dataDir = DATA_DIR$49) {
449
450
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
450
451
  const interactionDate = input.date ?? today;
451
452
  const sourceRef = input.source ?? `agent://log/${Date.now()}`;
@@ -550,12 +551,12 @@ Returns: { success: boolean, path: string, entry: string }`,
550
551
  }
551
552
  //#endregion
552
553
  //#region src/mcp/tools/export-customer.ts
553
- const DATA_DIR$47 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
554
+ const DATA_DIR$48 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
554
555
  function countInteractions(content) {
555
556
  const matches = content.match(/^## \d{4}-\d{2}-\d{2}/gm);
556
557
  return matches ? matches.length : 0;
557
558
  }
558
- async function handleExportCustomer(input, dataDir = DATA_DIR$47) {
559
+ async function handleExportCustomer(input, dataDir = DATA_DIR$48) {
559
560
  enforceRbac(dataDir, "export_customer");
560
561
  const customerDir = path.join(dataDir, "customers", input.slug);
561
562
  if (!fs.existsSync(customerDir)) return {
@@ -668,8 +669,8 @@ Returns:
668
669
  }
669
670
  //#endregion
670
671
  //#region src/mcp/tools/update-customer-facts.ts
671
- const DATA_DIR$46 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
672
- async function handleUpdateCustomerFacts(input, dataDir = DATA_DIR$46) {
672
+ const DATA_DIR$47 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
673
+ async function handleUpdateCustomerFacts(input, dataDir = DATA_DIR$47) {
673
674
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
674
675
  try {
675
676
  enforceRbac(dataDir, "update_customer_facts");
@@ -847,8 +848,8 @@ function scoreDealForToday(deal, todayDate) {
847
848
  }
848
849
  //#endregion
849
850
  //#region src/mcp/tools/get-deal-health.ts
850
- const DATA_DIR$45 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
851
- async function handleGetDealHealth(input, dataDir = DATA_DIR$45) {
851
+ const DATA_DIR$46 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
852
+ async function handleGetDealHealth(input, dataDir = DATA_DIR$46) {
852
853
  try {
853
854
  const deals = await readPipeline(dataDir, input.slug);
854
855
  const today = /* @__PURE__ */ new Date();
@@ -897,8 +898,8 @@ Returns: { slug, deals: [{ deal, stage, score, grade, signals, warnings }] }`,
897
898
  }
898
899
  //#endregion
899
900
  //#region src/mcp/tools/get-pipeline-forecast.ts
900
- const DATA_DIR$44 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
901
- async function handleGetPipelineForecast(input, dataDir = DATA_DIR$44) {
901
+ const DATA_DIR$45 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
902
+ async function handleGetPipelineForecast(input, dataDir = DATA_DIR$45) {
902
903
  try {
903
904
  const slugs = listCustomerSlugs(dataDir).filter((d) => !input.filter || d.includes(input.filter));
904
905
  const allDeals = [];
@@ -959,8 +960,8 @@ Returns: { deals: [...], totalWeightedValue: number, byStage: { stage: { count,
959
960
  }
960
961
  //#endregion
961
962
  //#region src/mcp/tools/summarize-meeting.ts
962
- const DATA_DIR$43 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
963
- async function handleSummarizeMeeting(input, dataDir = DATA_DIR$43) {
963
+ const DATA_DIR$44 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
964
+ async function handleSummarizeMeeting(input, dataDir = DATA_DIR$44) {
964
965
  try {
965
966
  let summary = input.transcript.slice(0, 400);
966
967
  let nextSteps = [];
@@ -1035,8 +1036,8 @@ Returns: { success, summary, nextSteps, sourceRef }`,
1035
1036
  }
1036
1037
  //#endregion
1037
1038
  //#region src/mcp/tools/get-pipeline-stages.ts
1038
- const DATA_DIR$42 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1039
- async function handleGetPipelineStages(_input, dataDir = DATA_DIR$42) {
1039
+ const DATA_DIR$43 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1040
+ async function handleGetPipelineStages(_input, dataDir = DATA_DIR$43) {
1040
1041
  const stages = getPipelineStages(dataDir);
1041
1042
  return { content: [{
1042
1043
  type: "text",
@@ -1064,8 +1065,8 @@ async function searchAcrossCustomers(dataDir, query, limit = 5, excludeSlug) {
1064
1065
  }
1065
1066
  //#endregion
1066
1067
  //#region src/mcp/tools/get-market-intelligence.ts
1067
- const DATA_DIR$41 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1068
- async function handleGetMarketIntelligence(input, dataDir = DATA_DIR$41) {
1068
+ const DATA_DIR$42 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1069
+ async function handleGetMarketIntelligence(input, dataDir = DATA_DIR$42) {
1069
1070
  const excludeSlug = input.excludeCurrentCustomer ? input.slug : void 0;
1070
1071
  const all = listCustomerSlugs(dataDir);
1071
1072
  const totalCustomersSearched = excludeSlug ? all.filter((s) => s !== excludeSlug).length : all.length;
@@ -1096,7 +1097,7 @@ function registerGetMarketIntelligence(server) {
1096
1097
  }
1097
1098
  //#endregion
1098
1099
  //#region src/mcp/tools/get-relationship-graph.ts
1099
- const DATA_DIR$40 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1100
+ const DATA_DIR$41 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1100
1101
  function summarizeNode(n) {
1101
1102
  return {
1102
1103
  id: n.id,
@@ -1104,7 +1105,7 @@ function summarizeNode(n) {
1104
1105
  email: n.properties["email"]
1105
1106
  };
1106
1107
  }
1107
- async function handleGetRelationshipGraph(input, dataDir = DATA_DIR$40) {
1108
+ async function handleGetRelationshipGraph(input, dataDir = DATA_DIR$41) {
1108
1109
  try {
1109
1110
  const graph = readGraph(dataDir, input.slug);
1110
1111
  const stakeholders = getStakeholders(graph);
@@ -1172,9 +1173,9 @@ Returns: {
1172
1173
  }
1173
1174
  //#endregion
1174
1175
  //#region src/mcp/tools/get-relationship-health.ts
1175
- const DATA_DIR$39 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1176
+ const DATA_DIR$40 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1176
1177
  const MAX_HEALTH_AGE_MS = 3600 * 1e3;
1177
- async function handleGetRelationshipHealth(input, dataDir = DATA_DIR$39) {
1178
+ async function handleGetRelationshipHealth(input, dataDir = DATA_DIR$40) {
1178
1179
  try {
1179
1180
  let health = readHealth(dataDir, input.slug);
1180
1181
  if (health === null || Date.now() - new Date(health.updatedAt).getTime() > MAX_HEALTH_AGE_MS) {
@@ -1843,8 +1844,8 @@ async function runDealAgent(config, dataDir, llmFn = callLlm) {
1843
1844
  }
1844
1845
  //#endregion
1845
1846
  //#region src/mcp/tools/run-deal-agent.ts
1846
- const DATA_DIR$38 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1847
- async function handleRunDealAgent(input, dataDir = DATA_DIR$38) {
1847
+ const DATA_DIR$39 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1848
+ async function handleRunDealAgent(input, dataDir = DATA_DIR$39) {
1848
1849
  try {
1849
1850
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
1850
1851
  const result = await runDealAgent({
@@ -1911,8 +1912,8 @@ Returns: { assessment, riskLevel, plan[], actionsQueued[], actionsExecuted[], tr
1911
1912
  }
1912
1913
  //#endregion
1913
1914
  //#region src/mcp/tools/approve-agent-action.ts
1914
- const DATA_DIR$37 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1915
- async function handleApproveAgentAction(input, dataDir = DATA_DIR$37) {
1915
+ const DATA_DIR$38 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1916
+ async function handleApproveAgentAction(input, dataDir = DATA_DIR$38) {
1916
1917
  try {
1917
1918
  const queue = readAgentQueue(dataDir, input.slug);
1918
1919
  const idx = queue.pendingActions.findIndex((a) => a.actionId === input.actionId);
@@ -1989,8 +1990,8 @@ Returns: { success, actionId, status }`,
1989
1990
  }
1990
1991
  //#endregion
1991
1992
  //#region src/mcp/tools/simulate-revenue.ts
1992
- const DATA_DIR$36 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1993
- async function handleSimulateRevenue(input, dataDir = DATA_DIR$36) {
1993
+ const DATA_DIR$37 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
1994
+ async function handleSimulateRevenue(input, dataDir = DATA_DIR$37) {
1994
1995
  try {
1995
1996
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
1996
1997
  const horizon = input.horizon ?? "quarter";
@@ -2048,8 +2049,8 @@ Returns: { forecast: { p10, p50, p90, expected, stdDev, atRiskRevenue, byCloseMo
2048
2049
  }
2049
2050
  //#endregion
2050
2051
  //#region src/mcp/tools/get-playbook.ts
2051
- const DATA_DIR$35 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2052
- async function handleGetPlaybook(input, dataDir = DATA_DIR$35) {
2052
+ const DATA_DIR$36 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2053
+ async function handleGetPlaybook(input, dataDir = DATA_DIR$36) {
2053
2054
  try {
2054
2055
  const playbooks = listPlaybooks(dataDir, input.slug);
2055
2056
  if (!(input.stage !== void 0 || input.value !== void 0 || input.healthScore !== void 0)) return { content: [{
@@ -2134,12 +2135,12 @@ Returns: { matches: [{ name, score, trigger, successRate, usedCount, content }],
2134
2135
  ...healthScore !== void 0 ? { healthScore } : {},
2135
2136
  ...daysSinceContact !== void 0 ? { daysSinceContact } : {},
2136
2137
  ...championPresent !== void 0 ? { championPresent } : {}
2137
- }, DATA_DIR$35));
2138
+ }, DATA_DIR$36));
2138
2139
  }
2139
2140
  //#endregion
2140
2141
  //#region src/mcp/tools/create-playbook.ts
2141
- const DATA_DIR$34 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2142
- async function handleCreatePlaybook(input, dataDir = DATA_DIR$34) {
2142
+ const DATA_DIR$35 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2143
+ async function handleCreatePlaybook(input, dataDir = DATA_DIR$35) {
2143
2144
  try {
2144
2145
  const name = toKebabCase(input.name);
2145
2146
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -2212,12 +2213,12 @@ Returns: { success: true, playbook: { name, trigger, successRate, path } }`,
2212
2213
  trigger,
2213
2214
  content,
2214
2215
  ...successRate !== void 0 ? { successRate } : {}
2215
- }, DATA_DIR$34));
2216
+ }, DATA_DIR$35));
2216
2217
  }
2217
2218
  //#endregion
2218
2219
  //#region src/mcp/tools/list-playbooks.ts
2219
- const DATA_DIR$33 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2220
- async function handleListPlaybooks(input, dataDir = DATA_DIR$33) {
2220
+ const DATA_DIR$34 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2221
+ async function handleListPlaybooks(input, dataDir = DATA_DIR$34) {
2221
2222
  try {
2222
2223
  const playbooks = listPlaybooks(dataDir, input.slug);
2223
2224
  return { content: [{
@@ -2256,12 +2257,12 @@ Args:
2256
2257
 
2257
2258
  Returns: { playbooks: [{ name, trigger, successRate, usedCount, lastUpdated }], count, slug }`,
2258
2259
  inputSchema: z.object({ slug: z.string().describe("Customer ID") })
2259
- }, async ({ slug }) => handleListPlaybooks({ slug }, DATA_DIR$33));
2260
+ }, async ({ slug }) => handleListPlaybooks({ slug }, DATA_DIR$34));
2260
2261
  }
2261
2262
  //#endregion
2262
2263
  //#region src/mcp/tools/distill-playbook.ts
2263
- const DATA_DIR$32 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2264
- async function handleDistillPlaybook(input, dataDir = DATA_DIR$32, llmFn = callLlm) {
2264
+ const DATA_DIR$33 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2265
+ async function handleDistillPlaybook(input, dataDir = DATA_DIR$33, llmFn = callLlm) {
2265
2266
  try {
2266
2267
  const result = await distillPlaybook(dataDir, input.slug, input.dealName, input.outcome, llmFn);
2267
2268
  if (!result.ok) {
@@ -2320,12 +2321,12 @@ Returns: { success: true, playbook: { name, trigger, successRate, path }, reason
2320
2321
  slug,
2321
2322
  dealName,
2322
2323
  outcome
2323
- }, DATA_DIR$32));
2324
+ }, DATA_DIR$33));
2324
2325
  }
2325
2326
  //#endregion
2326
2327
  //#region src/mcp/tools/pursue-goal.ts
2327
- const DATA_DIR$31 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2328
- async function handlePursueGoal(input, dataDir = DATA_DIR$31, options = {}) {
2328
+ const DATA_DIR$32 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2329
+ async function handlePursueGoal(input, dataDir = DATA_DIR$32, options = {}) {
2329
2330
  try {
2330
2331
  enforceRbac(dataDir, "pursue_goal");
2331
2332
  const goal = await pursueGoal(dataDir, {
@@ -2388,12 +2389,12 @@ Returns: { goalId, description, target, deadline, decomposition: { analysis, cur
2388
2389
  goal,
2389
2390
  deadline,
2390
2391
  ...context !== void 0 ? { context } : {}
2391
- }, DATA_DIR$31));
2392
+ }, DATA_DIR$32));
2392
2393
  }
2393
2394
  //#endregion
2394
2395
  //#region src/mcp/tools/get-goal-status.ts
2395
- const DATA_DIR$30 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2396
- async function handleGetGoalStatus(input, dataDir = DATA_DIR$30) {
2396
+ const DATA_DIR$31 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2397
+ async function handleGetGoalStatus(input, dataDir = DATA_DIR$31) {
2397
2398
  try {
2398
2399
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
2399
2400
  const allGoals = input.goalId ? readGoals(dataDir).filter((g) => g.id === input.goalId) : getActiveGoals(dataDir);
@@ -2452,17 +2453,17 @@ Args:
2452
2453
 
2453
2454
  Returns: { goals: [{ id, description, target, progress, status, deadline, daysRemaining, subGoals }], activeCount, completedCount }`,
2454
2455
  inputSchema: z.object({ goalId: z.string().optional().describe("Specific goal ID (omit for all active goals)") })
2455
- }, async ({ goalId }) => handleGetGoalStatus({ ...goalId !== void 0 ? { goalId } : {} }, DATA_DIR$30));
2456
+ }, async ({ goalId }) => handleGetGoalStatus({ ...goalId !== void 0 ? { goalId } : {} }, DATA_DIR$31));
2456
2457
  }
2457
2458
  //#endregion
2458
2459
  //#region src/mcp/tools/register-push-subscription.ts
2459
- const DATA_DIR$29 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2460
+ const DATA_DIR$30 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2460
2461
  const VALID_PROVIDERS = [
2461
2462
  "gmail",
2462
2463
  "microsoft-graph",
2463
2464
  "slack"
2464
2465
  ];
2465
- async function handleRegisterPushSubscription(input, dataDir = DATA_DIR$29) {
2466
+ async function handleRegisterPushSubscription(input, dataDir = DATA_DIR$30) {
2466
2467
  try {
2467
2468
  if (!VALID_PROVIDERS.includes(input.provider)) return { content: [{
2468
2469
  type: "text",
@@ -2548,12 +2549,12 @@ Returns: { subscriptionId, provider, slug, status, expiresAt, createdAt, warning
2548
2549
  ...microsoftResource !== void 0 ? { microsoftResource } : {},
2549
2550
  ...slackTeamId !== void 0 ? { slackTeamId } : {},
2550
2551
  ...slackChannelId !== void 0 ? { slackChannelId } : {}
2551
- }, DATA_DIR$29));
2552
+ }, DATA_DIR$30));
2552
2553
  }
2553
2554
  //#endregion
2554
2555
  //#region src/mcp/tools/get-push-status.ts
2555
- const DATA_DIR$28 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2556
- async function handleGetPushStatus(input, dataDir = DATA_DIR$28) {
2556
+ const DATA_DIR$29 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2557
+ async function handleGetPushStatus(input, dataDir = DATA_DIR$29) {
2557
2558
  try {
2558
2559
  let subs = await readSubscriptions(dataDir);
2559
2560
  if (input.slug) subs = subs.filter((s) => s.slug === input.slug);
@@ -2625,7 +2626,7 @@ Returns: { subscriptions: [{ id, provider, slug, status, expiresAt, expiresInHou
2625
2626
  }, async ({ slug, provider }) => handleGetPushStatus({
2626
2627
  ...slug !== void 0 ? { slug } : {},
2627
2628
  ...provider !== void 0 ? { provider } : {}
2628
- }, DATA_DIR$28));
2629
+ }, DATA_DIR$29));
2629
2630
  }
2630
2631
  //#endregion
2631
2632
  //#region src/core/org-intelligence.ts
@@ -2691,8 +2692,8 @@ function deriveRecommendation(people, missingRoles) {
2691
2692
  }
2692
2693
  //#endregion
2693
2694
  //#region src/mcp/tools/get-org-intelligence.ts
2694
- const DATA_DIR$27 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2695
- async function handleGetOrgIntelligence(input, dataDir = DATA_DIR$27) {
2695
+ const DATA_DIR$28 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2696
+ async function handleGetOrgIntelligence(input, dataDir = DATA_DIR$28) {
2696
2697
  try {
2697
2698
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
2698
2699
  const map = buildStakeholderMap(dataDir, input.slug, today, input.dealName);
@@ -2825,8 +2826,8 @@ function buildExecutiveSummary(slug, dealName, stakeholders, overallHealth, sim,
2825
2826
  }
2826
2827
  //#endregion
2827
2828
  //#region src/mcp/tools/open-deal-room.ts
2828
- const DATA_DIR$26 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2829
- async function handleOpenDealRoom(input, dataDir = DATA_DIR$26) {
2829
+ const DATA_DIR$27 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2830
+ async function handleOpenDealRoom(input, dataDir = DATA_DIR$27) {
2830
2831
  try {
2831
2832
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
2832
2833
  const brief = await buildDealRoom(dataDir, input.slug, input.dealName, today);
@@ -2861,8 +2862,8 @@ Returns: { slug, dealName, generatedAt, stakeholders, relationshipHealth, dealHe
2861
2862
  }
2862
2863
  //#endregion
2863
2864
  //#region src/mcp/tools/get-proactive-briefing.ts
2864
- const DATA_DIR$25 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2865
- async function handleGetProactiveBriefing(input, dataDir = DATA_DIR$25) {
2865
+ const DATA_DIR$26 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2866
+ async function handleGetProactiveBriefing(input, dataDir = DATA_DIR$26) {
2866
2867
  try {
2867
2868
  const briefing = await buildDailyBriefing(dataDir, input.date ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10));
2868
2869
  return { content: [{
@@ -2890,15 +2891,15 @@ Returns: { date, generatedAt, urgent: string[], opportunities: string[], forecas
2890
2891
  }
2891
2892
  //#endregion
2892
2893
  //#region src/mcp/tools/list-email-templates.ts
2893
- const DATA_DIR$24 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2894
- async function handleListEmailTemplates(input, dataDir = DATA_DIR$24) {
2894
+ const DATA_DIR$25 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2895
+ async function handleListEmailTemplates(input, dataDir = DATA_DIR$25) {
2895
2896
  const summary = listTemplates(dataDir, input.category ? { category: input.category } : {}).map(({ body: _body, ...meta }) => meta);
2896
2897
  return { content: [{
2897
2898
  type: "text",
2898
2899
  text: JSON.stringify(summary, null, 2)
2899
2900
  }] };
2900
2901
  }
2901
- function registerListEmailTemplates(server, dataDir = DATA_DIR$24) {
2902
+ function registerListEmailTemplates(server, dataDir = DATA_DIR$25) {
2902
2903
  server.registerTool("list_email_templates", {
2903
2904
  description: "List available email templates. Optionally filter by category (e.g. 'outreach', 'followup', 'support').",
2904
2905
  inputSchema: z.object({ category: z.string().optional().describe("Filter by category") })
@@ -2906,8 +2907,8 @@ function registerListEmailTemplates(server, dataDir = DATA_DIR$24) {
2906
2907
  }
2907
2908
  //#endregion
2908
2909
  //#region src/mcp/tools/get-email-template.ts
2909
- const DATA_DIR$23 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2910
- async function handleGetEmailTemplate(input, dataDir = DATA_DIR$23) {
2910
+ const DATA_DIR$24 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2911
+ async function handleGetEmailTemplate(input, dataDir = DATA_DIR$24) {
2911
2912
  const tmpl = getTemplate(dataDir, input.id);
2912
2913
  if (!tmpl) return { content: [{
2913
2914
  type: "text",
@@ -2923,7 +2924,7 @@ async function handleGetEmailTemplate(input, dataDir = DATA_DIR$23) {
2923
2924
  }, null, 2)
2924
2925
  }] };
2925
2926
  }
2926
- function registerGetEmailTemplate(server, dataDir = DATA_DIR$23) {
2927
+ function registerGetEmailTemplate(server, dataDir = DATA_DIR$24) {
2927
2928
  server.registerTool("get_email_template", {
2928
2929
  description: "Get a specific email template by ID, including its body and detected variables.",
2929
2930
  inputSchema: z.object({ id: z.string().describe("Template ID (e.g. 'enterprise-intro')") })
@@ -2931,8 +2932,8 @@ function registerGetEmailTemplate(server, dataDir = DATA_DIR$23) {
2931
2932
  }
2932
2933
  //#endregion
2933
2934
  //#region src/mcp/tools/draft-email.ts
2934
- const DATA_DIR$22 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2935
- async function handleDraftEmail(input, dataDir = DATA_DIR$22) {
2935
+ const DATA_DIR$23 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
2936
+ async function handleDraftEmail(input, dataDir = DATA_DIR$23) {
2936
2937
  const tmpl = getTemplate(dataDir, input.templateId);
2937
2938
  if (!tmpl) return { content: [{
2938
2939
  type: "text",
@@ -2976,7 +2977,7 @@ async function handleDraftEmail(input, dataDir = DATA_DIR$22) {
2976
2977
  }, null, 2)
2977
2978
  }] };
2978
2979
  }
2979
- function registerDraftEmail(server, dataDir = DATA_DIR$22) {
2980
+ function registerDraftEmail(server, dataDir = DATA_DIR$23) {
2980
2981
  server.registerTool("draft_email", {
2981
2982
  description: `Draft a personalized email for a customer using a stored template.
2982
2983
  Variables are auto-filled from the customer's main_facts.md. Override any variable manually.
@@ -2998,8 +2999,8 @@ Returns: { subject, body, to, tone, polished, resolvedVariables } — does NOT s
2998
2999
  }
2999
3000
  //#endregion
3000
3001
  //#region src/mcp/tools/enroll-in-sequence.ts
3001
- const DATA_DIR$21 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3002
- async function handleEnrollInSequence(input, dataDir = DATA_DIR$21) {
3002
+ const DATA_DIR$22 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3003
+ async function handleEnrollInSequence(input, dataDir = DATA_DIR$22) {
3003
3004
  const sequence = getSequence(dataDir, input.sequenceId);
3004
3005
  if (!sequence) return { content: [{
3005
3006
  type: "text",
@@ -3031,7 +3032,7 @@ async function handleEnrollInSequence(input, dataDir = DATA_DIR$21) {
3031
3032
  })
3032
3033
  }] };
3033
3034
  }
3034
- function registerEnrollInSequence(server, dataDir = DATA_DIR$21) {
3035
+ function registerEnrollInSequence(server, dataDir = DATA_DIR$22) {
3035
3036
  server.registerTool("enroll_in_sequence", {
3036
3037
  description: `Enroll a contact in an email sequence. Validates that the sequence and its first template exist.
3037
3038
  Returns: { enrollmentId, sequenceName, totalSteps }`,
@@ -3048,8 +3049,8 @@ Returns: { enrollmentId, sequenceName, totalSteps }`,
3048
3049
  }
3049
3050
  //#endregion
3050
3051
  //#region src/mcp/tools/list-sequence-enrollments.ts
3051
- const DATA_DIR$20 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3052
- async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$20) {
3052
+ const DATA_DIR$21 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3053
+ async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$21) {
3053
3054
  let enrollments = readEnrollments(dataDir);
3054
3055
  if (input.slug !== void 0) enrollments = enrollments.filter((e) => e.slug === input.slug);
3055
3056
  if (input.status !== void 0) enrollments = enrollments.filter((e) => e.status === input.status);
@@ -3058,7 +3059,7 @@ async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$20) {
3058
3059
  text: JSON.stringify({ enrollments }, null, 2)
3059
3060
  }] };
3060
3061
  }
3061
- function registerListSequenceEnrollments(server, dataDir = DATA_DIR$20) {
3062
+ function registerListSequenceEnrollments(server, dataDir = DATA_DIR$21) {
3062
3063
  server.registerTool("list_sequence_enrollments", {
3063
3064
  description: `List email sequence enrollments. Filter by customer slug or status.
3064
3065
  Returns: { enrollments: SequenceEnrollment[] }`,
@@ -3077,8 +3078,8 @@ Returns: { enrollments: SequenceEnrollment[] }`,
3077
3078
  }
3078
3079
  //#endregion
3079
3080
  //#region src/mcp/tools/unenroll-from-sequence.ts
3080
- const DATA_DIR$19 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3081
- async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$19) {
3081
+ const DATA_DIR$20 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3082
+ async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$20) {
3082
3083
  if (!await updateEnrollment(dataDir, input.enrollmentId, { status: "paused" })) return { content: [{
3083
3084
  type: "text",
3084
3085
  text: JSON.stringify({
@@ -3091,7 +3092,7 @@ async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$19) {
3091
3092
  text: JSON.stringify({ success: true })
3092
3093
  }] };
3093
3094
  }
3094
- function registerUnenrollFromSequence(server, dataDir = DATA_DIR$19) {
3095
+ function registerUnenrollFromSequence(server, dataDir = DATA_DIR$20) {
3095
3096
  server.registerTool("unenroll_from_sequence", {
3096
3097
  description: `Unenroll (pause) a contact from an email sequence. Sets status to "paused" (soft delete).
3097
3098
  Returns: { success: boolean }`,
@@ -3100,8 +3101,8 @@ Returns: { success: boolean }`,
3100
3101
  }
3101
3102
  //#endregion
3102
3103
  //#region src/mcp/tools/list-sequences.ts
3103
- const DATA_DIR$18 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3104
- async function handleListSequences(_input, dataDir = DATA_DIR$18) {
3104
+ const DATA_DIR$19 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3105
+ async function handleListSequences(_input, dataDir = DATA_DIR$19) {
3105
3106
  const sequences = listSequences(dataDir);
3106
3107
  const enrollments = readEnrollments(dataDir);
3107
3108
  const result = sequences.map((seq) => ({
@@ -3115,7 +3116,7 @@ async function handleListSequences(_input, dataDir = DATA_DIR$18) {
3115
3116
  text: JSON.stringify({ sequences: result }, null, 2)
3116
3117
  }] };
3117
3118
  }
3118
- function registerListSequences(server, dataDir = DATA_DIR$18) {
3119
+ function registerListSequences(server, dataDir = DATA_DIR$19) {
3119
3120
  server.registerTool("list_sequences", {
3120
3121
  description: `List all email sequences with step count and enrollment count.
3121
3122
  Returns: { sequences: Array<{ id, name, stepCount, enrollmentCount }> }`,
@@ -3124,8 +3125,8 @@ Returns: { sequences: Array<{ id, name, stepCount, enrollmentCount }> }`,
3124
3125
  }
3125
3126
  //#endregion
3126
3127
  //#region src/mcp/tools/generate-quote.ts
3127
- const DATA_DIR$17 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3128
- async function handleGenerateQuote(input, dataDir = DATA_DIR$17) {
3128
+ const DATA_DIR$18 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3129
+ async function handleGenerateQuote(input, dataDir = DATA_DIR$18) {
3129
3130
  try {
3130
3131
  const quote = await generateQuote(dataDir, input);
3131
3132
  return { content: [{
@@ -3149,7 +3150,7 @@ async function handleGenerateQuote(input, dataDir = DATA_DIR$17) {
3149
3150
  }] };
3150
3151
  }
3151
3152
  }
3152
- function registerGenerateQuote(server, dataDir = DATA_DIR$17) {
3153
+ function registerGenerateQuote(server, dataDir = DATA_DIR$18) {
3153
3154
  server.registerTool("generate_quote", {
3154
3155
  description: `Generate a professional HTML quote/offer for a customer deal.
3155
3156
  Calculates subtotal, VAT, and total. Saves JSON + HTML to .agentic/quotes/.
@@ -3177,8 +3178,8 @@ Returns: { quoteNumber, htmlPath, total, currency, validUntil }`,
3177
3178
  }
3178
3179
  //#endregion
3179
3180
  //#region src/mcp/tools/get-quote-status.ts
3180
- const DATA_DIR$16 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3181
- async function handleGetQuoteStatus(input, dataDir = DATA_DIR$16) {
3181
+ const DATA_DIR$17 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3182
+ async function handleGetQuoteStatus(input, dataDir = DATA_DIR$17) {
3182
3183
  if (input.quoteNumber) {
3183
3184
  const quote = readQuote(dataDir, input.quoteNumber);
3184
3185
  if (!quote) return { content: [{
@@ -3196,7 +3197,7 @@ async function handleGetQuoteStatus(input, dataDir = DATA_DIR$16) {
3196
3197
  text: JSON.stringify({ quotes }, null, 2)
3197
3198
  }] };
3198
3199
  }
3199
- function registerGetQuoteStatus(server, dataDir = DATA_DIR$16) {
3200
+ function registerGetQuoteStatus(server, dataDir = DATA_DIR$17) {
3200
3201
  server.registerTool("get_quote_status", {
3201
3202
  description: `Get quote status and details. Filter by quoteNumber (single quote) or slug (all quotes for a customer).
3202
3203
  Returns quote with status: draft | sent | viewed | accepted | declined`,
@@ -3211,7 +3212,7 @@ Returns quote with status: draft | sent | viewed | accepted | declined`,
3211
3212
  }
3212
3213
  //#endregion
3213
3214
  //#region src/mcp/tools/get-booking-link.ts
3214
- const DATA_DIR$15 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3215
+ const DATA_DIR$16 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3215
3216
  function loadCalendlyConfig(dataDir) {
3216
3217
  const p = path.join(dataDir, ".agentic", "integrations", "calendly.yaml");
3217
3218
  if (!fs.existsSync(p)) return {};
@@ -3234,7 +3235,7 @@ function readCustomerFacts(dataDir, slug) {
3234
3235
  ...email ? { email } : {}
3235
3236
  };
3236
3237
  }
3237
- async function handleGetBookingLink(input, dataDir = DATA_DIR$15) {
3238
+ async function handleGetBookingLink(input, dataDir = DATA_DIR$16) {
3238
3239
  const config = loadCalendlyConfig(dataDir);
3239
3240
  const apiKey = config.apiKey ?? process.env["CALENDLY_API_KEY"] ?? "";
3240
3241
  if (!apiKey) return { content: [{
@@ -3262,7 +3263,7 @@ async function handleGetBookingLink(input, dataDir = DATA_DIR$15) {
3262
3263
  }] };
3263
3264
  }
3264
3265
  }
3265
- function registerGetBookingLink(server, dataDir = DATA_DIR$15) {
3266
+ function registerGetBookingLink(server, dataDir = DATA_DIR$16) {
3266
3267
  server.registerTool("get_booking_link", {
3267
3268
  description: `Get a Calendly booking link for a customer. Optionally pre-fills the customer's name/email.
3268
3269
  Requires CALENDLY_API_KEY env var or .agentic/integrations/calendly.yaml config.
@@ -3280,8 +3281,8 @@ Returns: { bookingUrl, eventType, duration }`,
3280
3281
  }
3281
3282
  //#endregion
3282
3283
  //#region src/mcp/tools/create-ticket.ts
3283
- const DATA_DIR$14 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3284
- async function handleCreateTicket(input, dataDir = DATA_DIR$14) {
3284
+ const DATA_DIR$15 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3285
+ async function handleCreateTicket(input, dataDir = DATA_DIR$15) {
3285
3286
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
3286
3287
  const rules = loadSlaRules(dataDir);
3287
3288
  const priority = input.priority ?? "normal";
@@ -3303,7 +3304,7 @@ async function handleCreateTicket(input, dataDir = DATA_DIR$14) {
3303
3304
  text: JSON.stringify({ ticket }, null, 2)
3304
3305
  }] };
3305
3306
  }
3306
- function registerCreateTicket(server, dataDir = DATA_DIR$14) {
3307
+ function registerCreateTicket(server, dataDir = DATA_DIR$15) {
3307
3308
  server.registerTool("create_ticket", {
3308
3309
  description: `Create a support ticket for a customer. Auto-calculates SLA due date based on priority.
3309
3310
  Returns: { ticket } with id T-NNN, status=open, slaDue`,
@@ -3329,8 +3330,8 @@ Returns: { ticket } with id T-NNN, status=open, slaDue`,
3329
3330
  }
3330
3331
  //#endregion
3331
3332
  //#region src/mcp/tools/update-ticket.ts
3332
- const DATA_DIR$13 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3333
- async function handleUpdateTicket(input, dataDir = DATA_DIR$13) {
3333
+ const DATA_DIR$14 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3334
+ async function handleUpdateTicket(input, dataDir = DATA_DIR$14) {
3334
3335
  const ticket = (await readTickets(dataDir, input.slug)).find((t) => t.id === input.ticketId);
3335
3336
  if (!ticket) return { content: [{
3336
3337
  type: "text",
@@ -3349,7 +3350,7 @@ async function handleUpdateTicket(input, dataDir = DATA_DIR$13) {
3349
3350
  text: JSON.stringify({ ticket: updated }, null, 2)
3350
3351
  }] };
3351
3352
  }
3352
- function registerUpdateTicket(server, dataDir = DATA_DIR$13) {
3353
+ function registerUpdateTicket(server, dataDir = DATA_DIR$14) {
3353
3354
  server.registerTool("update_ticket", {
3354
3355
  description: `Update a ticket's status or assignee. Setting status=resolved auto-sets resolved date.
3355
3356
  Returns: { ticket }`,
@@ -3374,8 +3375,8 @@ Returns: { ticket }`,
3374
3375
  }
3375
3376
  //#endregion
3376
3377
  //#region src/mcp/tools/list-tickets.ts
3377
- const DATA_DIR$12 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3378
- async function handleListTickets(input, dataDir = DATA_DIR$12) {
3378
+ const DATA_DIR$13 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3379
+ async function handleListTickets(input, dataDir = DATA_DIR$13) {
3379
3380
  const results = await listAllTickets(dataDir, {
3380
3381
  ...input.slug !== void 0 ? { slug: input.slug } : {},
3381
3382
  ...input.status !== void 0 ? { status: input.status } : {},
@@ -3387,7 +3388,7 @@ async function handleListTickets(input, dataDir = DATA_DIR$12) {
3387
3388
  text: JSON.stringify({ tickets: results }, null, 2)
3388
3389
  }] };
3389
3390
  }
3390
- function registerListTickets(server, dataDir = DATA_DIR$12) {
3391
+ function registerListTickets(server, dataDir = DATA_DIR$13) {
3391
3392
  server.registerTool("list_tickets", {
3392
3393
  description: `List support tickets. Filter by customer, status, priority, or assignee. Sorted by priority then date.
3393
3394
  Returns: { tickets: Array<{ slug, ticket }> }`,
@@ -3417,8 +3418,8 @@ Returns: { tickets: Array<{ slug, ticket }> }`,
3417
3418
  }
3418
3419
  //#endregion
3419
3420
  //#region src/mcp/tools/close-ticket.ts
3420
- const DATA_DIR$11 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3421
- async function handleCloseTicket(input, dataDir = DATA_DIR$11) {
3421
+ const DATA_DIR$12 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3422
+ async function handleCloseTicket(input, dataDir = DATA_DIR$12) {
3422
3423
  const ticket = (await readTickets(dataDir, input.slug)).find((t) => t.id === input.ticketId);
3423
3424
  if (!ticket) return { content: [{
3424
3425
  type: "text",
@@ -3445,7 +3446,7 @@ async function handleCloseTicket(input, dataDir = DATA_DIR$11) {
3445
3446
  text: JSON.stringify({ ticket: updated }, null, 2)
3446
3447
  }] };
3447
3448
  }
3448
- function registerCloseTicket(server, dataDir = DATA_DIR$11) {
3449
+ function registerCloseTicket(server, dataDir = DATA_DIR$12) {
3449
3450
  server.registerTool("close_ticket", {
3450
3451
  description: `Close a support ticket. Optionally logs the resolution as an interaction.
3451
3452
  Returns: { ticket } with status=closed`,
@@ -3462,8 +3463,8 @@ Returns: { ticket } with status=closed`,
3462
3463
  }
3463
3464
  //#endregion
3464
3465
  //#region src/mcp/tools/send-nps-survey.ts
3465
- const DATA_DIR$10 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3466
- async function handleSendNpsSurvey(input, dataDir = DATA_DIR$10) {
3466
+ const DATA_DIR$11 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3467
+ async function handleSendNpsSurvey(input, dataDir = DATA_DIR$11) {
3467
3468
  const survey = getSurvey(dataDir, input.surveyId);
3468
3469
  if (!survey) return { content: [{
3469
3470
  type: "text",
@@ -3484,7 +3485,7 @@ async function handleSendNpsSurvey(input, dataDir = DATA_DIR$10) {
3484
3485
  }, null, 2)
3485
3486
  }] };
3486
3487
  }
3487
- function registerSendNpsSurvey(server, dataDir = DATA_DIR$10) {
3488
+ function registerSendNpsSurvey(server, dataDir = DATA_DIR$11) {
3488
3489
  server.registerTool("send_nps_survey", {
3489
3490
  description: `Generate an NPS/CSAT survey email for a customer contact. Returns subject, HTML body, and a token-based response URL.
3490
3491
  Does NOT send automatically — returns draft for review.
@@ -3504,8 +3505,8 @@ Returns: { token, subject, body, surveyUrl }`,
3504
3505
  }
3505
3506
  //#endregion
3506
3507
  //#region src/mcp/tools/get-survey-results.ts
3507
- const DATA_DIR$9 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3508
- async function handleGetSurveyResults(input, dataDir = DATA_DIR$9) {
3508
+ const DATA_DIR$10 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3509
+ async function handleGetSurveyResults(input, dataDir = DATA_DIR$10) {
3509
3510
  const responses = loadSurveyResponses(dataDir, input.surveyId, input.slug);
3510
3511
  const nps = calcNpsScore(responses);
3511
3512
  const promoters = responses.filter((r) => r.score >= 9).length;
@@ -3531,7 +3532,7 @@ async function handleGetSurveyResults(input, dataDir = DATA_DIR$9) {
3531
3532
  }, null, 2)
3532
3533
  }] };
3533
3534
  }
3534
- function registerGetSurveyResults(server, dataDir = DATA_DIR$9) {
3535
+ function registerGetSurveyResults(server, dataDir = DATA_DIR$10) {
3535
3536
  server.registerTool("get_survey_results", {
3536
3537
  description: `Get NPS/CSAT survey results with score breakdown. Calculates Net Promoter Score.
3537
3538
  Returns: { npsScore, totalResponses, promoters, passives, detractors, responses[] }`,
@@ -3546,8 +3547,8 @@ Returns: { npsScore, totalResponses, promoters, passives, detractors, responses[
3546
3547
  }
3547
3548
  //#endregion
3548
3549
  //#region src/mcp/tools/search-knowledge-base.ts
3549
- const DATA_DIR$8 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3550
- async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$8) {
3550
+ const DATA_DIR$9 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3551
+ async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$9) {
3551
3552
  const results = searchKbSimple(dataDir, input.query, { ...input.publicOnly ? { publicOnly: true } : {} });
3552
3553
  const limited = (input.category ? results.filter((a) => a.category === input.category) : results).slice(0, input.limit ?? 10);
3553
3554
  return { content: [{
@@ -3562,7 +3563,7 @@ async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$8) {
3562
3563
  }, null, 2)
3563
3564
  }] };
3564
3565
  }
3565
- function registerSearchKnowledgeBase(server, dataDir = DATA_DIR$8) {
3566
+ function registerSearchKnowledgeBase(server, dataDir = DATA_DIR$9) {
3566
3567
  server.registerTool("search_knowledge_base", {
3567
3568
  description: `Search the knowledge base for articles. Text search on title, body, and tags.
3568
3569
  Returns: { count, articles[] } with excerpts`,
@@ -3581,8 +3582,8 @@ Returns: { count, articles[] } with excerpts`,
3581
3582
  }
3582
3583
  //#endregion
3583
3584
  //#region src/mcp/tools/create-kb-article.ts
3584
- const DATA_DIR$7 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3585
- async function handleCreateKbArticle(input, dataDir = DATA_DIR$7) {
3585
+ const DATA_DIR$8 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3586
+ async function handleCreateKbArticle(input, dataDir = DATA_DIR$8) {
3586
3587
  if (getKbArticle(dataDir, input.id)) return { content: [{
3587
3588
  type: "text",
3588
3589
  text: JSON.stringify({ error: `Article '${input.id}' already exists` })
@@ -3610,7 +3611,7 @@ async function handleCreateKbArticle(input, dataDir = DATA_DIR$7) {
3610
3611
  }, null, 2)
3611
3612
  }] };
3612
3613
  }
3613
- function registerCreateKbArticle(server, dataDir = DATA_DIR$7) {
3614
+ function registerCreateKbArticle(server, dataDir = DATA_DIR$8) {
3614
3615
  server.registerTool("create_kb_article", {
3615
3616
  description: `Create a new knowledge base article. Articles are stored as Markdown files in .agentic/knowledge-base/.
3616
3617
  Returns: { id, title, category, path }`,
@@ -3635,8 +3636,8 @@ Returns: { id, title, category, path }`,
3635
3636
  }
3636
3637
  //#endregion
3637
3638
  //#region src/mcp/tools/backup-now.ts
3638
- const DATA_DIR$6 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3639
- async function handleBackupNow(input, dataDir = DATA_DIR$6) {
3639
+ const DATA_DIR$7 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3640
+ async function handleBackupNow(input, dataDir = DATA_DIR$7) {
3640
3641
  const zipPath = path.join(dataDir, `dxcrm-backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19)}.zip`);
3641
3642
  const manifest = await runBackup(zipPath, dataDir, { ...input.remote ? { remote: input.remote } : {} }).catch(() => null);
3642
3643
  if (!manifest) return { content: [{
@@ -3673,8 +3674,8 @@ function registerBackupNow(server) {
3673
3674
  }
3674
3675
  //#endregion
3675
3676
  //#region src/mcp/tools/list-backups.ts
3676
- const DATA_DIR$5 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3677
- async function handleListBackups(input, dataDir = DATA_DIR$5) {
3677
+ const DATA_DIR$6 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3678
+ async function handleListBackups(input, dataDir = DATA_DIR$6) {
3678
3679
  const logEntries = readBackupLog(dataDir);
3679
3680
  const fileEntries = listBackupsInDir(dataDir);
3680
3681
  const entries = logEntries.length > 0 ? logEntries : fileEntries;
@@ -3708,8 +3709,8 @@ function registerListBackups(server) {
3708
3709
  }
3709
3710
  //#endregion
3710
3711
  //#region src/mcp/tools/trigger-sync.ts
3711
- const DATA_DIR$4 = process.cwd();
3712
- async function handleTriggerSync(input, dataDir = DATA_DIR$4) {
3712
+ const DATA_DIR$5 = process.cwd();
3713
+ async function handleTriggerSync(input, dataDir = DATA_DIR$5) {
3713
3714
  const auth = getGmailAuth();
3714
3715
  if (!auth) return { content: [{
3715
3716
  type: "text",
@@ -3803,8 +3804,8 @@ Returns: { success: boolean, synced: number, skipped: number, customers: [...],
3803
3804
  }
3804
3805
  //#endregion
3805
3806
  //#region src/mcp/tools/get-audit-log.ts
3806
- const DATA_DIR$3 = process.cwd();
3807
- async function handleGetAuditLog(input, dataDir = DATA_DIR$3) {
3807
+ const DATA_DIR$4 = process.cwd();
3808
+ async function handleGetAuditLog(input, dataDir = DATA_DIR$4) {
3808
3809
  const entries = readAuditLog(dataDir);
3809
3810
  const filterOpts = { limit: input.limit ?? 50 };
3810
3811
  if (input.slug !== void 0) filterOpts.slug = input.slug;
@@ -3846,8 +3847,8 @@ Returns: { total: number, returned: number, entries: [{timestamp, actor, tool, s
3846
3847
  }
3847
3848
  //#endregion
3848
3849
  //#region src/mcp/tools/get-logs.ts
3849
- const DATA_DIR$2 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3850
- async function handleGetLogs(input, dataDir = DATA_DIR$2) {
3850
+ const DATA_DIR$3 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3851
+ async function handleGetLogs(input, dataDir = DATA_DIR$3) {
3851
3852
  const query = {
3852
3853
  ...input.level !== void 0 ? { level: input.level } : {},
3853
3854
  ...input.component !== void 0 ? { component: input.component } : {},
@@ -3908,6 +3909,40 @@ Returns (summary): { total, byLevel, byComponent, firstTs, lastTs, recentErrors
3908
3909
  });
3909
3910
  }
3910
3911
  //#endregion
3912
+ //#region src/mcp/tools/get-diagnostics.ts
3913
+ const DATA_DIR$2 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
3914
+ async function handleGetDiagnostics(input, dataDir = DATA_DIR$2) {
3915
+ let cleaned = 0;
3916
+ if (input.fix) {
3917
+ const { cleanupTempFiles } = await import("./doctor-CYDaNmFn.js");
3918
+ cleaned = cleanupTempFiles(dataDir).length;
3919
+ }
3920
+ const report = await runDiagnostics(dataDir);
3921
+ return { content: [{
3922
+ type: "text",
3923
+ text: JSON.stringify({
3924
+ ok: report.ok,
3925
+ ...input.fix ? { tempFilesRemoved: cleaned } : {},
3926
+ checks: report.checks
3927
+ }, null, 2)
3928
+ }] };
3929
+ }
3930
+ function registerGetDiagnostics(server) {
3931
+ server.registerTool("get_diagnostics", {
3932
+ title: "Get Diagnostics",
3933
+ description: `Run a self-diagnostic health check of the CRM workspace.
3934
+ Verifies the data directory, validates every customer's profile, detects orphaned
3935
+ atomic-write temp files (a crash signature), surfaces recent log errors, and checks
3936
+ backup freshness. Use to answer "is everything healthy?" before/after bulk operations.
3937
+
3938
+ Args:
3939
+ fix: When true, first remove orphaned temp files (the only safely auto-fixable issue)
3940
+
3941
+ Returns: { ok: boolean, tempFilesRemoved?: number, checks: [{ name, status: "ok"|"warn"|"fail", detail }] }`,
3942
+ inputSchema: z.object({ fix: z.boolean().optional().describe("Clean orphaned temp files before reporting") })
3943
+ }, async ({ fix }) => handleGetDiagnostics(fix !== void 0 ? { fix } : {}));
3944
+ }
3945
+ //#endregion
3911
3946
  //#region src/mcp/prompts.ts
3912
3947
  /**
3913
3948
  * CRM playbook prompts exposed via MCP `prompts/list` + `prompts/get`.
@@ -4164,6 +4199,7 @@ function createMcpServer() {
4164
4199
  registerTriggerSync(server);
4165
4200
  registerGetAuditLog(server);
4166
4201
  registerGetLogs(server);
4202
+ registerGetDiagnostics(server);
4167
4203
  registerCustomObjectTools(server);
4168
4204
  registerPrompts(server);
4169
4205
  registerResources(server);
@@ -4362,4 +4398,4 @@ else startStdio().catch((err) => {
4362
4398
  //#endregion
4363
4399
  export { startHttp, startStdio };
4364
4400
 
4365
- //# sourceMappingURL=server-DoRPPOeR.js.map
4401
+ //# sourceMappingURL=server-BhNLrnAD.js.map