@datasynx/agentic-crm 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -1
- package/dist/{ask-D8iYqDAr.js → ask-CDysGnRg.js} +2 -2
- package/dist/{ask-D8iYqDAr.js.map → ask-CDysGnRg.js.map} +1 -1
- package/dist/attachments-CX2GAtsw.cjs +517 -0
- package/dist/attachments-CX2GAtsw.cjs.map +1 -0
- package/dist/attachments-D207gXfN.js +514 -0
- package/dist/attachments-D207gXfN.js.map +1 -0
- package/dist/attachments-rLa96rOK.js +514 -0
- package/dist/attachments-rLa96rOK.js.map +1 -0
- package/dist/chunk-BfDYWZQ8.cjs +32 -0
- package/dist/chunk-BfDYWZQ8.cjs.map +1 -0
- package/dist/chunk-BhUZmQg5.js +32 -0
- package/dist/chunk-BhUZmQg5.js.map +1 -0
- package/dist/chunk-ChC83jai.js +2 -0
- package/dist/chunk-e_w8qqtP.js +32 -0
- package/dist/chunk-e_w8qqtP.js.map +1 -0
- package/dist/cli.js +20 -18
- package/dist/cli.js.map +1 -1
- package/dist/daemon/worker.js +3 -3
- package/dist/{doctor-C14-vnJ1.js → doctor-BFeelnq8.js} +2 -2
- package/dist/{doctor-C14-vnJ1.js.map → doctor-BFeelnq8.js.map} +1 -1
- package/dist/doctor-CYDaNmFn.js +2 -0
- package/dist/email-body-BFSRa0AW.cjs +42 -0
- package/dist/email-body-BFSRa0AW.cjs.map +1 -0
- package/dist/email-body-BOd7U-D2.js +42 -0
- package/dist/email-body-BOd7U-D2.js.map +1 -0
- package/dist/{gmail-sync-DueE6tl5.js → gmail-sync-B4Iu3AQb.js} +45 -15
- package/dist/gmail-sync-B4Iu3AQb.js.map +1 -0
- package/dist/{gmail-sync-GEy3oVvw.cjs → gmail-sync-BpSVESSe.cjs} +45 -15
- package/dist/gmail-sync-BpSVESSe.cjs.map +1 -0
- package/dist/{gmail-sync-C-NmibzS.js → gmail-sync-DIbrPnTK.js} +45 -15
- package/dist/gmail-sync-DIbrPnTK.js.map +1 -0
- package/dist/{gmail-webhook-handler-kGKpbY9h.js → gmail-webhook-handler-BzOFbvgh.js} +2 -2
- package/dist/{gmail-webhook-handler-kGKpbY9h.js.map → gmail-webhook-handler-BzOFbvgh.js.map} +1 -1
- package/dist/{gmail-webhook-handler-B26COilD.js → gmail-webhook-handler-CvSDW_Js.js} +1 -1
- package/dist/{google-drive-sync-D1n7WKZn.js → google-drive-sync-B_I1d54Y.js} +2 -2
- package/dist/{google-drive-sync-D1n7WKZn.js.map → google-drive-sync-B_I1d54Y.js.map} +1 -1
- package/dist/html-BaeOCZKE.js +36 -0
- package/dist/html-BaeOCZKE.js.map +1 -0
- package/dist/html-CmOku6jS.cjs +47 -0
- package/dist/html-CmOku6jS.cjs.map +1 -0
- package/dist/{import-hubspot-DB4n89jy.js → import-hubspot-CTId9IGV.js} +2 -2
- package/dist/{import-hubspot-DB4n89jy.js.map → import-hubspot-CTId9IGV.js.map} +1 -1
- package/dist/{index-pY7tYXwH.d.cts → index-CLUKKfGb.d.cts} +12 -8
- package/dist/index-CLUKKfGb.d.cts.map +1 -0
- package/dist/{index-B0IMMrp_.d.ts → index-D8jJ1VIt.d.ts} +14 -10
- package/dist/index-D8jJ1VIt.d.ts.map +1 -0
- package/dist/index.d.cts +12 -8
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +14 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/{interactions-writer-RJB8SWf2.js → interactions-writer-B2y-73lh.js} +1 -1
- package/dist/{interactions-writer-DbSyI2rt.js → interactions-writer-B8XAzdqR.js} +3 -2
- package/dist/interactions-writer-B8XAzdqR.js.map +1 -0
- package/dist/{interactions-writer-a2yzBd7T.cjs → interactions-writer-BRJNrefF.cjs} +3 -2
- package/dist/interactions-writer-BRJNrefF.cjs.map +1 -0
- package/dist/{interactions-writer-BZzUIgJd.js → interactions-writer-ZQcpFOh9.js} +3 -2
- package/dist/interactions-writer-ZQcpFOh9.js.map +1 -0
- package/dist/{knowledge-base-DHNc4hVj.js → knowledge-base-Bx2PKQR2.js} +10 -7
- package/dist/knowledge-base-Bx2PKQR2.js.map +1 -0
- package/dist/mcp-CdTJWTJf.d.cts.map +1 -1
- package/dist/mcp-CdTJWTJf.d.ts.map +1 -1
- package/dist/mcp.cjs +308 -150
- package/dist/mcp.cjs.map +1 -1
- package/dist/mcp.d.cts.map +1 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +308 -150
- package/dist/mcp.js.map +1 -1
- package/dist/{microsoft-calendar-jIu9K5zX.js → microsoft-calendar-BgVR8GDv.js} +3 -3
- package/dist/{microsoft-calendar-jIu9K5zX.js.map → microsoft-calendar-BgVR8GDv.js.map} +1 -1
- package/dist/{microsoft-sync-R_r8HL-B.js → microsoft-sync-D30_XksI.js} +3 -3
- package/dist/{microsoft-sync-R_r8HL-B.js.map → microsoft-sync-D30_XksI.js.map} +1 -1
- package/dist/{nba-mTJ4yEqD.js → nba-DwdfM93s.js} +2 -2
- package/dist/{nba-mTJ4yEqD.js.map → nba-DwdfM93s.js.map} +1 -1
- package/dist/{server-DqSMYhSA.js → server-BhNLrnAD.js} +201 -145
- package/dist/server-BhNLrnAD.js.map +1 -0
- package/dist/{transcript-watcher-0mh2ZhmH.js → transcript-watcher-BoClrJAz.js} +2 -2
- package/dist/{transcript-watcher-0mh2ZhmH.js.map → transcript-watcher-BoClrJAz.js.map} +1 -1
- package/package.json +13 -2
- package/dist/gmail-sync-C-NmibzS.js.map +0 -1
- package/dist/gmail-sync-DueE6tl5.js.map +0 -1
- package/dist/gmail-sync-GEy3oVvw.cjs.map +0 -1
- package/dist/index-B0IMMrp_.d.ts.map +0 -1
- package/dist/index-pY7tYXwH.d.cts.map +0 -1
- package/dist/interactions-writer-BZzUIgJd.js.map +0 -1
- package/dist/interactions-writer-DbSyI2rt.js.map +0 -1
- package/dist/interactions-writer-a2yzBd7T.cjs.map +0 -1
- package/dist/knowledge-base-DHNc4hVj.js.map +0 -1
- package/dist/server-DqSMYhSA.js.map +0 -1
|
@@ -2,11 +2,11 @@ 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-
|
|
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";
|
|
9
|
-
import { n as appendInteraction, r as formatInteractionEntry } from "./interactions-writer-
|
|
9
|
+
import { n as appendInteraction, r as formatInteractionEntry } from "./interactions-writer-B8XAzdqR.js";
|
|
10
10
|
import { i as writeAuditEntry, n as getActor, r as readAuditLog, t as filterAuditLog } from "./audit-log-DNMY9mUZ.js";
|
|
11
11
|
import { a as customerVisibility, n as canSeeCustomer, o as enforceRbac } from "./rbac-msmBc_tK.js";
|
|
12
12
|
import { f as getPipelineStages, i as buildSimulationInput, l as runSimulation, n as buildConfidenceMessage } from "./revenue-simulation-D8f_YkUY.js";
|
|
@@ -23,10 +23,11 @@ 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";
|
|
29
|
-
import { i as verifyGmailPubSubSignature, n as decodeGmailPubSubPayload, r as handleGmailPushEvent } from "./gmail-webhook-handler-
|
|
30
|
+
import { i as verifyGmailPubSubSignature, n as decodeGmailPubSubPayload, r as handleGmailPushEvent } from "./gmail-webhook-handler-BzOFbvgh.js";
|
|
30
31
|
import { n as registerUpdateDeal } from "./update-deal-DSzr_Aau.js";
|
|
31
32
|
import path from "path";
|
|
32
33
|
import fs from "fs";
|
|
@@ -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$
|
|
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;
|
|
@@ -267,7 +268,7 @@ function triggerOnQuerySync(dataDir, slug) {
|
|
|
267
268
|
const sources = JSON.parse(fs.readFileSync(sourcesPath, "utf-8"));
|
|
268
269
|
if (!sources.gmail?.enabled || !sources.gmail.query) return;
|
|
269
270
|
const query = sources.gmail.query;
|
|
270
|
-
import("./gmail-sync-
|
|
271
|
+
import("./gmail-sync-B4Iu3AQb.js").then(({ syncGmail }) => syncGmail({
|
|
271
272
|
slug,
|
|
272
273
|
dataDir,
|
|
273
274
|
auth,
|
|
@@ -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$
|
|
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$
|
|
331
|
-
async function handleSearchCustomerKnowledge(input, dataDir = DATA_DIR$
|
|
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$
|
|
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$
|
|
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$
|
|
448
|
-
async function handleLogInteraction(input, dataDir = DATA_DIR$
|
|
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$
|
|
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$
|
|
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 {
|
|
@@ -582,14 +583,27 @@ async function handleExportCustomer(input, dataDir = DATA_DIR$47) {
|
|
|
582
583
|
interactionsCount = countInteractions(interactionsContent);
|
|
583
584
|
}
|
|
584
585
|
const pipeline = await readPipeline(dataDir, input.slug);
|
|
586
|
+
const includeAttachmentContent = input.includeAttachmentContent ?? false;
|
|
585
587
|
const attachmentsDir = path.join(customerDir, "attachments");
|
|
586
588
|
const attachments = [];
|
|
589
|
+
const attachmentContents = {};
|
|
587
590
|
if (fs.existsSync(attachmentsDir)) try {
|
|
588
591
|
const files = fs.readdirSync(attachmentsDir);
|
|
589
592
|
for (const f of files) try {
|
|
590
|
-
if (fs.statSync(path.join(attachmentsDir, f)).isFile())
|
|
593
|
+
if (!fs.statSync(path.join(attachmentsDir, f)).isFile()) continue;
|
|
594
|
+
attachments.push(f);
|
|
595
|
+
if (includeAttachmentContent && f.endsWith(".md")) attachmentContents[f] = fs.readFileSync(path.join(attachmentsDir, f), "utf-8");
|
|
591
596
|
} catch {}
|
|
592
597
|
} catch {}
|
|
598
|
+
const attachmentContentSection = () => {
|
|
599
|
+
const entries = Object.entries(attachmentContents);
|
|
600
|
+
if (!includeAttachmentContent || entries.length === 0) return [];
|
|
601
|
+
return [
|
|
602
|
+
"",
|
|
603
|
+
`## Attachment Contents (${entries.length})`,
|
|
604
|
+
...entries.map(([name, content]) => `\n### ${name}\n\n${content.trim()}`)
|
|
605
|
+
];
|
|
606
|
+
};
|
|
593
607
|
if (format === "markdown") return { content: [{
|
|
594
608
|
type: "text",
|
|
595
609
|
text: [
|
|
@@ -608,7 +622,8 @@ async function handleExportCustomer(input, dataDir = DATA_DIR$47) {
|
|
|
608
622
|
pipeline.length > 0 ? pipeline.map((d) => `- **${d.name}** · ${d.stage}${d.value !== void 0 ? ` · €${d.value}` : ""}${d.close_date ? ` · close: ${d.close_date}` : ""}`).join("\n") : "(no deals)",
|
|
609
623
|
"",
|
|
610
624
|
`## Attachments (${attachments.length})`,
|
|
611
|
-
attachments.length > 0 ? attachments.map((f) => `- ${f}`).join("\n") : "(none)"
|
|
625
|
+
attachments.length > 0 ? attachments.map((f) => `- ${f}`).join("\n") : "(none)",
|
|
626
|
+
...attachmentContentSection()
|
|
612
627
|
].join("\n")
|
|
613
628
|
}] };
|
|
614
629
|
const exported = {
|
|
@@ -617,7 +632,8 @@ async function handleExportCustomer(input, dataDir = DATA_DIR$47) {
|
|
|
617
632
|
mainFacts,
|
|
618
633
|
interactionsCount,
|
|
619
634
|
pipeline,
|
|
620
|
-
attachments
|
|
635
|
+
attachments,
|
|
636
|
+
...includeAttachmentContent ? { attachmentContents } : {}
|
|
621
637
|
};
|
|
622
638
|
return { content: [{
|
|
623
639
|
type: "text",
|
|
@@ -627,29 +643,34 @@ async function handleExportCustomer(input, dataDir = DATA_DIR$47) {
|
|
|
627
643
|
function registerExportCustomer(server) {
|
|
628
644
|
server.registerTool("export_customer", {
|
|
629
645
|
title: "Export Customer",
|
|
630
|
-
description: `Export all customer data (main_facts + interactions
|
|
631
|
-
Useful for reporting, audits, or creating
|
|
646
|
+
description: `Export all customer data (main_facts + interactions + pipeline deals + attachments).
|
|
647
|
+
Useful for reporting, audits, handoffs, or creating a complete sendable bundle
|
|
648
|
+
of every conversation and document for a customer.
|
|
632
649
|
|
|
633
650
|
Args:
|
|
634
651
|
slug: Customer ID (e.g. "acme-corp")
|
|
635
652
|
format: Output format — "json" (default) or "markdown"
|
|
653
|
+
includeAttachmentContent: Inline the converted Markdown of every attachment
|
|
654
|
+
(default false). Use this to produce a single self-contained bundle.
|
|
636
655
|
|
|
637
656
|
Returns:
|
|
638
|
-
JSON: { slug, exportedAt, mainFacts, interactionsCount, pipeline }
|
|
639
|
-
Markdown: Formatted document with all sections`,
|
|
657
|
+
JSON: { slug, exportedAt, mainFacts, interactionsCount, pipeline, attachments[, attachmentContents] }
|
|
658
|
+
Markdown: Formatted document with all sections (and attachment contents when requested)`,
|
|
640
659
|
inputSchema: z.object({
|
|
641
660
|
slug: z.string().describe("Customer slug (e.g. 'acme-corp')"),
|
|
642
|
-
format: z.enum(["json", "markdown"]).optional().describe("Output format: 'json' (default) or 'markdown'")
|
|
661
|
+
format: z.enum(["json", "markdown"]).optional().describe("Output format: 'json' (default) or 'markdown'"),
|
|
662
|
+
includeAttachmentContent: z.boolean().optional().describe("Inline converted attachment Markdown into the export (default false)")
|
|
643
663
|
})
|
|
644
|
-
}, async ({ slug, format }) => handleExportCustomer({
|
|
664
|
+
}, async ({ slug, format, includeAttachmentContent }) => handleExportCustomer({
|
|
645
665
|
slug,
|
|
646
|
-
...format !== void 0 ? { format } : {}
|
|
666
|
+
...format !== void 0 ? { format } : {},
|
|
667
|
+
...includeAttachmentContent !== void 0 ? { includeAttachmentContent } : {}
|
|
647
668
|
}));
|
|
648
669
|
}
|
|
649
670
|
//#endregion
|
|
650
671
|
//#region src/mcp/tools/update-customer-facts.ts
|
|
651
|
-
const DATA_DIR$
|
|
652
|
-
async function handleUpdateCustomerFacts(input, dataDir = DATA_DIR$
|
|
672
|
+
const DATA_DIR$47 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
673
|
+
async function handleUpdateCustomerFacts(input, dataDir = DATA_DIR$47) {
|
|
653
674
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
654
675
|
try {
|
|
655
676
|
enforceRbac(dataDir, "update_customer_facts");
|
|
@@ -827,8 +848,8 @@ function scoreDealForToday(deal, todayDate) {
|
|
|
827
848
|
}
|
|
828
849
|
//#endregion
|
|
829
850
|
//#region src/mcp/tools/get-deal-health.ts
|
|
830
|
-
const DATA_DIR$
|
|
831
|
-
async function handleGetDealHealth(input, dataDir = DATA_DIR$
|
|
851
|
+
const DATA_DIR$46 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
852
|
+
async function handleGetDealHealth(input, dataDir = DATA_DIR$46) {
|
|
832
853
|
try {
|
|
833
854
|
const deals = await readPipeline(dataDir, input.slug);
|
|
834
855
|
const today = /* @__PURE__ */ new Date();
|
|
@@ -877,8 +898,8 @@ Returns: { slug, deals: [{ deal, stage, score, grade, signals, warnings }] }`,
|
|
|
877
898
|
}
|
|
878
899
|
//#endregion
|
|
879
900
|
//#region src/mcp/tools/get-pipeline-forecast.ts
|
|
880
|
-
const DATA_DIR$
|
|
881
|
-
async function handleGetPipelineForecast(input, dataDir = DATA_DIR$
|
|
901
|
+
const DATA_DIR$45 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
902
|
+
async function handleGetPipelineForecast(input, dataDir = DATA_DIR$45) {
|
|
882
903
|
try {
|
|
883
904
|
const slugs = listCustomerSlugs(dataDir).filter((d) => !input.filter || d.includes(input.filter));
|
|
884
905
|
const allDeals = [];
|
|
@@ -939,8 +960,8 @@ Returns: { deals: [...], totalWeightedValue: number, byStage: { stage: { count,
|
|
|
939
960
|
}
|
|
940
961
|
//#endregion
|
|
941
962
|
//#region src/mcp/tools/summarize-meeting.ts
|
|
942
|
-
const DATA_DIR$
|
|
943
|
-
async function handleSummarizeMeeting(input, dataDir = DATA_DIR$
|
|
963
|
+
const DATA_DIR$44 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
964
|
+
async function handleSummarizeMeeting(input, dataDir = DATA_DIR$44) {
|
|
944
965
|
try {
|
|
945
966
|
let summary = input.transcript.slice(0, 400);
|
|
946
967
|
let nextSteps = [];
|
|
@@ -1015,8 +1036,8 @@ Returns: { success, summary, nextSteps, sourceRef }`,
|
|
|
1015
1036
|
}
|
|
1016
1037
|
//#endregion
|
|
1017
1038
|
//#region src/mcp/tools/get-pipeline-stages.ts
|
|
1018
|
-
const DATA_DIR$
|
|
1019
|
-
async function handleGetPipelineStages(_input, dataDir = DATA_DIR$
|
|
1039
|
+
const DATA_DIR$43 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1040
|
+
async function handleGetPipelineStages(_input, dataDir = DATA_DIR$43) {
|
|
1020
1041
|
const stages = getPipelineStages(dataDir);
|
|
1021
1042
|
return { content: [{
|
|
1022
1043
|
type: "text",
|
|
@@ -1044,8 +1065,8 @@ async function searchAcrossCustomers(dataDir, query, limit = 5, excludeSlug) {
|
|
|
1044
1065
|
}
|
|
1045
1066
|
//#endregion
|
|
1046
1067
|
//#region src/mcp/tools/get-market-intelligence.ts
|
|
1047
|
-
const DATA_DIR$
|
|
1048
|
-
async function handleGetMarketIntelligence(input, dataDir = DATA_DIR$
|
|
1068
|
+
const DATA_DIR$42 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1069
|
+
async function handleGetMarketIntelligence(input, dataDir = DATA_DIR$42) {
|
|
1049
1070
|
const excludeSlug = input.excludeCurrentCustomer ? input.slug : void 0;
|
|
1050
1071
|
const all = listCustomerSlugs(dataDir);
|
|
1051
1072
|
const totalCustomersSearched = excludeSlug ? all.filter((s) => s !== excludeSlug).length : all.length;
|
|
@@ -1076,7 +1097,7 @@ function registerGetMarketIntelligence(server) {
|
|
|
1076
1097
|
}
|
|
1077
1098
|
//#endregion
|
|
1078
1099
|
//#region src/mcp/tools/get-relationship-graph.ts
|
|
1079
|
-
const DATA_DIR$
|
|
1100
|
+
const DATA_DIR$41 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1080
1101
|
function summarizeNode(n) {
|
|
1081
1102
|
return {
|
|
1082
1103
|
id: n.id,
|
|
@@ -1084,7 +1105,7 @@ function summarizeNode(n) {
|
|
|
1084
1105
|
email: n.properties["email"]
|
|
1085
1106
|
};
|
|
1086
1107
|
}
|
|
1087
|
-
async function handleGetRelationshipGraph(input, dataDir = DATA_DIR$
|
|
1108
|
+
async function handleGetRelationshipGraph(input, dataDir = DATA_DIR$41) {
|
|
1088
1109
|
try {
|
|
1089
1110
|
const graph = readGraph(dataDir, input.slug);
|
|
1090
1111
|
const stakeholders = getStakeholders(graph);
|
|
@@ -1152,9 +1173,9 @@ Returns: {
|
|
|
1152
1173
|
}
|
|
1153
1174
|
//#endregion
|
|
1154
1175
|
//#region src/mcp/tools/get-relationship-health.ts
|
|
1155
|
-
const DATA_DIR$
|
|
1176
|
+
const DATA_DIR$40 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1156
1177
|
const MAX_HEALTH_AGE_MS = 3600 * 1e3;
|
|
1157
|
-
async function handleGetRelationshipHealth(input, dataDir = DATA_DIR$
|
|
1178
|
+
async function handleGetRelationshipHealth(input, dataDir = DATA_DIR$40) {
|
|
1158
1179
|
try {
|
|
1159
1180
|
let health = readHealth(dataDir, input.slug);
|
|
1160
1181
|
if (health === null || Date.now() - new Date(health.updatedAt).getTime() > MAX_HEALTH_AGE_MS) {
|
|
@@ -1704,7 +1725,7 @@ async function executeAction(action, dataDir) {
|
|
|
1704
1725
|
if (!slug) return "skipped";
|
|
1705
1726
|
switch (action.type) {
|
|
1706
1727
|
case "log_interaction": {
|
|
1707
|
-
const { appendInteraction } = await import("./interactions-writer-
|
|
1728
|
+
const { appendInteraction } = await import("./interactions-writer-B2y-73lh.js");
|
|
1708
1729
|
await appendInteraction(dataDir, slug, {
|
|
1709
1730
|
date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
1710
1731
|
type: action.payload["type"] ?? "Note",
|
|
@@ -1717,7 +1738,7 @@ async function executeAction(action, dataDir) {
|
|
|
1717
1738
|
return "executed";
|
|
1718
1739
|
}
|
|
1719
1740
|
case "schedule_meeting": {
|
|
1720
|
-
const { appendInteraction } = await import("./interactions-writer-
|
|
1741
|
+
const { appendInteraction } = await import("./interactions-writer-B2y-73lh.js");
|
|
1721
1742
|
await appendInteraction(dataDir, slug, {
|
|
1722
1743
|
date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
1723
1744
|
type: "Note",
|
|
@@ -1823,8 +1844,8 @@ async function runDealAgent(config, dataDir, llmFn = callLlm) {
|
|
|
1823
1844
|
}
|
|
1824
1845
|
//#endregion
|
|
1825
1846
|
//#region src/mcp/tools/run-deal-agent.ts
|
|
1826
|
-
const DATA_DIR$
|
|
1827
|
-
async function handleRunDealAgent(input, dataDir = DATA_DIR$
|
|
1847
|
+
const DATA_DIR$39 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1848
|
+
async function handleRunDealAgent(input, dataDir = DATA_DIR$39) {
|
|
1828
1849
|
try {
|
|
1829
1850
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
1830
1851
|
const result = await runDealAgent({
|
|
@@ -1891,8 +1912,8 @@ Returns: { assessment, riskLevel, plan[], actionsQueued[], actionsExecuted[], tr
|
|
|
1891
1912
|
}
|
|
1892
1913
|
//#endregion
|
|
1893
1914
|
//#region src/mcp/tools/approve-agent-action.ts
|
|
1894
|
-
const DATA_DIR$
|
|
1895
|
-
async function handleApproveAgentAction(input, dataDir = DATA_DIR$
|
|
1915
|
+
const DATA_DIR$38 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1916
|
+
async function handleApproveAgentAction(input, dataDir = DATA_DIR$38) {
|
|
1896
1917
|
try {
|
|
1897
1918
|
const queue = readAgentQueue(dataDir, input.slug);
|
|
1898
1919
|
const idx = queue.pendingActions.findIndex((a) => a.actionId === input.actionId);
|
|
@@ -1969,8 +1990,8 @@ Returns: { success, actionId, status }`,
|
|
|
1969
1990
|
}
|
|
1970
1991
|
//#endregion
|
|
1971
1992
|
//#region src/mcp/tools/simulate-revenue.ts
|
|
1972
|
-
const DATA_DIR$
|
|
1973
|
-
async function handleSimulateRevenue(input, dataDir = DATA_DIR$
|
|
1993
|
+
const DATA_DIR$37 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1994
|
+
async function handleSimulateRevenue(input, dataDir = DATA_DIR$37) {
|
|
1974
1995
|
try {
|
|
1975
1996
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
1976
1997
|
const horizon = input.horizon ?? "quarter";
|
|
@@ -2028,8 +2049,8 @@ Returns: { forecast: { p10, p50, p90, expected, stdDev, atRiskRevenue, byCloseMo
|
|
|
2028
2049
|
}
|
|
2029
2050
|
//#endregion
|
|
2030
2051
|
//#region src/mcp/tools/get-playbook.ts
|
|
2031
|
-
const DATA_DIR$
|
|
2032
|
-
async function handleGetPlaybook(input, dataDir = DATA_DIR$
|
|
2052
|
+
const DATA_DIR$36 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2053
|
+
async function handleGetPlaybook(input, dataDir = DATA_DIR$36) {
|
|
2033
2054
|
try {
|
|
2034
2055
|
const playbooks = listPlaybooks(dataDir, input.slug);
|
|
2035
2056
|
if (!(input.stage !== void 0 || input.value !== void 0 || input.healthScore !== void 0)) return { content: [{
|
|
@@ -2114,12 +2135,12 @@ Returns: { matches: [{ name, score, trigger, successRate, usedCount, content }],
|
|
|
2114
2135
|
...healthScore !== void 0 ? { healthScore } : {},
|
|
2115
2136
|
...daysSinceContact !== void 0 ? { daysSinceContact } : {},
|
|
2116
2137
|
...championPresent !== void 0 ? { championPresent } : {}
|
|
2117
|
-
}, DATA_DIR$
|
|
2138
|
+
}, DATA_DIR$36));
|
|
2118
2139
|
}
|
|
2119
2140
|
//#endregion
|
|
2120
2141
|
//#region src/mcp/tools/create-playbook.ts
|
|
2121
|
-
const DATA_DIR$
|
|
2122
|
-
async function handleCreatePlaybook(input, dataDir = DATA_DIR$
|
|
2142
|
+
const DATA_DIR$35 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2143
|
+
async function handleCreatePlaybook(input, dataDir = DATA_DIR$35) {
|
|
2123
2144
|
try {
|
|
2124
2145
|
const name = toKebabCase(input.name);
|
|
2125
2146
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -2192,12 +2213,12 @@ Returns: { success: true, playbook: { name, trigger, successRate, path } }`,
|
|
|
2192
2213
|
trigger,
|
|
2193
2214
|
content,
|
|
2194
2215
|
...successRate !== void 0 ? { successRate } : {}
|
|
2195
|
-
}, DATA_DIR$
|
|
2216
|
+
}, DATA_DIR$35));
|
|
2196
2217
|
}
|
|
2197
2218
|
//#endregion
|
|
2198
2219
|
//#region src/mcp/tools/list-playbooks.ts
|
|
2199
|
-
const DATA_DIR$
|
|
2200
|
-
async function handleListPlaybooks(input, dataDir = DATA_DIR$
|
|
2220
|
+
const DATA_DIR$34 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2221
|
+
async function handleListPlaybooks(input, dataDir = DATA_DIR$34) {
|
|
2201
2222
|
try {
|
|
2202
2223
|
const playbooks = listPlaybooks(dataDir, input.slug);
|
|
2203
2224
|
return { content: [{
|
|
@@ -2236,12 +2257,12 @@ Args:
|
|
|
2236
2257
|
|
|
2237
2258
|
Returns: { playbooks: [{ name, trigger, successRate, usedCount, lastUpdated }], count, slug }`,
|
|
2238
2259
|
inputSchema: z.object({ slug: z.string().describe("Customer ID") })
|
|
2239
|
-
}, async ({ slug }) => handleListPlaybooks({ slug }, DATA_DIR$
|
|
2260
|
+
}, async ({ slug }) => handleListPlaybooks({ slug }, DATA_DIR$34));
|
|
2240
2261
|
}
|
|
2241
2262
|
//#endregion
|
|
2242
2263
|
//#region src/mcp/tools/distill-playbook.ts
|
|
2243
|
-
const DATA_DIR$
|
|
2244
|
-
async function handleDistillPlaybook(input, dataDir = DATA_DIR$
|
|
2264
|
+
const DATA_DIR$33 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2265
|
+
async function handleDistillPlaybook(input, dataDir = DATA_DIR$33, llmFn = callLlm) {
|
|
2245
2266
|
try {
|
|
2246
2267
|
const result = await distillPlaybook(dataDir, input.slug, input.dealName, input.outcome, llmFn);
|
|
2247
2268
|
if (!result.ok) {
|
|
@@ -2300,12 +2321,12 @@ Returns: { success: true, playbook: { name, trigger, successRate, path }, reason
|
|
|
2300
2321
|
slug,
|
|
2301
2322
|
dealName,
|
|
2302
2323
|
outcome
|
|
2303
|
-
}, DATA_DIR$
|
|
2324
|
+
}, DATA_DIR$33));
|
|
2304
2325
|
}
|
|
2305
2326
|
//#endregion
|
|
2306
2327
|
//#region src/mcp/tools/pursue-goal.ts
|
|
2307
|
-
const DATA_DIR$
|
|
2308
|
-
async function handlePursueGoal(input, dataDir = DATA_DIR$
|
|
2328
|
+
const DATA_DIR$32 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2329
|
+
async function handlePursueGoal(input, dataDir = DATA_DIR$32, options = {}) {
|
|
2309
2330
|
try {
|
|
2310
2331
|
enforceRbac(dataDir, "pursue_goal");
|
|
2311
2332
|
const goal = await pursueGoal(dataDir, {
|
|
@@ -2368,12 +2389,12 @@ Returns: { goalId, description, target, deadline, decomposition: { analysis, cur
|
|
|
2368
2389
|
goal,
|
|
2369
2390
|
deadline,
|
|
2370
2391
|
...context !== void 0 ? { context } : {}
|
|
2371
|
-
}, DATA_DIR$
|
|
2392
|
+
}, DATA_DIR$32));
|
|
2372
2393
|
}
|
|
2373
2394
|
//#endregion
|
|
2374
2395
|
//#region src/mcp/tools/get-goal-status.ts
|
|
2375
|
-
const DATA_DIR$
|
|
2376
|
-
async function handleGetGoalStatus(input, dataDir = DATA_DIR$
|
|
2396
|
+
const DATA_DIR$31 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2397
|
+
async function handleGetGoalStatus(input, dataDir = DATA_DIR$31) {
|
|
2377
2398
|
try {
|
|
2378
2399
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2379
2400
|
const allGoals = input.goalId ? readGoals(dataDir).filter((g) => g.id === input.goalId) : getActiveGoals(dataDir);
|
|
@@ -2432,17 +2453,17 @@ Args:
|
|
|
2432
2453
|
|
|
2433
2454
|
Returns: { goals: [{ id, description, target, progress, status, deadline, daysRemaining, subGoals }], activeCount, completedCount }`,
|
|
2434
2455
|
inputSchema: z.object({ goalId: z.string().optional().describe("Specific goal ID (omit for all active goals)") })
|
|
2435
|
-
}, async ({ goalId }) => handleGetGoalStatus({ ...goalId !== void 0 ? { goalId } : {} }, DATA_DIR$
|
|
2456
|
+
}, async ({ goalId }) => handleGetGoalStatus({ ...goalId !== void 0 ? { goalId } : {} }, DATA_DIR$31));
|
|
2436
2457
|
}
|
|
2437
2458
|
//#endregion
|
|
2438
2459
|
//#region src/mcp/tools/register-push-subscription.ts
|
|
2439
|
-
const DATA_DIR$
|
|
2460
|
+
const DATA_DIR$30 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2440
2461
|
const VALID_PROVIDERS = [
|
|
2441
2462
|
"gmail",
|
|
2442
2463
|
"microsoft-graph",
|
|
2443
2464
|
"slack"
|
|
2444
2465
|
];
|
|
2445
|
-
async function handleRegisterPushSubscription(input, dataDir = DATA_DIR$
|
|
2466
|
+
async function handleRegisterPushSubscription(input, dataDir = DATA_DIR$30) {
|
|
2446
2467
|
try {
|
|
2447
2468
|
if (!VALID_PROVIDERS.includes(input.provider)) return { content: [{
|
|
2448
2469
|
type: "text",
|
|
@@ -2528,12 +2549,12 @@ Returns: { subscriptionId, provider, slug, status, expiresAt, createdAt, warning
|
|
|
2528
2549
|
...microsoftResource !== void 0 ? { microsoftResource } : {},
|
|
2529
2550
|
...slackTeamId !== void 0 ? { slackTeamId } : {},
|
|
2530
2551
|
...slackChannelId !== void 0 ? { slackChannelId } : {}
|
|
2531
|
-
}, DATA_DIR$
|
|
2552
|
+
}, DATA_DIR$30));
|
|
2532
2553
|
}
|
|
2533
2554
|
//#endregion
|
|
2534
2555
|
//#region src/mcp/tools/get-push-status.ts
|
|
2535
|
-
const DATA_DIR$
|
|
2536
|
-
async function handleGetPushStatus(input, dataDir = DATA_DIR$
|
|
2556
|
+
const DATA_DIR$29 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2557
|
+
async function handleGetPushStatus(input, dataDir = DATA_DIR$29) {
|
|
2537
2558
|
try {
|
|
2538
2559
|
let subs = await readSubscriptions(dataDir);
|
|
2539
2560
|
if (input.slug) subs = subs.filter((s) => s.slug === input.slug);
|
|
@@ -2605,7 +2626,7 @@ Returns: { subscriptions: [{ id, provider, slug, status, expiresAt, expiresInHou
|
|
|
2605
2626
|
}, async ({ slug, provider }) => handleGetPushStatus({
|
|
2606
2627
|
...slug !== void 0 ? { slug } : {},
|
|
2607
2628
|
...provider !== void 0 ? { provider } : {}
|
|
2608
|
-
}, DATA_DIR$
|
|
2629
|
+
}, DATA_DIR$29));
|
|
2609
2630
|
}
|
|
2610
2631
|
//#endregion
|
|
2611
2632
|
//#region src/core/org-intelligence.ts
|
|
@@ -2671,8 +2692,8 @@ function deriveRecommendation(people, missingRoles) {
|
|
|
2671
2692
|
}
|
|
2672
2693
|
//#endregion
|
|
2673
2694
|
//#region src/mcp/tools/get-org-intelligence.ts
|
|
2674
|
-
const DATA_DIR$
|
|
2675
|
-
async function handleGetOrgIntelligence(input, dataDir = DATA_DIR$
|
|
2695
|
+
const DATA_DIR$28 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2696
|
+
async function handleGetOrgIntelligence(input, dataDir = DATA_DIR$28) {
|
|
2676
2697
|
try {
|
|
2677
2698
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2678
2699
|
const map = buildStakeholderMap(dataDir, input.slug, today, input.dealName);
|
|
@@ -2805,8 +2826,8 @@ function buildExecutiveSummary(slug, dealName, stakeholders, overallHealth, sim,
|
|
|
2805
2826
|
}
|
|
2806
2827
|
//#endregion
|
|
2807
2828
|
//#region src/mcp/tools/open-deal-room.ts
|
|
2808
|
-
const DATA_DIR$
|
|
2809
|
-
async function handleOpenDealRoom(input, dataDir = DATA_DIR$
|
|
2829
|
+
const DATA_DIR$27 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2830
|
+
async function handleOpenDealRoom(input, dataDir = DATA_DIR$27) {
|
|
2810
2831
|
try {
|
|
2811
2832
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2812
2833
|
const brief = await buildDealRoom(dataDir, input.slug, input.dealName, today);
|
|
@@ -2841,8 +2862,8 @@ Returns: { slug, dealName, generatedAt, stakeholders, relationshipHealth, dealHe
|
|
|
2841
2862
|
}
|
|
2842
2863
|
//#endregion
|
|
2843
2864
|
//#region src/mcp/tools/get-proactive-briefing.ts
|
|
2844
|
-
const DATA_DIR$
|
|
2845
|
-
async function handleGetProactiveBriefing(input, dataDir = DATA_DIR$
|
|
2865
|
+
const DATA_DIR$26 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2866
|
+
async function handleGetProactiveBriefing(input, dataDir = DATA_DIR$26) {
|
|
2846
2867
|
try {
|
|
2847
2868
|
const briefing = await buildDailyBriefing(dataDir, input.date ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10));
|
|
2848
2869
|
return { content: [{
|
|
@@ -2870,15 +2891,15 @@ Returns: { date, generatedAt, urgent: string[], opportunities: string[], forecas
|
|
|
2870
2891
|
}
|
|
2871
2892
|
//#endregion
|
|
2872
2893
|
//#region src/mcp/tools/list-email-templates.ts
|
|
2873
|
-
const DATA_DIR$
|
|
2874
|
-
async function handleListEmailTemplates(input, dataDir = DATA_DIR$
|
|
2894
|
+
const DATA_DIR$25 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2895
|
+
async function handleListEmailTemplates(input, dataDir = DATA_DIR$25) {
|
|
2875
2896
|
const summary = listTemplates(dataDir, input.category ? { category: input.category } : {}).map(({ body: _body, ...meta }) => meta);
|
|
2876
2897
|
return { content: [{
|
|
2877
2898
|
type: "text",
|
|
2878
2899
|
text: JSON.stringify(summary, null, 2)
|
|
2879
2900
|
}] };
|
|
2880
2901
|
}
|
|
2881
|
-
function registerListEmailTemplates(server, dataDir = DATA_DIR$
|
|
2902
|
+
function registerListEmailTemplates(server, dataDir = DATA_DIR$25) {
|
|
2882
2903
|
server.registerTool("list_email_templates", {
|
|
2883
2904
|
description: "List available email templates. Optionally filter by category (e.g. 'outreach', 'followup', 'support').",
|
|
2884
2905
|
inputSchema: z.object({ category: z.string().optional().describe("Filter by category") })
|
|
@@ -2886,8 +2907,8 @@ function registerListEmailTemplates(server, dataDir = DATA_DIR$24) {
|
|
|
2886
2907
|
}
|
|
2887
2908
|
//#endregion
|
|
2888
2909
|
//#region src/mcp/tools/get-email-template.ts
|
|
2889
|
-
const DATA_DIR$
|
|
2890
|
-
async function handleGetEmailTemplate(input, dataDir = DATA_DIR$
|
|
2910
|
+
const DATA_DIR$24 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2911
|
+
async function handleGetEmailTemplate(input, dataDir = DATA_DIR$24) {
|
|
2891
2912
|
const tmpl = getTemplate(dataDir, input.id);
|
|
2892
2913
|
if (!tmpl) return { content: [{
|
|
2893
2914
|
type: "text",
|
|
@@ -2903,7 +2924,7 @@ async function handleGetEmailTemplate(input, dataDir = DATA_DIR$23) {
|
|
|
2903
2924
|
}, null, 2)
|
|
2904
2925
|
}] };
|
|
2905
2926
|
}
|
|
2906
|
-
function registerGetEmailTemplate(server, dataDir = DATA_DIR$
|
|
2927
|
+
function registerGetEmailTemplate(server, dataDir = DATA_DIR$24) {
|
|
2907
2928
|
server.registerTool("get_email_template", {
|
|
2908
2929
|
description: "Get a specific email template by ID, including its body and detected variables.",
|
|
2909
2930
|
inputSchema: z.object({ id: z.string().describe("Template ID (e.g. 'enterprise-intro')") })
|
|
@@ -2911,8 +2932,8 @@ function registerGetEmailTemplate(server, dataDir = DATA_DIR$23) {
|
|
|
2911
2932
|
}
|
|
2912
2933
|
//#endregion
|
|
2913
2934
|
//#region src/mcp/tools/draft-email.ts
|
|
2914
|
-
const DATA_DIR$
|
|
2915
|
-
async function handleDraftEmail(input, dataDir = DATA_DIR$
|
|
2935
|
+
const DATA_DIR$23 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2936
|
+
async function handleDraftEmail(input, dataDir = DATA_DIR$23) {
|
|
2916
2937
|
const tmpl = getTemplate(dataDir, input.templateId);
|
|
2917
2938
|
if (!tmpl) return { content: [{
|
|
2918
2939
|
type: "text",
|
|
@@ -2956,7 +2977,7 @@ async function handleDraftEmail(input, dataDir = DATA_DIR$22) {
|
|
|
2956
2977
|
}, null, 2)
|
|
2957
2978
|
}] };
|
|
2958
2979
|
}
|
|
2959
|
-
function registerDraftEmail(server, dataDir = DATA_DIR$
|
|
2980
|
+
function registerDraftEmail(server, dataDir = DATA_DIR$23) {
|
|
2960
2981
|
server.registerTool("draft_email", {
|
|
2961
2982
|
description: `Draft a personalized email for a customer using a stored template.
|
|
2962
2983
|
Variables are auto-filled from the customer's main_facts.md. Override any variable manually.
|
|
@@ -2978,8 +2999,8 @@ Returns: { subject, body, to, tone, polished, resolvedVariables } — does NOT s
|
|
|
2978
2999
|
}
|
|
2979
3000
|
//#endregion
|
|
2980
3001
|
//#region src/mcp/tools/enroll-in-sequence.ts
|
|
2981
|
-
const DATA_DIR$
|
|
2982
|
-
async function handleEnrollInSequence(input, dataDir = DATA_DIR$
|
|
3002
|
+
const DATA_DIR$22 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3003
|
+
async function handleEnrollInSequence(input, dataDir = DATA_DIR$22) {
|
|
2983
3004
|
const sequence = getSequence(dataDir, input.sequenceId);
|
|
2984
3005
|
if (!sequence) return { content: [{
|
|
2985
3006
|
type: "text",
|
|
@@ -3011,7 +3032,7 @@ async function handleEnrollInSequence(input, dataDir = DATA_DIR$21) {
|
|
|
3011
3032
|
})
|
|
3012
3033
|
}] };
|
|
3013
3034
|
}
|
|
3014
|
-
function registerEnrollInSequence(server, dataDir = DATA_DIR$
|
|
3035
|
+
function registerEnrollInSequence(server, dataDir = DATA_DIR$22) {
|
|
3015
3036
|
server.registerTool("enroll_in_sequence", {
|
|
3016
3037
|
description: `Enroll a contact in an email sequence. Validates that the sequence and its first template exist.
|
|
3017
3038
|
Returns: { enrollmentId, sequenceName, totalSteps }`,
|
|
@@ -3028,8 +3049,8 @@ Returns: { enrollmentId, sequenceName, totalSteps }`,
|
|
|
3028
3049
|
}
|
|
3029
3050
|
//#endregion
|
|
3030
3051
|
//#region src/mcp/tools/list-sequence-enrollments.ts
|
|
3031
|
-
const DATA_DIR$
|
|
3032
|
-
async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$
|
|
3052
|
+
const DATA_DIR$21 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3053
|
+
async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$21) {
|
|
3033
3054
|
let enrollments = readEnrollments(dataDir);
|
|
3034
3055
|
if (input.slug !== void 0) enrollments = enrollments.filter((e) => e.slug === input.slug);
|
|
3035
3056
|
if (input.status !== void 0) enrollments = enrollments.filter((e) => e.status === input.status);
|
|
@@ -3038,7 +3059,7 @@ async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$20) {
|
|
|
3038
3059
|
text: JSON.stringify({ enrollments }, null, 2)
|
|
3039
3060
|
}] };
|
|
3040
3061
|
}
|
|
3041
|
-
function registerListSequenceEnrollments(server, dataDir = DATA_DIR$
|
|
3062
|
+
function registerListSequenceEnrollments(server, dataDir = DATA_DIR$21) {
|
|
3042
3063
|
server.registerTool("list_sequence_enrollments", {
|
|
3043
3064
|
description: `List email sequence enrollments. Filter by customer slug or status.
|
|
3044
3065
|
Returns: { enrollments: SequenceEnrollment[] }`,
|
|
@@ -3057,8 +3078,8 @@ Returns: { enrollments: SequenceEnrollment[] }`,
|
|
|
3057
3078
|
}
|
|
3058
3079
|
//#endregion
|
|
3059
3080
|
//#region src/mcp/tools/unenroll-from-sequence.ts
|
|
3060
|
-
const DATA_DIR$
|
|
3061
|
-
async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$
|
|
3081
|
+
const DATA_DIR$20 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3082
|
+
async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$20) {
|
|
3062
3083
|
if (!await updateEnrollment(dataDir, input.enrollmentId, { status: "paused" })) return { content: [{
|
|
3063
3084
|
type: "text",
|
|
3064
3085
|
text: JSON.stringify({
|
|
@@ -3071,7 +3092,7 @@ async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$19) {
|
|
|
3071
3092
|
text: JSON.stringify({ success: true })
|
|
3072
3093
|
}] };
|
|
3073
3094
|
}
|
|
3074
|
-
function registerUnenrollFromSequence(server, dataDir = DATA_DIR$
|
|
3095
|
+
function registerUnenrollFromSequence(server, dataDir = DATA_DIR$20) {
|
|
3075
3096
|
server.registerTool("unenroll_from_sequence", {
|
|
3076
3097
|
description: `Unenroll (pause) a contact from an email sequence. Sets status to "paused" (soft delete).
|
|
3077
3098
|
Returns: { success: boolean }`,
|
|
@@ -3080,8 +3101,8 @@ Returns: { success: boolean }`,
|
|
|
3080
3101
|
}
|
|
3081
3102
|
//#endregion
|
|
3082
3103
|
//#region src/mcp/tools/list-sequences.ts
|
|
3083
|
-
const DATA_DIR$
|
|
3084
|
-
async function handleListSequences(_input, dataDir = DATA_DIR$
|
|
3104
|
+
const DATA_DIR$19 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3105
|
+
async function handleListSequences(_input, dataDir = DATA_DIR$19) {
|
|
3085
3106
|
const sequences = listSequences(dataDir);
|
|
3086
3107
|
const enrollments = readEnrollments(dataDir);
|
|
3087
3108
|
const result = sequences.map((seq) => ({
|
|
@@ -3095,7 +3116,7 @@ async function handleListSequences(_input, dataDir = DATA_DIR$18) {
|
|
|
3095
3116
|
text: JSON.stringify({ sequences: result }, null, 2)
|
|
3096
3117
|
}] };
|
|
3097
3118
|
}
|
|
3098
|
-
function registerListSequences(server, dataDir = DATA_DIR$
|
|
3119
|
+
function registerListSequences(server, dataDir = DATA_DIR$19) {
|
|
3099
3120
|
server.registerTool("list_sequences", {
|
|
3100
3121
|
description: `List all email sequences with step count and enrollment count.
|
|
3101
3122
|
Returns: { sequences: Array<{ id, name, stepCount, enrollmentCount }> }`,
|
|
@@ -3104,8 +3125,8 @@ Returns: { sequences: Array<{ id, name, stepCount, enrollmentCount }> }`,
|
|
|
3104
3125
|
}
|
|
3105
3126
|
//#endregion
|
|
3106
3127
|
//#region src/mcp/tools/generate-quote.ts
|
|
3107
|
-
const DATA_DIR$
|
|
3108
|
-
async function handleGenerateQuote(input, dataDir = DATA_DIR$
|
|
3128
|
+
const DATA_DIR$18 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3129
|
+
async function handleGenerateQuote(input, dataDir = DATA_DIR$18) {
|
|
3109
3130
|
try {
|
|
3110
3131
|
const quote = await generateQuote(dataDir, input);
|
|
3111
3132
|
return { content: [{
|
|
@@ -3129,7 +3150,7 @@ async function handleGenerateQuote(input, dataDir = DATA_DIR$17) {
|
|
|
3129
3150
|
}] };
|
|
3130
3151
|
}
|
|
3131
3152
|
}
|
|
3132
|
-
function registerGenerateQuote(server, dataDir = DATA_DIR$
|
|
3153
|
+
function registerGenerateQuote(server, dataDir = DATA_DIR$18) {
|
|
3133
3154
|
server.registerTool("generate_quote", {
|
|
3134
3155
|
description: `Generate a professional HTML quote/offer for a customer deal.
|
|
3135
3156
|
Calculates subtotal, VAT, and total. Saves JSON + HTML to .agentic/quotes/.
|
|
@@ -3157,8 +3178,8 @@ Returns: { quoteNumber, htmlPath, total, currency, validUntil }`,
|
|
|
3157
3178
|
}
|
|
3158
3179
|
//#endregion
|
|
3159
3180
|
//#region src/mcp/tools/get-quote-status.ts
|
|
3160
|
-
const DATA_DIR$
|
|
3161
|
-
async function handleGetQuoteStatus(input, dataDir = DATA_DIR$
|
|
3181
|
+
const DATA_DIR$17 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3182
|
+
async function handleGetQuoteStatus(input, dataDir = DATA_DIR$17) {
|
|
3162
3183
|
if (input.quoteNumber) {
|
|
3163
3184
|
const quote = readQuote(dataDir, input.quoteNumber);
|
|
3164
3185
|
if (!quote) return { content: [{
|
|
@@ -3176,7 +3197,7 @@ async function handleGetQuoteStatus(input, dataDir = DATA_DIR$16) {
|
|
|
3176
3197
|
text: JSON.stringify({ quotes }, null, 2)
|
|
3177
3198
|
}] };
|
|
3178
3199
|
}
|
|
3179
|
-
function registerGetQuoteStatus(server, dataDir = DATA_DIR$
|
|
3200
|
+
function registerGetQuoteStatus(server, dataDir = DATA_DIR$17) {
|
|
3180
3201
|
server.registerTool("get_quote_status", {
|
|
3181
3202
|
description: `Get quote status and details. Filter by quoteNumber (single quote) or slug (all quotes for a customer).
|
|
3182
3203
|
Returns quote with status: draft | sent | viewed | accepted | declined`,
|
|
@@ -3191,7 +3212,7 @@ Returns quote with status: draft | sent | viewed | accepted | declined`,
|
|
|
3191
3212
|
}
|
|
3192
3213
|
//#endregion
|
|
3193
3214
|
//#region src/mcp/tools/get-booking-link.ts
|
|
3194
|
-
const DATA_DIR$
|
|
3215
|
+
const DATA_DIR$16 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3195
3216
|
function loadCalendlyConfig(dataDir) {
|
|
3196
3217
|
const p = path.join(dataDir, ".agentic", "integrations", "calendly.yaml");
|
|
3197
3218
|
if (!fs.existsSync(p)) return {};
|
|
@@ -3214,7 +3235,7 @@ function readCustomerFacts(dataDir, slug) {
|
|
|
3214
3235
|
...email ? { email } : {}
|
|
3215
3236
|
};
|
|
3216
3237
|
}
|
|
3217
|
-
async function handleGetBookingLink(input, dataDir = DATA_DIR$
|
|
3238
|
+
async function handleGetBookingLink(input, dataDir = DATA_DIR$16) {
|
|
3218
3239
|
const config = loadCalendlyConfig(dataDir);
|
|
3219
3240
|
const apiKey = config.apiKey ?? process.env["CALENDLY_API_KEY"] ?? "";
|
|
3220
3241
|
if (!apiKey) return { content: [{
|
|
@@ -3242,7 +3263,7 @@ async function handleGetBookingLink(input, dataDir = DATA_DIR$15) {
|
|
|
3242
3263
|
}] };
|
|
3243
3264
|
}
|
|
3244
3265
|
}
|
|
3245
|
-
function registerGetBookingLink(server, dataDir = DATA_DIR$
|
|
3266
|
+
function registerGetBookingLink(server, dataDir = DATA_DIR$16) {
|
|
3246
3267
|
server.registerTool("get_booking_link", {
|
|
3247
3268
|
description: `Get a Calendly booking link for a customer. Optionally pre-fills the customer's name/email.
|
|
3248
3269
|
Requires CALENDLY_API_KEY env var or .agentic/integrations/calendly.yaml config.
|
|
@@ -3260,8 +3281,8 @@ Returns: { bookingUrl, eventType, duration }`,
|
|
|
3260
3281
|
}
|
|
3261
3282
|
//#endregion
|
|
3262
3283
|
//#region src/mcp/tools/create-ticket.ts
|
|
3263
|
-
const DATA_DIR$
|
|
3264
|
-
async function handleCreateTicket(input, dataDir = DATA_DIR$
|
|
3284
|
+
const DATA_DIR$15 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3285
|
+
async function handleCreateTicket(input, dataDir = DATA_DIR$15) {
|
|
3265
3286
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
3266
3287
|
const rules = loadSlaRules(dataDir);
|
|
3267
3288
|
const priority = input.priority ?? "normal";
|
|
@@ -3283,7 +3304,7 @@ async function handleCreateTicket(input, dataDir = DATA_DIR$14) {
|
|
|
3283
3304
|
text: JSON.stringify({ ticket }, null, 2)
|
|
3284
3305
|
}] };
|
|
3285
3306
|
}
|
|
3286
|
-
function registerCreateTicket(server, dataDir = DATA_DIR$
|
|
3307
|
+
function registerCreateTicket(server, dataDir = DATA_DIR$15) {
|
|
3287
3308
|
server.registerTool("create_ticket", {
|
|
3288
3309
|
description: `Create a support ticket for a customer. Auto-calculates SLA due date based on priority.
|
|
3289
3310
|
Returns: { ticket } with id T-NNN, status=open, slaDue`,
|
|
@@ -3309,8 +3330,8 @@ Returns: { ticket } with id T-NNN, status=open, slaDue`,
|
|
|
3309
3330
|
}
|
|
3310
3331
|
//#endregion
|
|
3311
3332
|
//#region src/mcp/tools/update-ticket.ts
|
|
3312
|
-
const DATA_DIR$
|
|
3313
|
-
async function handleUpdateTicket(input, dataDir = DATA_DIR$
|
|
3333
|
+
const DATA_DIR$14 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3334
|
+
async function handleUpdateTicket(input, dataDir = DATA_DIR$14) {
|
|
3314
3335
|
const ticket = (await readTickets(dataDir, input.slug)).find((t) => t.id === input.ticketId);
|
|
3315
3336
|
if (!ticket) return { content: [{
|
|
3316
3337
|
type: "text",
|
|
@@ -3329,7 +3350,7 @@ async function handleUpdateTicket(input, dataDir = DATA_DIR$13) {
|
|
|
3329
3350
|
text: JSON.stringify({ ticket: updated }, null, 2)
|
|
3330
3351
|
}] };
|
|
3331
3352
|
}
|
|
3332
|
-
function registerUpdateTicket(server, dataDir = DATA_DIR$
|
|
3353
|
+
function registerUpdateTicket(server, dataDir = DATA_DIR$14) {
|
|
3333
3354
|
server.registerTool("update_ticket", {
|
|
3334
3355
|
description: `Update a ticket's status or assignee. Setting status=resolved auto-sets resolved date.
|
|
3335
3356
|
Returns: { ticket }`,
|
|
@@ -3354,8 +3375,8 @@ Returns: { ticket }`,
|
|
|
3354
3375
|
}
|
|
3355
3376
|
//#endregion
|
|
3356
3377
|
//#region src/mcp/tools/list-tickets.ts
|
|
3357
|
-
const DATA_DIR$
|
|
3358
|
-
async function handleListTickets(input, dataDir = DATA_DIR$
|
|
3378
|
+
const DATA_DIR$13 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3379
|
+
async function handleListTickets(input, dataDir = DATA_DIR$13) {
|
|
3359
3380
|
const results = await listAllTickets(dataDir, {
|
|
3360
3381
|
...input.slug !== void 0 ? { slug: input.slug } : {},
|
|
3361
3382
|
...input.status !== void 0 ? { status: input.status } : {},
|
|
@@ -3367,7 +3388,7 @@ async function handleListTickets(input, dataDir = DATA_DIR$12) {
|
|
|
3367
3388
|
text: JSON.stringify({ tickets: results }, null, 2)
|
|
3368
3389
|
}] };
|
|
3369
3390
|
}
|
|
3370
|
-
function registerListTickets(server, dataDir = DATA_DIR$
|
|
3391
|
+
function registerListTickets(server, dataDir = DATA_DIR$13) {
|
|
3371
3392
|
server.registerTool("list_tickets", {
|
|
3372
3393
|
description: `List support tickets. Filter by customer, status, priority, or assignee. Sorted by priority then date.
|
|
3373
3394
|
Returns: { tickets: Array<{ slug, ticket }> }`,
|
|
@@ -3397,8 +3418,8 @@ Returns: { tickets: Array<{ slug, ticket }> }`,
|
|
|
3397
3418
|
}
|
|
3398
3419
|
//#endregion
|
|
3399
3420
|
//#region src/mcp/tools/close-ticket.ts
|
|
3400
|
-
const DATA_DIR$
|
|
3401
|
-
async function handleCloseTicket(input, dataDir = DATA_DIR$
|
|
3421
|
+
const DATA_DIR$12 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3422
|
+
async function handleCloseTicket(input, dataDir = DATA_DIR$12) {
|
|
3402
3423
|
const ticket = (await readTickets(dataDir, input.slug)).find((t) => t.id === input.ticketId);
|
|
3403
3424
|
if (!ticket) return { content: [{
|
|
3404
3425
|
type: "text",
|
|
@@ -3425,7 +3446,7 @@ async function handleCloseTicket(input, dataDir = DATA_DIR$11) {
|
|
|
3425
3446
|
text: JSON.stringify({ ticket: updated }, null, 2)
|
|
3426
3447
|
}] };
|
|
3427
3448
|
}
|
|
3428
|
-
function registerCloseTicket(server, dataDir = DATA_DIR$
|
|
3449
|
+
function registerCloseTicket(server, dataDir = DATA_DIR$12) {
|
|
3429
3450
|
server.registerTool("close_ticket", {
|
|
3430
3451
|
description: `Close a support ticket. Optionally logs the resolution as an interaction.
|
|
3431
3452
|
Returns: { ticket } with status=closed`,
|
|
@@ -3442,8 +3463,8 @@ Returns: { ticket } with status=closed`,
|
|
|
3442
3463
|
}
|
|
3443
3464
|
//#endregion
|
|
3444
3465
|
//#region src/mcp/tools/send-nps-survey.ts
|
|
3445
|
-
const DATA_DIR$
|
|
3446
|
-
async function handleSendNpsSurvey(input, dataDir = DATA_DIR$
|
|
3466
|
+
const DATA_DIR$11 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3467
|
+
async function handleSendNpsSurvey(input, dataDir = DATA_DIR$11) {
|
|
3447
3468
|
const survey = getSurvey(dataDir, input.surveyId);
|
|
3448
3469
|
if (!survey) return { content: [{
|
|
3449
3470
|
type: "text",
|
|
@@ -3464,7 +3485,7 @@ async function handleSendNpsSurvey(input, dataDir = DATA_DIR$10) {
|
|
|
3464
3485
|
}, null, 2)
|
|
3465
3486
|
}] };
|
|
3466
3487
|
}
|
|
3467
|
-
function registerSendNpsSurvey(server, dataDir = DATA_DIR$
|
|
3488
|
+
function registerSendNpsSurvey(server, dataDir = DATA_DIR$11) {
|
|
3468
3489
|
server.registerTool("send_nps_survey", {
|
|
3469
3490
|
description: `Generate an NPS/CSAT survey email for a customer contact. Returns subject, HTML body, and a token-based response URL.
|
|
3470
3491
|
Does NOT send automatically — returns draft for review.
|
|
@@ -3484,8 +3505,8 @@ Returns: { token, subject, body, surveyUrl }`,
|
|
|
3484
3505
|
}
|
|
3485
3506
|
//#endregion
|
|
3486
3507
|
//#region src/mcp/tools/get-survey-results.ts
|
|
3487
|
-
const DATA_DIR$
|
|
3488
|
-
async function handleGetSurveyResults(input, dataDir = DATA_DIR$
|
|
3508
|
+
const DATA_DIR$10 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3509
|
+
async function handleGetSurveyResults(input, dataDir = DATA_DIR$10) {
|
|
3489
3510
|
const responses = loadSurveyResponses(dataDir, input.surveyId, input.slug);
|
|
3490
3511
|
const nps = calcNpsScore(responses);
|
|
3491
3512
|
const promoters = responses.filter((r) => r.score >= 9).length;
|
|
@@ -3511,7 +3532,7 @@ async function handleGetSurveyResults(input, dataDir = DATA_DIR$9) {
|
|
|
3511
3532
|
}, null, 2)
|
|
3512
3533
|
}] };
|
|
3513
3534
|
}
|
|
3514
|
-
function registerGetSurveyResults(server, dataDir = DATA_DIR$
|
|
3535
|
+
function registerGetSurveyResults(server, dataDir = DATA_DIR$10) {
|
|
3515
3536
|
server.registerTool("get_survey_results", {
|
|
3516
3537
|
description: `Get NPS/CSAT survey results with score breakdown. Calculates Net Promoter Score.
|
|
3517
3538
|
Returns: { npsScore, totalResponses, promoters, passives, detractors, responses[] }`,
|
|
@@ -3526,8 +3547,8 @@ Returns: { npsScore, totalResponses, promoters, passives, detractors, responses[
|
|
|
3526
3547
|
}
|
|
3527
3548
|
//#endregion
|
|
3528
3549
|
//#region src/mcp/tools/search-knowledge-base.ts
|
|
3529
|
-
const DATA_DIR$
|
|
3530
|
-
async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$
|
|
3550
|
+
const DATA_DIR$9 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3551
|
+
async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$9) {
|
|
3531
3552
|
const results = searchKbSimple(dataDir, input.query, { ...input.publicOnly ? { publicOnly: true } : {} });
|
|
3532
3553
|
const limited = (input.category ? results.filter((a) => a.category === input.category) : results).slice(0, input.limit ?? 10);
|
|
3533
3554
|
return { content: [{
|
|
@@ -3542,7 +3563,7 @@ async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$8) {
|
|
|
3542
3563
|
}, null, 2)
|
|
3543
3564
|
}] };
|
|
3544
3565
|
}
|
|
3545
|
-
function registerSearchKnowledgeBase(server, dataDir = DATA_DIR$
|
|
3566
|
+
function registerSearchKnowledgeBase(server, dataDir = DATA_DIR$9) {
|
|
3546
3567
|
server.registerTool("search_knowledge_base", {
|
|
3547
3568
|
description: `Search the knowledge base for articles. Text search on title, body, and tags.
|
|
3548
3569
|
Returns: { count, articles[] } with excerpts`,
|
|
@@ -3561,8 +3582,8 @@ Returns: { count, articles[] } with excerpts`,
|
|
|
3561
3582
|
}
|
|
3562
3583
|
//#endregion
|
|
3563
3584
|
//#region src/mcp/tools/create-kb-article.ts
|
|
3564
|
-
const DATA_DIR$
|
|
3565
|
-
async function handleCreateKbArticle(input, dataDir = DATA_DIR$
|
|
3585
|
+
const DATA_DIR$8 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3586
|
+
async function handleCreateKbArticle(input, dataDir = DATA_DIR$8) {
|
|
3566
3587
|
if (getKbArticle(dataDir, input.id)) return { content: [{
|
|
3567
3588
|
type: "text",
|
|
3568
3589
|
text: JSON.stringify({ error: `Article '${input.id}' already exists` })
|
|
@@ -3590,7 +3611,7 @@ async function handleCreateKbArticle(input, dataDir = DATA_DIR$7) {
|
|
|
3590
3611
|
}, null, 2)
|
|
3591
3612
|
}] };
|
|
3592
3613
|
}
|
|
3593
|
-
function registerCreateKbArticle(server, dataDir = DATA_DIR$
|
|
3614
|
+
function registerCreateKbArticle(server, dataDir = DATA_DIR$8) {
|
|
3594
3615
|
server.registerTool("create_kb_article", {
|
|
3595
3616
|
description: `Create a new knowledge base article. Articles are stored as Markdown files in .agentic/knowledge-base/.
|
|
3596
3617
|
Returns: { id, title, category, path }`,
|
|
@@ -3615,8 +3636,8 @@ Returns: { id, title, category, path }`,
|
|
|
3615
3636
|
}
|
|
3616
3637
|
//#endregion
|
|
3617
3638
|
//#region src/mcp/tools/backup-now.ts
|
|
3618
|
-
const DATA_DIR$
|
|
3619
|
-
async function handleBackupNow(input, dataDir = DATA_DIR$
|
|
3639
|
+
const DATA_DIR$7 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3640
|
+
async function handleBackupNow(input, dataDir = DATA_DIR$7) {
|
|
3620
3641
|
const zipPath = path.join(dataDir, `dxcrm-backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19)}.zip`);
|
|
3621
3642
|
const manifest = await runBackup(zipPath, dataDir, { ...input.remote ? { remote: input.remote } : {} }).catch(() => null);
|
|
3622
3643
|
if (!manifest) return { content: [{
|
|
@@ -3653,8 +3674,8 @@ function registerBackupNow(server) {
|
|
|
3653
3674
|
}
|
|
3654
3675
|
//#endregion
|
|
3655
3676
|
//#region src/mcp/tools/list-backups.ts
|
|
3656
|
-
const DATA_DIR$
|
|
3657
|
-
async function handleListBackups(input, dataDir = DATA_DIR$
|
|
3677
|
+
const DATA_DIR$6 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3678
|
+
async function handleListBackups(input, dataDir = DATA_DIR$6) {
|
|
3658
3679
|
const logEntries = readBackupLog(dataDir);
|
|
3659
3680
|
const fileEntries = listBackupsInDir(dataDir);
|
|
3660
3681
|
const entries = logEntries.length > 0 ? logEntries : fileEntries;
|
|
@@ -3688,8 +3709,8 @@ function registerListBackups(server) {
|
|
|
3688
3709
|
}
|
|
3689
3710
|
//#endregion
|
|
3690
3711
|
//#region src/mcp/tools/trigger-sync.ts
|
|
3691
|
-
const DATA_DIR$
|
|
3692
|
-
async function handleTriggerSync(input, dataDir = DATA_DIR$
|
|
3712
|
+
const DATA_DIR$5 = process.cwd();
|
|
3713
|
+
async function handleTriggerSync(input, dataDir = DATA_DIR$5) {
|
|
3693
3714
|
const auth = getGmailAuth();
|
|
3694
3715
|
if (!auth) return { content: [{
|
|
3695
3716
|
type: "text",
|
|
@@ -3724,7 +3745,7 @@ async function handleTriggerSync(input, dataDir = DATA_DIR$4) {
|
|
|
3724
3745
|
try {
|
|
3725
3746
|
const sources = JSON.parse(fs.readFileSync(sourcesPath, "utf-8"));
|
|
3726
3747
|
if (!sources.gmail?.enabled || !sources.gmail.query) continue;
|
|
3727
|
-
const { syncGmail } = await import("./gmail-sync-
|
|
3748
|
+
const { syncGmail } = await import("./gmail-sync-B4Iu3AQb.js");
|
|
3728
3749
|
const result = await syncGmail({
|
|
3729
3750
|
slug,
|
|
3730
3751
|
dataDir,
|
|
@@ -3783,8 +3804,8 @@ Returns: { success: boolean, synced: number, skipped: number, customers: [...],
|
|
|
3783
3804
|
}
|
|
3784
3805
|
//#endregion
|
|
3785
3806
|
//#region src/mcp/tools/get-audit-log.ts
|
|
3786
|
-
const DATA_DIR$
|
|
3787
|
-
async function handleGetAuditLog(input, dataDir = DATA_DIR$
|
|
3807
|
+
const DATA_DIR$4 = process.cwd();
|
|
3808
|
+
async function handleGetAuditLog(input, dataDir = DATA_DIR$4) {
|
|
3788
3809
|
const entries = readAuditLog(dataDir);
|
|
3789
3810
|
const filterOpts = { limit: input.limit ?? 50 };
|
|
3790
3811
|
if (input.slug !== void 0) filterOpts.slug = input.slug;
|
|
@@ -3826,8 +3847,8 @@ Returns: { total: number, returned: number, entries: [{timestamp, actor, tool, s
|
|
|
3826
3847
|
}
|
|
3827
3848
|
//#endregion
|
|
3828
3849
|
//#region src/mcp/tools/get-logs.ts
|
|
3829
|
-
const DATA_DIR$
|
|
3830
|
-
async function handleGetLogs(input, dataDir = DATA_DIR$
|
|
3850
|
+
const DATA_DIR$3 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3851
|
+
async function handleGetLogs(input, dataDir = DATA_DIR$3) {
|
|
3831
3852
|
const query = {
|
|
3832
3853
|
...input.level !== void 0 ? { level: input.level } : {},
|
|
3833
3854
|
...input.component !== void 0 ? { component: input.component } : {},
|
|
@@ -3888,6 +3909,40 @@ Returns (summary): { total, byLevel, byComponent, firstTs, lastTs, recentErrors
|
|
|
3888
3909
|
});
|
|
3889
3910
|
}
|
|
3890
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
|
|
3891
3946
|
//#region src/mcp/prompts.ts
|
|
3892
3947
|
/**
|
|
3893
3948
|
* CRM playbook prompts exposed via MCP `prompts/list` + `prompts/get`.
|
|
@@ -3982,7 +4037,7 @@ function registerResources(server, dataDir = DATA_DIR$1) {
|
|
|
3982
4037
|
description: "Newest-first interaction history for a customer",
|
|
3983
4038
|
mimeType: "text/markdown"
|
|
3984
4039
|
}, async (uri, variables) => {
|
|
3985
|
-
const { readInteractions } = await import("./interactions-writer-
|
|
4040
|
+
const { readInteractions } = await import("./interactions-writer-B2y-73lh.js");
|
|
3986
4041
|
const text = await readInteractions(dataDir, String(variables["slug"]));
|
|
3987
4042
|
return { contents: [{
|
|
3988
4043
|
uri: uri.href,
|
|
@@ -4144,6 +4199,7 @@ function createMcpServer() {
|
|
|
4144
4199
|
registerTriggerSync(server);
|
|
4145
4200
|
registerGetAuditLog(server);
|
|
4146
4201
|
registerGetLogs(server);
|
|
4202
|
+
registerGetDiagnostics(server);
|
|
4147
4203
|
registerCustomObjectTools(server);
|
|
4148
4204
|
registerPrompts(server);
|
|
4149
4205
|
registerResources(server);
|
|
@@ -4342,4 +4398,4 @@ else startStdio().catch((err) => {
|
|
|
4342
4398
|
//#endregion
|
|
4343
4399
|
export { startHttp, startStdio };
|
|
4344
4400
|
|
|
4345
|
-
//# sourceMappingURL=server-
|
|
4401
|
+
//# sourceMappingURL=server-BhNLrnAD.js.map
|