@datasynx/agentic-crm 1.5.0 → 1.7.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/dist/cli.js +70 -76
- package/dist/cli.js.map +1 -1
- package/dist/daemon/worker.js +40 -1
- package/dist/daemon/worker.js.map +1 -1
- package/dist/{imap-o6PRuBvm.js → imap-BRgNh3T3.js} +2 -2
- package/dist/{imap-o6PRuBvm.js.map → imap-BRgNh3T3.js.map} +1 -1
- package/dist/imap-DzeqMdZ3.js +2 -0
- package/dist/{index-FzDsNSSb.d.ts → index-BBAlKZg6.d.ts} +3 -3
- package/dist/{index-FzDsNSSb.d.ts.map → index-BBAlKZg6.d.ts.map} +1 -1
- package/dist/{index-B5_QnkG8.d.cts → index-DcDaz_cu.d.cts} +16 -16
- package/dist/index-DcDaz_cu.d.cts.map +1 -0
- package/dist/index.d.cts +16 -16
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/{knowledge-base-Bx2PKQR2.js → knowledge-base-Cc0niBFf.js} +2 -1
- package/dist/knowledge-base-Cc0niBFf.js.map +1 -0
- package/dist/{login-CYgla6-A.js → login-yt9OOQQk.js} +3 -2
- package/dist/{login-CYgla6-A.js.map → login-yt9OOQQk.js.map} +1 -1
- package/dist/mailbox-config-Bu-J1O4I.js +2 -0
- package/dist/mailbox-config-Dn2xTn9N.js +67 -0
- package/dist/mailbox-config-Dn2xTn9N.js.map +1 -0
- package/dist/mailbox-poll-B8dvFAXT.js +80 -0
- package/dist/mailbox-poll-B8dvFAXT.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 +289 -130
- 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 +289 -130
- package/dist/mcp.js.map +1 -1
- package/dist/{microsoft-DgbVlHdT.js → microsoft-dsC1fQQG.js} +2 -38
- package/dist/microsoft-dsC1fQQG.js.map +1 -0
- package/dist/{server-uqXUhF4H.js → server-BbInMUgp.js} +172 -130
- package/dist/server-BbInMUgp.js.map +1 -0
- package/dist/snapshots-B6aOhoXs.js +2 -0
- package/dist/snapshots-CQSOaIMs.js +161 -0
- package/dist/snapshots-CQSOaIMs.js.map +1 -0
- package/dist/{token-resolver-BRLOmRvF.js → token-resolver-D98qPOOf.js} +3 -2
- package/dist/{token-resolver-BRLOmRvF.js.map → token-resolver-D98qPOOf.js.map} +1 -1
- package/dist/token-store-B0h0USqe.js +43 -0
- package/dist/token-store-B0h0USqe.js.map +1 -0
- package/dist/token-store-CEmz8d-0.js +2 -0
- package/package.json +2 -2
- package/dist/index-B5_QnkG8.d.cts.map +0 -1
- package/dist/knowledge-base-Bx2PKQR2.js.map +0 -1
- package/dist/microsoft-DgbVlHdT.js.map +0 -1
- package/dist/server-uqXUhF4H.js.map +0 -1
|
@@ -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-
|
|
5
|
+
import { a as searchKbSimple, n as getKbArticle, o as writeKbArticle, r as getKbMetaForExport, s as CAPABILITIES_TEXT } from "./knowledge-base-Cc0niBFf.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";
|
|
@@ -26,6 +26,7 @@ import { a as loadCustomObjects, i as listRecords, n as defineCustomObject, t as
|
|
|
26
26
|
import { n as runDiagnostics } from "./doctor-BFeelnq8.js";
|
|
27
27
|
import { r as searchKnowledge } from "./lancedb-CuHKNsNZ.js";
|
|
28
28
|
import { t as buildDailyBriefing } from "./proactive-agent-B7u3Bj_l.js";
|
|
29
|
+
import { n as diffAgainstNow } from "./snapshots-CQSOaIMs.js";
|
|
29
30
|
import { a as protectedResourceMetadata, o as verifyBearer, r as isAuthRequired, s as wwwAuthenticateHeader } from "./auth-DDXZTwS0.js";
|
|
30
31
|
import { i as verifyGmailPubSubSignature, n as decodeGmailPubSubPayload, r as handleGmailPushEvent } from "./gmail-webhook-handler-BzOFbvgh.js";
|
|
31
32
|
import { n as registerUpdateDeal } from "./update-deal-DSzr_Aau.js";
|
|
@@ -255,7 +256,7 @@ function registerGetActiveSession(server) {
|
|
|
255
256
|
}
|
|
256
257
|
//#endregion
|
|
257
258
|
//#region src/mcp/tools/get-customer-context.ts
|
|
258
|
-
const DATA_DIR$
|
|
259
|
+
const DATA_DIR$53 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
259
260
|
function triggerOnQuerySync(dataDir, slug) {
|
|
260
261
|
const auth = getGmailAuth();
|
|
261
262
|
if (!auth) return;
|
|
@@ -276,7 +277,7 @@ function triggerOnQuerySync(dataDir, slug) {
|
|
|
276
277
|
}).then(() => updateSlugSyncState(dataDir, slug, { lastGmailSync: (/* @__PURE__ */ new Date()).toISOString() })).catch(() => {})).catch(() => {});
|
|
277
278
|
} catch {}
|
|
278
279
|
}
|
|
279
|
-
async function handleGetCustomerContext(input, dataDir = DATA_DIR$
|
|
280
|
+
async function handleGetCustomerContext(input, dataDir = DATA_DIR$53) {
|
|
280
281
|
const targetSlug = input.slug ?? getSession()?.customerSlug;
|
|
281
282
|
if (!targetSlug) return {
|
|
282
283
|
content: [{
|
|
@@ -328,8 +329,8 @@ Performance: <3 seconds. Token budget: <3000.`,
|
|
|
328
329
|
}
|
|
329
330
|
//#endregion
|
|
330
331
|
//#region src/mcp/tools/search-customer-knowledge.ts
|
|
331
|
-
const DATA_DIR$
|
|
332
|
-
async function handleSearchCustomerKnowledge(input, dataDir = DATA_DIR$
|
|
332
|
+
const DATA_DIR$52 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
333
|
+
async function handleSearchCustomerKnowledge(input, dataDir = DATA_DIR$52) {
|
|
333
334
|
const limit = input.limit ?? 5;
|
|
334
335
|
try {
|
|
335
336
|
const results = await searchKnowledge(dataDir, input.slug, input.query, limit);
|
|
@@ -377,14 +378,14 @@ If no results: returns empty array with a helpful sync suggestion.`,
|
|
|
377
378
|
}
|
|
378
379
|
//#endregion
|
|
379
380
|
//#region src/mcp/tools/list-customers.ts
|
|
380
|
-
const DATA_DIR$
|
|
381
|
+
const DATA_DIR$51 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
381
382
|
function extractLastInteractionDate(interactionsPath) {
|
|
382
383
|
if (!fs.existsSync(interactionsPath)) return void 0;
|
|
383
384
|
const content = fs.readFileSync(interactionsPath, "utf-8");
|
|
384
385
|
const match = /^## (\d{4}-\d{2}-\d{2})/m.exec(content);
|
|
385
386
|
return match ? match[1] : void 0;
|
|
386
387
|
}
|
|
387
|
-
async function handleListCustomers(input, dataDir = DATA_DIR$
|
|
388
|
+
async function handleListCustomers(input, dataDir = DATA_DIR$51) {
|
|
388
389
|
const customersDir = path.join(dataDir, "customers");
|
|
389
390
|
const customers = [];
|
|
390
391
|
if (!fs.existsSync(customersDir)) return { content: [{
|
|
@@ -445,8 +446,8 @@ Returns: Array of { slug, name, stage, lastInteraction?, dealValue? }`,
|
|
|
445
446
|
}
|
|
446
447
|
//#endregion
|
|
447
448
|
//#region src/mcp/tools/log-interaction.ts
|
|
448
|
-
const DATA_DIR$
|
|
449
|
-
async function handleLogInteraction(input, dataDir = DATA_DIR$
|
|
449
|
+
const DATA_DIR$50 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
450
|
+
async function handleLogInteraction(input, dataDir = DATA_DIR$50) {
|
|
450
451
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
451
452
|
const interactionDate = input.date ?? today;
|
|
452
453
|
const sourceRef = input.source ?? `agent://log/${Date.now()}`;
|
|
@@ -551,12 +552,12 @@ Returns: { success: boolean, path: string, entry: string }`,
|
|
|
551
552
|
}
|
|
552
553
|
//#endregion
|
|
553
554
|
//#region src/mcp/tools/export-customer.ts
|
|
554
|
-
const DATA_DIR$
|
|
555
|
+
const DATA_DIR$49 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
555
556
|
function countInteractions(content) {
|
|
556
557
|
const matches = content.match(/^## \d{4}-\d{2}-\d{2}/gm);
|
|
557
558
|
return matches ? matches.length : 0;
|
|
558
559
|
}
|
|
559
|
-
async function handleExportCustomer(input, dataDir = DATA_DIR$
|
|
560
|
+
async function handleExportCustomer(input, dataDir = DATA_DIR$49) {
|
|
560
561
|
enforceRbac(dataDir, "export_customer");
|
|
561
562
|
const customerDir = path.join(dataDir, "customers", input.slug);
|
|
562
563
|
if (!fs.existsSync(customerDir)) return {
|
|
@@ -669,8 +670,8 @@ Returns:
|
|
|
669
670
|
}
|
|
670
671
|
//#endregion
|
|
671
672
|
//#region src/mcp/tools/update-customer-facts.ts
|
|
672
|
-
const DATA_DIR$
|
|
673
|
-
async function handleUpdateCustomerFacts(input, dataDir = DATA_DIR$
|
|
673
|
+
const DATA_DIR$48 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
674
|
+
async function handleUpdateCustomerFacts(input, dataDir = DATA_DIR$48) {
|
|
674
675
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
675
676
|
try {
|
|
676
677
|
enforceRbac(dataDir, "update_customer_facts");
|
|
@@ -848,8 +849,8 @@ function scoreDealForToday(deal, todayDate) {
|
|
|
848
849
|
}
|
|
849
850
|
//#endregion
|
|
850
851
|
//#region src/mcp/tools/get-deal-health.ts
|
|
851
|
-
const DATA_DIR$
|
|
852
|
-
async function handleGetDealHealth(input, dataDir = DATA_DIR$
|
|
852
|
+
const DATA_DIR$47 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
853
|
+
async function handleGetDealHealth(input, dataDir = DATA_DIR$47) {
|
|
853
854
|
try {
|
|
854
855
|
const deals = await readPipeline(dataDir, input.slug);
|
|
855
856
|
const today = /* @__PURE__ */ new Date();
|
|
@@ -898,8 +899,8 @@ Returns: { slug, deals: [{ deal, stage, score, grade, signals, warnings }] }`,
|
|
|
898
899
|
}
|
|
899
900
|
//#endregion
|
|
900
901
|
//#region src/mcp/tools/get-pipeline-forecast.ts
|
|
901
|
-
const DATA_DIR$
|
|
902
|
-
async function handleGetPipelineForecast(input, dataDir = DATA_DIR$
|
|
902
|
+
const DATA_DIR$46 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
903
|
+
async function handleGetPipelineForecast(input, dataDir = DATA_DIR$46) {
|
|
903
904
|
try {
|
|
904
905
|
const slugs = listCustomerSlugs(dataDir).filter((d) => !input.filter || d.includes(input.filter));
|
|
905
906
|
const allDeals = [];
|
|
@@ -960,8 +961,8 @@ Returns: { deals: [...], totalWeightedValue: number, byStage: { stage: { count,
|
|
|
960
961
|
}
|
|
961
962
|
//#endregion
|
|
962
963
|
//#region src/mcp/tools/summarize-meeting.ts
|
|
963
|
-
const DATA_DIR$
|
|
964
|
-
async function handleSummarizeMeeting(input, dataDir = DATA_DIR$
|
|
964
|
+
const DATA_DIR$45 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
965
|
+
async function handleSummarizeMeeting(input, dataDir = DATA_DIR$45) {
|
|
965
966
|
try {
|
|
966
967
|
let summary = input.transcript.slice(0, 400);
|
|
967
968
|
let nextSteps = [];
|
|
@@ -1036,8 +1037,8 @@ Returns: { success, summary, nextSteps, sourceRef }`,
|
|
|
1036
1037
|
}
|
|
1037
1038
|
//#endregion
|
|
1038
1039
|
//#region src/mcp/tools/get-pipeline-stages.ts
|
|
1039
|
-
const DATA_DIR$
|
|
1040
|
-
async function handleGetPipelineStages(_input, dataDir = DATA_DIR$
|
|
1040
|
+
const DATA_DIR$44 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1041
|
+
async function handleGetPipelineStages(_input, dataDir = DATA_DIR$44) {
|
|
1041
1042
|
const stages = getPipelineStages(dataDir);
|
|
1042
1043
|
return { content: [{
|
|
1043
1044
|
type: "text",
|
|
@@ -1065,8 +1066,8 @@ async function searchAcrossCustomers(dataDir, query, limit = 5, excludeSlug) {
|
|
|
1065
1066
|
}
|
|
1066
1067
|
//#endregion
|
|
1067
1068
|
//#region src/mcp/tools/get-market-intelligence.ts
|
|
1068
|
-
const DATA_DIR$
|
|
1069
|
-
async function handleGetMarketIntelligence(input, dataDir = DATA_DIR$
|
|
1069
|
+
const DATA_DIR$43 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1070
|
+
async function handleGetMarketIntelligence(input, dataDir = DATA_DIR$43) {
|
|
1070
1071
|
const excludeSlug = input.excludeCurrentCustomer ? input.slug : void 0;
|
|
1071
1072
|
const all = listCustomerSlugs(dataDir);
|
|
1072
1073
|
const totalCustomersSearched = excludeSlug ? all.filter((s) => s !== excludeSlug).length : all.length;
|
|
@@ -1097,7 +1098,7 @@ function registerGetMarketIntelligence(server) {
|
|
|
1097
1098
|
}
|
|
1098
1099
|
//#endregion
|
|
1099
1100
|
//#region src/mcp/tools/get-relationship-graph.ts
|
|
1100
|
-
const DATA_DIR$
|
|
1101
|
+
const DATA_DIR$42 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1101
1102
|
function summarizeNode(n) {
|
|
1102
1103
|
return {
|
|
1103
1104
|
id: n.id,
|
|
@@ -1105,7 +1106,7 @@ function summarizeNode(n) {
|
|
|
1105
1106
|
email: n.properties["email"]
|
|
1106
1107
|
};
|
|
1107
1108
|
}
|
|
1108
|
-
async function handleGetRelationshipGraph(input, dataDir = DATA_DIR$
|
|
1109
|
+
async function handleGetRelationshipGraph(input, dataDir = DATA_DIR$42) {
|
|
1109
1110
|
try {
|
|
1110
1111
|
const graph = readGraph(dataDir, input.slug);
|
|
1111
1112
|
const stakeholders = getStakeholders(graph);
|
|
@@ -1173,9 +1174,9 @@ Returns: {
|
|
|
1173
1174
|
}
|
|
1174
1175
|
//#endregion
|
|
1175
1176
|
//#region src/mcp/tools/get-relationship-health.ts
|
|
1176
|
-
const DATA_DIR$
|
|
1177
|
+
const DATA_DIR$41 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1177
1178
|
const MAX_HEALTH_AGE_MS = 3600 * 1e3;
|
|
1178
|
-
async function handleGetRelationshipHealth(input, dataDir = DATA_DIR$
|
|
1179
|
+
async function handleGetRelationshipHealth(input, dataDir = DATA_DIR$41) {
|
|
1179
1180
|
try {
|
|
1180
1181
|
let health = readHealth(dataDir, input.slug);
|
|
1181
1182
|
if (health === null || Date.now() - new Date(health.updatedAt).getTime() > MAX_HEALTH_AGE_MS) {
|
|
@@ -1844,8 +1845,8 @@ async function runDealAgent(config, dataDir, llmFn = callLlm) {
|
|
|
1844
1845
|
}
|
|
1845
1846
|
//#endregion
|
|
1846
1847
|
//#region src/mcp/tools/run-deal-agent.ts
|
|
1847
|
-
const DATA_DIR$
|
|
1848
|
-
async function handleRunDealAgent(input, dataDir = DATA_DIR$
|
|
1848
|
+
const DATA_DIR$40 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1849
|
+
async function handleRunDealAgent(input, dataDir = DATA_DIR$40) {
|
|
1849
1850
|
try {
|
|
1850
1851
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
1851
1852
|
const result = await runDealAgent({
|
|
@@ -1912,8 +1913,8 @@ Returns: { assessment, riskLevel, plan[], actionsQueued[], actionsExecuted[], tr
|
|
|
1912
1913
|
}
|
|
1913
1914
|
//#endregion
|
|
1914
1915
|
//#region src/mcp/tools/approve-agent-action.ts
|
|
1915
|
-
const DATA_DIR$
|
|
1916
|
-
async function handleApproveAgentAction(input, dataDir = DATA_DIR$
|
|
1916
|
+
const DATA_DIR$39 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1917
|
+
async function handleApproveAgentAction(input, dataDir = DATA_DIR$39) {
|
|
1917
1918
|
try {
|
|
1918
1919
|
const queue = readAgentQueue(dataDir, input.slug);
|
|
1919
1920
|
const idx = queue.pendingActions.findIndex((a) => a.actionId === input.actionId);
|
|
@@ -1990,8 +1991,8 @@ Returns: { success, actionId, status }`,
|
|
|
1990
1991
|
}
|
|
1991
1992
|
//#endregion
|
|
1992
1993
|
//#region src/mcp/tools/simulate-revenue.ts
|
|
1993
|
-
const DATA_DIR$
|
|
1994
|
-
async function handleSimulateRevenue(input, dataDir = DATA_DIR$
|
|
1994
|
+
const DATA_DIR$38 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1995
|
+
async function handleSimulateRevenue(input, dataDir = DATA_DIR$38) {
|
|
1995
1996
|
try {
|
|
1996
1997
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
1997
1998
|
const horizon = input.horizon ?? "quarter";
|
|
@@ -2049,8 +2050,8 @@ Returns: { forecast: { p10, p50, p90, expected, stdDev, atRiskRevenue, byCloseMo
|
|
|
2049
2050
|
}
|
|
2050
2051
|
//#endregion
|
|
2051
2052
|
//#region src/mcp/tools/get-playbook.ts
|
|
2052
|
-
const DATA_DIR$
|
|
2053
|
-
async function handleGetPlaybook(input, dataDir = DATA_DIR$
|
|
2053
|
+
const DATA_DIR$37 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2054
|
+
async function handleGetPlaybook(input, dataDir = DATA_DIR$37) {
|
|
2054
2055
|
try {
|
|
2055
2056
|
const playbooks = listPlaybooks(dataDir, input.slug);
|
|
2056
2057
|
if (!(input.stage !== void 0 || input.value !== void 0 || input.healthScore !== void 0)) return { content: [{
|
|
@@ -2135,12 +2136,12 @@ Returns: { matches: [{ name, score, trigger, successRate, usedCount, content }],
|
|
|
2135
2136
|
...healthScore !== void 0 ? { healthScore } : {},
|
|
2136
2137
|
...daysSinceContact !== void 0 ? { daysSinceContact } : {},
|
|
2137
2138
|
...championPresent !== void 0 ? { championPresent } : {}
|
|
2138
|
-
}, DATA_DIR$
|
|
2139
|
+
}, DATA_DIR$37));
|
|
2139
2140
|
}
|
|
2140
2141
|
//#endregion
|
|
2141
2142
|
//#region src/mcp/tools/create-playbook.ts
|
|
2142
|
-
const DATA_DIR$
|
|
2143
|
-
async function handleCreatePlaybook(input, dataDir = DATA_DIR$
|
|
2143
|
+
const DATA_DIR$36 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2144
|
+
async function handleCreatePlaybook(input, dataDir = DATA_DIR$36) {
|
|
2144
2145
|
try {
|
|
2145
2146
|
const name = toKebabCase(input.name);
|
|
2146
2147
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -2213,12 +2214,12 @@ Returns: { success: true, playbook: { name, trigger, successRate, path } }`,
|
|
|
2213
2214
|
trigger,
|
|
2214
2215
|
content,
|
|
2215
2216
|
...successRate !== void 0 ? { successRate } : {}
|
|
2216
|
-
}, DATA_DIR$
|
|
2217
|
+
}, DATA_DIR$36));
|
|
2217
2218
|
}
|
|
2218
2219
|
//#endregion
|
|
2219
2220
|
//#region src/mcp/tools/list-playbooks.ts
|
|
2220
|
-
const DATA_DIR$
|
|
2221
|
-
async function handleListPlaybooks(input, dataDir = DATA_DIR$
|
|
2221
|
+
const DATA_DIR$35 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2222
|
+
async function handleListPlaybooks(input, dataDir = DATA_DIR$35) {
|
|
2222
2223
|
try {
|
|
2223
2224
|
const playbooks = listPlaybooks(dataDir, input.slug);
|
|
2224
2225
|
return { content: [{
|
|
@@ -2257,12 +2258,12 @@ Args:
|
|
|
2257
2258
|
|
|
2258
2259
|
Returns: { playbooks: [{ name, trigger, successRate, usedCount, lastUpdated }], count, slug }`,
|
|
2259
2260
|
inputSchema: z.object({ slug: z.string().describe("Customer ID") })
|
|
2260
|
-
}, async ({ slug }) => handleListPlaybooks({ slug }, DATA_DIR$
|
|
2261
|
+
}, async ({ slug }) => handleListPlaybooks({ slug }, DATA_DIR$35));
|
|
2261
2262
|
}
|
|
2262
2263
|
//#endregion
|
|
2263
2264
|
//#region src/mcp/tools/distill-playbook.ts
|
|
2264
|
-
const DATA_DIR$
|
|
2265
|
-
async function handleDistillPlaybook(input, dataDir = DATA_DIR$
|
|
2265
|
+
const DATA_DIR$34 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2266
|
+
async function handleDistillPlaybook(input, dataDir = DATA_DIR$34, llmFn = callLlm) {
|
|
2266
2267
|
try {
|
|
2267
2268
|
const result = await distillPlaybook(dataDir, input.slug, input.dealName, input.outcome, llmFn);
|
|
2268
2269
|
if (!result.ok) {
|
|
@@ -2321,12 +2322,12 @@ Returns: { success: true, playbook: { name, trigger, successRate, path }, reason
|
|
|
2321
2322
|
slug,
|
|
2322
2323
|
dealName,
|
|
2323
2324
|
outcome
|
|
2324
|
-
}, DATA_DIR$
|
|
2325
|
+
}, DATA_DIR$34));
|
|
2325
2326
|
}
|
|
2326
2327
|
//#endregion
|
|
2327
2328
|
//#region src/mcp/tools/pursue-goal.ts
|
|
2328
|
-
const DATA_DIR$
|
|
2329
|
-
async function handlePursueGoal(input, dataDir = DATA_DIR$
|
|
2329
|
+
const DATA_DIR$33 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2330
|
+
async function handlePursueGoal(input, dataDir = DATA_DIR$33, options = {}) {
|
|
2330
2331
|
try {
|
|
2331
2332
|
enforceRbac(dataDir, "pursue_goal");
|
|
2332
2333
|
const goal = await pursueGoal(dataDir, {
|
|
@@ -2389,12 +2390,12 @@ Returns: { goalId, description, target, deadline, decomposition: { analysis, cur
|
|
|
2389
2390
|
goal,
|
|
2390
2391
|
deadline,
|
|
2391
2392
|
...context !== void 0 ? { context } : {}
|
|
2392
|
-
}, DATA_DIR$
|
|
2393
|
+
}, DATA_DIR$33));
|
|
2393
2394
|
}
|
|
2394
2395
|
//#endregion
|
|
2395
2396
|
//#region src/mcp/tools/get-goal-status.ts
|
|
2396
|
-
const DATA_DIR$
|
|
2397
|
-
async function handleGetGoalStatus(input, dataDir = DATA_DIR$
|
|
2397
|
+
const DATA_DIR$32 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2398
|
+
async function handleGetGoalStatus(input, dataDir = DATA_DIR$32) {
|
|
2398
2399
|
try {
|
|
2399
2400
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2400
2401
|
const allGoals = input.goalId ? readGoals(dataDir).filter((g) => g.id === input.goalId) : getActiveGoals(dataDir);
|
|
@@ -2453,17 +2454,17 @@ Args:
|
|
|
2453
2454
|
|
|
2454
2455
|
Returns: { goals: [{ id, description, target, progress, status, deadline, daysRemaining, subGoals }], activeCount, completedCount }`,
|
|
2455
2456
|
inputSchema: z.object({ goalId: z.string().optional().describe("Specific goal ID (omit for all active goals)") })
|
|
2456
|
-
}, async ({ goalId }) => handleGetGoalStatus({ ...goalId !== void 0 ? { goalId } : {} }, DATA_DIR$
|
|
2457
|
+
}, async ({ goalId }) => handleGetGoalStatus({ ...goalId !== void 0 ? { goalId } : {} }, DATA_DIR$32));
|
|
2457
2458
|
}
|
|
2458
2459
|
//#endregion
|
|
2459
2460
|
//#region src/mcp/tools/register-push-subscription.ts
|
|
2460
|
-
const DATA_DIR$
|
|
2461
|
+
const DATA_DIR$31 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2461
2462
|
const VALID_PROVIDERS = [
|
|
2462
2463
|
"gmail",
|
|
2463
2464
|
"microsoft-graph",
|
|
2464
2465
|
"slack"
|
|
2465
2466
|
];
|
|
2466
|
-
async function handleRegisterPushSubscription(input, dataDir = DATA_DIR$
|
|
2467
|
+
async function handleRegisterPushSubscription(input, dataDir = DATA_DIR$31) {
|
|
2467
2468
|
try {
|
|
2468
2469
|
if (!VALID_PROVIDERS.includes(input.provider)) return { content: [{
|
|
2469
2470
|
type: "text",
|
|
@@ -2549,12 +2550,12 @@ Returns: { subscriptionId, provider, slug, status, expiresAt, createdAt, warning
|
|
|
2549
2550
|
...microsoftResource !== void 0 ? { microsoftResource } : {},
|
|
2550
2551
|
...slackTeamId !== void 0 ? { slackTeamId } : {},
|
|
2551
2552
|
...slackChannelId !== void 0 ? { slackChannelId } : {}
|
|
2552
|
-
}, DATA_DIR$
|
|
2553
|
+
}, DATA_DIR$31));
|
|
2553
2554
|
}
|
|
2554
2555
|
//#endregion
|
|
2555
2556
|
//#region src/mcp/tools/get-push-status.ts
|
|
2556
|
-
const DATA_DIR$
|
|
2557
|
-
async function handleGetPushStatus(input, dataDir = DATA_DIR$
|
|
2557
|
+
const DATA_DIR$30 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2558
|
+
async function handleGetPushStatus(input, dataDir = DATA_DIR$30) {
|
|
2558
2559
|
try {
|
|
2559
2560
|
let subs = await readSubscriptions(dataDir);
|
|
2560
2561
|
if (input.slug) subs = subs.filter((s) => s.slug === input.slug);
|
|
@@ -2626,7 +2627,7 @@ Returns: { subscriptions: [{ id, provider, slug, status, expiresAt, expiresInHou
|
|
|
2626
2627
|
}, async ({ slug, provider }) => handleGetPushStatus({
|
|
2627
2628
|
...slug !== void 0 ? { slug } : {},
|
|
2628
2629
|
...provider !== void 0 ? { provider } : {}
|
|
2629
|
-
}, DATA_DIR$
|
|
2630
|
+
}, DATA_DIR$30));
|
|
2630
2631
|
}
|
|
2631
2632
|
//#endregion
|
|
2632
2633
|
//#region src/core/org-intelligence.ts
|
|
@@ -2692,8 +2693,8 @@ function deriveRecommendation(people, missingRoles) {
|
|
|
2692
2693
|
}
|
|
2693
2694
|
//#endregion
|
|
2694
2695
|
//#region src/mcp/tools/get-org-intelligence.ts
|
|
2695
|
-
const DATA_DIR$
|
|
2696
|
-
async function handleGetOrgIntelligence(input, dataDir = DATA_DIR$
|
|
2696
|
+
const DATA_DIR$29 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2697
|
+
async function handleGetOrgIntelligence(input, dataDir = DATA_DIR$29) {
|
|
2697
2698
|
try {
|
|
2698
2699
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2699
2700
|
const map = buildStakeholderMap(dataDir, input.slug, today, input.dealName);
|
|
@@ -2826,8 +2827,8 @@ function buildExecutiveSummary(slug, dealName, stakeholders, overallHealth, sim,
|
|
|
2826
2827
|
}
|
|
2827
2828
|
//#endregion
|
|
2828
2829
|
//#region src/mcp/tools/open-deal-room.ts
|
|
2829
|
-
const DATA_DIR$
|
|
2830
|
-
async function handleOpenDealRoom(input, dataDir = DATA_DIR$
|
|
2830
|
+
const DATA_DIR$28 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2831
|
+
async function handleOpenDealRoom(input, dataDir = DATA_DIR$28) {
|
|
2831
2832
|
try {
|
|
2832
2833
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2833
2834
|
const brief = await buildDealRoom(dataDir, input.slug, input.dealName, today);
|
|
@@ -2862,8 +2863,8 @@ Returns: { slug, dealName, generatedAt, stakeholders, relationshipHealth, dealHe
|
|
|
2862
2863
|
}
|
|
2863
2864
|
//#endregion
|
|
2864
2865
|
//#region src/mcp/tools/get-proactive-briefing.ts
|
|
2865
|
-
const DATA_DIR$
|
|
2866
|
-
async function handleGetProactiveBriefing(input, dataDir = DATA_DIR$
|
|
2866
|
+
const DATA_DIR$27 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2867
|
+
async function handleGetProactiveBriefing(input, dataDir = DATA_DIR$27) {
|
|
2867
2868
|
try {
|
|
2868
2869
|
const briefing = await buildDailyBriefing(dataDir, input.date ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10));
|
|
2869
2870
|
return { content: [{
|
|
@@ -2891,15 +2892,15 @@ Returns: { date, generatedAt, urgent: string[], opportunities: string[], forecas
|
|
|
2891
2892
|
}
|
|
2892
2893
|
//#endregion
|
|
2893
2894
|
//#region src/mcp/tools/list-email-templates.ts
|
|
2894
|
-
const DATA_DIR$
|
|
2895
|
-
async function handleListEmailTemplates(input, dataDir = DATA_DIR$
|
|
2895
|
+
const DATA_DIR$26 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2896
|
+
async function handleListEmailTemplates(input, dataDir = DATA_DIR$26) {
|
|
2896
2897
|
const summary = listTemplates(dataDir, input.category ? { category: input.category } : {}).map(({ body: _body, ...meta }) => meta);
|
|
2897
2898
|
return { content: [{
|
|
2898
2899
|
type: "text",
|
|
2899
2900
|
text: JSON.stringify(summary, null, 2)
|
|
2900
2901
|
}] };
|
|
2901
2902
|
}
|
|
2902
|
-
function registerListEmailTemplates(server, dataDir = DATA_DIR$
|
|
2903
|
+
function registerListEmailTemplates(server, dataDir = DATA_DIR$26) {
|
|
2903
2904
|
server.registerTool("list_email_templates", {
|
|
2904
2905
|
description: "List available email templates. Optionally filter by category (e.g. 'outreach', 'followup', 'support').",
|
|
2905
2906
|
inputSchema: z.object({ category: z.string().optional().describe("Filter by category") })
|
|
@@ -2907,8 +2908,8 @@ function registerListEmailTemplates(server, dataDir = DATA_DIR$25) {
|
|
|
2907
2908
|
}
|
|
2908
2909
|
//#endregion
|
|
2909
2910
|
//#region src/mcp/tools/get-email-template.ts
|
|
2910
|
-
const DATA_DIR$
|
|
2911
|
-
async function handleGetEmailTemplate(input, dataDir = DATA_DIR$
|
|
2911
|
+
const DATA_DIR$25 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2912
|
+
async function handleGetEmailTemplate(input, dataDir = DATA_DIR$25) {
|
|
2912
2913
|
const tmpl = getTemplate(dataDir, input.id);
|
|
2913
2914
|
if (!tmpl) return { content: [{
|
|
2914
2915
|
type: "text",
|
|
@@ -2924,7 +2925,7 @@ async function handleGetEmailTemplate(input, dataDir = DATA_DIR$24) {
|
|
|
2924
2925
|
}, null, 2)
|
|
2925
2926
|
}] };
|
|
2926
2927
|
}
|
|
2927
|
-
function registerGetEmailTemplate(server, dataDir = DATA_DIR$
|
|
2928
|
+
function registerGetEmailTemplate(server, dataDir = DATA_DIR$25) {
|
|
2928
2929
|
server.registerTool("get_email_template", {
|
|
2929
2930
|
description: "Get a specific email template by ID, including its body and detected variables.",
|
|
2930
2931
|
inputSchema: z.object({ id: z.string().describe("Template ID (e.g. 'enterprise-intro')") })
|
|
@@ -2932,8 +2933,8 @@ function registerGetEmailTemplate(server, dataDir = DATA_DIR$24) {
|
|
|
2932
2933
|
}
|
|
2933
2934
|
//#endregion
|
|
2934
2935
|
//#region src/mcp/tools/draft-email.ts
|
|
2935
|
-
const DATA_DIR$
|
|
2936
|
-
async function handleDraftEmail(input, dataDir = DATA_DIR$
|
|
2936
|
+
const DATA_DIR$24 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2937
|
+
async function handleDraftEmail(input, dataDir = DATA_DIR$24) {
|
|
2937
2938
|
const tmpl = getTemplate(dataDir, input.templateId);
|
|
2938
2939
|
if (!tmpl) return { content: [{
|
|
2939
2940
|
type: "text",
|
|
@@ -2977,7 +2978,7 @@ async function handleDraftEmail(input, dataDir = DATA_DIR$23) {
|
|
|
2977
2978
|
}, null, 2)
|
|
2978
2979
|
}] };
|
|
2979
2980
|
}
|
|
2980
|
-
function registerDraftEmail(server, dataDir = DATA_DIR$
|
|
2981
|
+
function registerDraftEmail(server, dataDir = DATA_DIR$24) {
|
|
2981
2982
|
server.registerTool("draft_email", {
|
|
2982
2983
|
description: `Draft a personalized email for a customer using a stored template.
|
|
2983
2984
|
Variables are auto-filled from the customer's main_facts.md. Override any variable manually.
|
|
@@ -2999,8 +3000,8 @@ Returns: { subject, body, to, tone, polished, resolvedVariables } — does NOT s
|
|
|
2999
3000
|
}
|
|
3000
3001
|
//#endregion
|
|
3001
3002
|
//#region src/mcp/tools/enroll-in-sequence.ts
|
|
3002
|
-
const DATA_DIR$
|
|
3003
|
-
async function handleEnrollInSequence(input, dataDir = DATA_DIR$
|
|
3003
|
+
const DATA_DIR$23 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3004
|
+
async function handleEnrollInSequence(input, dataDir = DATA_DIR$23) {
|
|
3004
3005
|
const sequence = getSequence(dataDir, input.sequenceId);
|
|
3005
3006
|
if (!sequence) return { content: [{
|
|
3006
3007
|
type: "text",
|
|
@@ -3032,7 +3033,7 @@ async function handleEnrollInSequence(input, dataDir = DATA_DIR$22) {
|
|
|
3032
3033
|
})
|
|
3033
3034
|
}] };
|
|
3034
3035
|
}
|
|
3035
|
-
function registerEnrollInSequence(server, dataDir = DATA_DIR$
|
|
3036
|
+
function registerEnrollInSequence(server, dataDir = DATA_DIR$23) {
|
|
3036
3037
|
server.registerTool("enroll_in_sequence", {
|
|
3037
3038
|
description: `Enroll a contact in an email sequence. Validates that the sequence and its first template exist.
|
|
3038
3039
|
Returns: { enrollmentId, sequenceName, totalSteps }`,
|
|
@@ -3049,8 +3050,8 @@ Returns: { enrollmentId, sequenceName, totalSteps }`,
|
|
|
3049
3050
|
}
|
|
3050
3051
|
//#endregion
|
|
3051
3052
|
//#region src/mcp/tools/list-sequence-enrollments.ts
|
|
3052
|
-
const DATA_DIR$
|
|
3053
|
-
async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$
|
|
3053
|
+
const DATA_DIR$22 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3054
|
+
async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$22) {
|
|
3054
3055
|
let enrollments = readEnrollments(dataDir);
|
|
3055
3056
|
if (input.slug !== void 0) enrollments = enrollments.filter((e) => e.slug === input.slug);
|
|
3056
3057
|
if (input.status !== void 0) enrollments = enrollments.filter((e) => e.status === input.status);
|
|
@@ -3059,7 +3060,7 @@ async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$21) {
|
|
|
3059
3060
|
text: JSON.stringify({ enrollments }, null, 2)
|
|
3060
3061
|
}] };
|
|
3061
3062
|
}
|
|
3062
|
-
function registerListSequenceEnrollments(server, dataDir = DATA_DIR$
|
|
3063
|
+
function registerListSequenceEnrollments(server, dataDir = DATA_DIR$22) {
|
|
3063
3064
|
server.registerTool("list_sequence_enrollments", {
|
|
3064
3065
|
description: `List email sequence enrollments. Filter by customer slug or status.
|
|
3065
3066
|
Returns: { enrollments: SequenceEnrollment[] }`,
|
|
@@ -3078,8 +3079,8 @@ Returns: { enrollments: SequenceEnrollment[] }`,
|
|
|
3078
3079
|
}
|
|
3079
3080
|
//#endregion
|
|
3080
3081
|
//#region src/mcp/tools/unenroll-from-sequence.ts
|
|
3081
|
-
const DATA_DIR$
|
|
3082
|
-
async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$
|
|
3082
|
+
const DATA_DIR$21 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3083
|
+
async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$21) {
|
|
3083
3084
|
if (!await updateEnrollment(dataDir, input.enrollmentId, { status: "paused" })) return { content: [{
|
|
3084
3085
|
type: "text",
|
|
3085
3086
|
text: JSON.stringify({
|
|
@@ -3092,7 +3093,7 @@ async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$20) {
|
|
|
3092
3093
|
text: JSON.stringify({ success: true })
|
|
3093
3094
|
}] };
|
|
3094
3095
|
}
|
|
3095
|
-
function registerUnenrollFromSequence(server, dataDir = DATA_DIR$
|
|
3096
|
+
function registerUnenrollFromSequence(server, dataDir = DATA_DIR$21) {
|
|
3096
3097
|
server.registerTool("unenroll_from_sequence", {
|
|
3097
3098
|
description: `Unenroll (pause) a contact from an email sequence. Sets status to "paused" (soft delete).
|
|
3098
3099
|
Returns: { success: boolean }`,
|
|
@@ -3101,8 +3102,8 @@ Returns: { success: boolean }`,
|
|
|
3101
3102
|
}
|
|
3102
3103
|
//#endregion
|
|
3103
3104
|
//#region src/mcp/tools/list-sequences.ts
|
|
3104
|
-
const DATA_DIR$
|
|
3105
|
-
async function handleListSequences(_input, dataDir = DATA_DIR$
|
|
3105
|
+
const DATA_DIR$20 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3106
|
+
async function handleListSequences(_input, dataDir = DATA_DIR$20) {
|
|
3106
3107
|
const sequences = listSequences(dataDir);
|
|
3107
3108
|
const enrollments = readEnrollments(dataDir);
|
|
3108
3109
|
const result = sequences.map((seq) => ({
|
|
@@ -3116,7 +3117,7 @@ async function handleListSequences(_input, dataDir = DATA_DIR$19) {
|
|
|
3116
3117
|
text: JSON.stringify({ sequences: result }, null, 2)
|
|
3117
3118
|
}] };
|
|
3118
3119
|
}
|
|
3119
|
-
function registerListSequences(server, dataDir = DATA_DIR$
|
|
3120
|
+
function registerListSequences(server, dataDir = DATA_DIR$20) {
|
|
3120
3121
|
server.registerTool("list_sequences", {
|
|
3121
3122
|
description: `List all email sequences with step count and enrollment count.
|
|
3122
3123
|
Returns: { sequences: Array<{ id, name, stepCount, enrollmentCount }> }`,
|
|
@@ -3125,8 +3126,8 @@ Returns: { sequences: Array<{ id, name, stepCount, enrollmentCount }> }`,
|
|
|
3125
3126
|
}
|
|
3126
3127
|
//#endregion
|
|
3127
3128
|
//#region src/mcp/tools/generate-quote.ts
|
|
3128
|
-
const DATA_DIR$
|
|
3129
|
-
async function handleGenerateQuote(input, dataDir = DATA_DIR$
|
|
3129
|
+
const DATA_DIR$19 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3130
|
+
async function handleGenerateQuote(input, dataDir = DATA_DIR$19) {
|
|
3130
3131
|
try {
|
|
3131
3132
|
const quote = await generateQuote(dataDir, input);
|
|
3132
3133
|
return { content: [{
|
|
@@ -3150,7 +3151,7 @@ async function handleGenerateQuote(input, dataDir = DATA_DIR$18) {
|
|
|
3150
3151
|
}] };
|
|
3151
3152
|
}
|
|
3152
3153
|
}
|
|
3153
|
-
function registerGenerateQuote(server, dataDir = DATA_DIR$
|
|
3154
|
+
function registerGenerateQuote(server, dataDir = DATA_DIR$19) {
|
|
3154
3155
|
server.registerTool("generate_quote", {
|
|
3155
3156
|
description: `Generate a professional HTML quote/offer for a customer deal.
|
|
3156
3157
|
Calculates subtotal, VAT, and total. Saves JSON + HTML to .agentic/quotes/.
|
|
@@ -3178,8 +3179,8 @@ Returns: { quoteNumber, htmlPath, total, currency, validUntil }`,
|
|
|
3178
3179
|
}
|
|
3179
3180
|
//#endregion
|
|
3180
3181
|
//#region src/mcp/tools/get-quote-status.ts
|
|
3181
|
-
const DATA_DIR$
|
|
3182
|
-
async function handleGetQuoteStatus(input, dataDir = DATA_DIR$
|
|
3182
|
+
const DATA_DIR$18 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3183
|
+
async function handleGetQuoteStatus(input, dataDir = DATA_DIR$18) {
|
|
3183
3184
|
if (input.quoteNumber) {
|
|
3184
3185
|
const quote = readQuote(dataDir, input.quoteNumber);
|
|
3185
3186
|
if (!quote) return { content: [{
|
|
@@ -3197,7 +3198,7 @@ async function handleGetQuoteStatus(input, dataDir = DATA_DIR$17) {
|
|
|
3197
3198
|
text: JSON.stringify({ quotes }, null, 2)
|
|
3198
3199
|
}] };
|
|
3199
3200
|
}
|
|
3200
|
-
function registerGetQuoteStatus(server, dataDir = DATA_DIR$
|
|
3201
|
+
function registerGetQuoteStatus(server, dataDir = DATA_DIR$18) {
|
|
3201
3202
|
server.registerTool("get_quote_status", {
|
|
3202
3203
|
description: `Get quote status and details. Filter by quoteNumber (single quote) or slug (all quotes for a customer).
|
|
3203
3204
|
Returns quote with status: draft | sent | viewed | accepted | declined`,
|
|
@@ -3212,7 +3213,7 @@ Returns quote with status: draft | sent | viewed | accepted | declined`,
|
|
|
3212
3213
|
}
|
|
3213
3214
|
//#endregion
|
|
3214
3215
|
//#region src/mcp/tools/get-booking-link.ts
|
|
3215
|
-
const DATA_DIR$
|
|
3216
|
+
const DATA_DIR$17 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3216
3217
|
function loadCalendlyConfig(dataDir) {
|
|
3217
3218
|
const p = path.join(dataDir, ".agentic", "integrations", "calendly.yaml");
|
|
3218
3219
|
if (!fs.existsSync(p)) return {};
|
|
@@ -3235,7 +3236,7 @@ function readCustomerFacts(dataDir, slug) {
|
|
|
3235
3236
|
...email ? { email } : {}
|
|
3236
3237
|
};
|
|
3237
3238
|
}
|
|
3238
|
-
async function handleGetBookingLink(input, dataDir = DATA_DIR$
|
|
3239
|
+
async function handleGetBookingLink(input, dataDir = DATA_DIR$17) {
|
|
3239
3240
|
const config = loadCalendlyConfig(dataDir);
|
|
3240
3241
|
const apiKey = config.apiKey ?? process.env["CALENDLY_API_KEY"] ?? "";
|
|
3241
3242
|
if (!apiKey) return { content: [{
|
|
@@ -3263,7 +3264,7 @@ async function handleGetBookingLink(input, dataDir = DATA_DIR$16) {
|
|
|
3263
3264
|
}] };
|
|
3264
3265
|
}
|
|
3265
3266
|
}
|
|
3266
|
-
function registerGetBookingLink(server, dataDir = DATA_DIR$
|
|
3267
|
+
function registerGetBookingLink(server, dataDir = DATA_DIR$17) {
|
|
3267
3268
|
server.registerTool("get_booking_link", {
|
|
3268
3269
|
description: `Get a Calendly booking link for a customer. Optionally pre-fills the customer's name/email.
|
|
3269
3270
|
Requires CALENDLY_API_KEY env var or .agentic/integrations/calendly.yaml config.
|
|
@@ -3281,8 +3282,8 @@ Returns: { bookingUrl, eventType, duration }`,
|
|
|
3281
3282
|
}
|
|
3282
3283
|
//#endregion
|
|
3283
3284
|
//#region src/mcp/tools/create-ticket.ts
|
|
3284
|
-
const DATA_DIR$
|
|
3285
|
-
async function handleCreateTicket(input, dataDir = DATA_DIR$
|
|
3285
|
+
const DATA_DIR$16 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3286
|
+
async function handleCreateTicket(input, dataDir = DATA_DIR$16) {
|
|
3286
3287
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
3287
3288
|
const rules = loadSlaRules(dataDir);
|
|
3288
3289
|
const priority = input.priority ?? "normal";
|
|
@@ -3304,7 +3305,7 @@ async function handleCreateTicket(input, dataDir = DATA_DIR$15) {
|
|
|
3304
3305
|
text: JSON.stringify({ ticket }, null, 2)
|
|
3305
3306
|
}] };
|
|
3306
3307
|
}
|
|
3307
|
-
function registerCreateTicket(server, dataDir = DATA_DIR$
|
|
3308
|
+
function registerCreateTicket(server, dataDir = DATA_DIR$16) {
|
|
3308
3309
|
server.registerTool("create_ticket", {
|
|
3309
3310
|
description: `Create a support ticket for a customer. Auto-calculates SLA due date based on priority.
|
|
3310
3311
|
Returns: { ticket } with id T-NNN, status=open, slaDue`,
|
|
@@ -3330,8 +3331,8 @@ Returns: { ticket } with id T-NNN, status=open, slaDue`,
|
|
|
3330
3331
|
}
|
|
3331
3332
|
//#endregion
|
|
3332
3333
|
//#region src/mcp/tools/update-ticket.ts
|
|
3333
|
-
const DATA_DIR$
|
|
3334
|
-
async function handleUpdateTicket(input, dataDir = DATA_DIR$
|
|
3334
|
+
const DATA_DIR$15 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3335
|
+
async function handleUpdateTicket(input, dataDir = DATA_DIR$15) {
|
|
3335
3336
|
const ticket = (await readTickets(dataDir, input.slug)).find((t) => t.id === input.ticketId);
|
|
3336
3337
|
if (!ticket) return { content: [{
|
|
3337
3338
|
type: "text",
|
|
@@ -3350,7 +3351,7 @@ async function handleUpdateTicket(input, dataDir = DATA_DIR$14) {
|
|
|
3350
3351
|
text: JSON.stringify({ ticket: updated }, null, 2)
|
|
3351
3352
|
}] };
|
|
3352
3353
|
}
|
|
3353
|
-
function registerUpdateTicket(server, dataDir = DATA_DIR$
|
|
3354
|
+
function registerUpdateTicket(server, dataDir = DATA_DIR$15) {
|
|
3354
3355
|
server.registerTool("update_ticket", {
|
|
3355
3356
|
description: `Update a ticket's status or assignee. Setting status=resolved auto-sets resolved date.
|
|
3356
3357
|
Returns: { ticket }`,
|
|
@@ -3375,8 +3376,8 @@ Returns: { ticket }`,
|
|
|
3375
3376
|
}
|
|
3376
3377
|
//#endregion
|
|
3377
3378
|
//#region src/mcp/tools/list-tickets.ts
|
|
3378
|
-
const DATA_DIR$
|
|
3379
|
-
async function handleListTickets(input, dataDir = DATA_DIR$
|
|
3379
|
+
const DATA_DIR$14 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3380
|
+
async function handleListTickets(input, dataDir = DATA_DIR$14) {
|
|
3380
3381
|
const results = await listAllTickets(dataDir, {
|
|
3381
3382
|
...input.slug !== void 0 ? { slug: input.slug } : {},
|
|
3382
3383
|
...input.status !== void 0 ? { status: input.status } : {},
|
|
@@ -3388,7 +3389,7 @@ async function handleListTickets(input, dataDir = DATA_DIR$13) {
|
|
|
3388
3389
|
text: JSON.stringify({ tickets: results }, null, 2)
|
|
3389
3390
|
}] };
|
|
3390
3391
|
}
|
|
3391
|
-
function registerListTickets(server, dataDir = DATA_DIR$
|
|
3392
|
+
function registerListTickets(server, dataDir = DATA_DIR$14) {
|
|
3392
3393
|
server.registerTool("list_tickets", {
|
|
3393
3394
|
description: `List support tickets. Filter by customer, status, priority, or assignee. Sorted by priority then date.
|
|
3394
3395
|
Returns: { tickets: Array<{ slug, ticket }> }`,
|
|
@@ -3418,8 +3419,8 @@ Returns: { tickets: Array<{ slug, ticket }> }`,
|
|
|
3418
3419
|
}
|
|
3419
3420
|
//#endregion
|
|
3420
3421
|
//#region src/mcp/tools/close-ticket.ts
|
|
3421
|
-
const DATA_DIR$
|
|
3422
|
-
async function handleCloseTicket(input, dataDir = DATA_DIR$
|
|
3422
|
+
const DATA_DIR$13 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3423
|
+
async function handleCloseTicket(input, dataDir = DATA_DIR$13) {
|
|
3423
3424
|
const ticket = (await readTickets(dataDir, input.slug)).find((t) => t.id === input.ticketId);
|
|
3424
3425
|
if (!ticket) return { content: [{
|
|
3425
3426
|
type: "text",
|
|
@@ -3446,7 +3447,7 @@ async function handleCloseTicket(input, dataDir = DATA_DIR$12) {
|
|
|
3446
3447
|
text: JSON.stringify({ ticket: updated }, null, 2)
|
|
3447
3448
|
}] };
|
|
3448
3449
|
}
|
|
3449
|
-
function registerCloseTicket(server, dataDir = DATA_DIR$
|
|
3450
|
+
function registerCloseTicket(server, dataDir = DATA_DIR$13) {
|
|
3450
3451
|
server.registerTool("close_ticket", {
|
|
3451
3452
|
description: `Close a support ticket. Optionally logs the resolution as an interaction.
|
|
3452
3453
|
Returns: { ticket } with status=closed`,
|
|
@@ -3463,8 +3464,8 @@ Returns: { ticket } with status=closed`,
|
|
|
3463
3464
|
}
|
|
3464
3465
|
//#endregion
|
|
3465
3466
|
//#region src/mcp/tools/send-nps-survey.ts
|
|
3466
|
-
const DATA_DIR$
|
|
3467
|
-
async function handleSendNpsSurvey(input, dataDir = DATA_DIR$
|
|
3467
|
+
const DATA_DIR$12 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3468
|
+
async function handleSendNpsSurvey(input, dataDir = DATA_DIR$12) {
|
|
3468
3469
|
const survey = getSurvey(dataDir, input.surveyId);
|
|
3469
3470
|
if (!survey) return { content: [{
|
|
3470
3471
|
type: "text",
|
|
@@ -3485,7 +3486,7 @@ async function handleSendNpsSurvey(input, dataDir = DATA_DIR$11) {
|
|
|
3485
3486
|
}, null, 2)
|
|
3486
3487
|
}] };
|
|
3487
3488
|
}
|
|
3488
|
-
function registerSendNpsSurvey(server, dataDir = DATA_DIR$
|
|
3489
|
+
function registerSendNpsSurvey(server, dataDir = DATA_DIR$12) {
|
|
3489
3490
|
server.registerTool("send_nps_survey", {
|
|
3490
3491
|
description: `Generate an NPS/CSAT survey email for a customer contact. Returns subject, HTML body, and a token-based response URL.
|
|
3491
3492
|
Does NOT send automatically — returns draft for review.
|
|
@@ -3505,8 +3506,8 @@ Returns: { token, subject, body, surveyUrl }`,
|
|
|
3505
3506
|
}
|
|
3506
3507
|
//#endregion
|
|
3507
3508
|
//#region src/mcp/tools/get-survey-results.ts
|
|
3508
|
-
const DATA_DIR$
|
|
3509
|
-
async function handleGetSurveyResults(input, dataDir = DATA_DIR$
|
|
3509
|
+
const DATA_DIR$11 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3510
|
+
async function handleGetSurveyResults(input, dataDir = DATA_DIR$11) {
|
|
3510
3511
|
const responses = loadSurveyResponses(dataDir, input.surveyId, input.slug);
|
|
3511
3512
|
const nps = calcNpsScore(responses);
|
|
3512
3513
|
const promoters = responses.filter((r) => r.score >= 9).length;
|
|
@@ -3532,7 +3533,7 @@ async function handleGetSurveyResults(input, dataDir = DATA_DIR$10) {
|
|
|
3532
3533
|
}, null, 2)
|
|
3533
3534
|
}] };
|
|
3534
3535
|
}
|
|
3535
|
-
function registerGetSurveyResults(server, dataDir = DATA_DIR$
|
|
3536
|
+
function registerGetSurveyResults(server, dataDir = DATA_DIR$11) {
|
|
3536
3537
|
server.registerTool("get_survey_results", {
|
|
3537
3538
|
description: `Get NPS/CSAT survey results with score breakdown. Calculates Net Promoter Score.
|
|
3538
3539
|
Returns: { npsScore, totalResponses, promoters, passives, detractors, responses[] }`,
|
|
@@ -3547,8 +3548,8 @@ Returns: { npsScore, totalResponses, promoters, passives, detractors, responses[
|
|
|
3547
3548
|
}
|
|
3548
3549
|
//#endregion
|
|
3549
3550
|
//#region src/mcp/tools/search-knowledge-base.ts
|
|
3550
|
-
const DATA_DIR$
|
|
3551
|
-
async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$
|
|
3551
|
+
const DATA_DIR$10 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3552
|
+
async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$10) {
|
|
3552
3553
|
const results = searchKbSimple(dataDir, input.query, { ...input.publicOnly ? { publicOnly: true } : {} });
|
|
3553
3554
|
const limited = (input.category ? results.filter((a) => a.category === input.category) : results).slice(0, input.limit ?? 10);
|
|
3554
3555
|
return { content: [{
|
|
@@ -3563,7 +3564,7 @@ async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$9) {
|
|
|
3563
3564
|
}, null, 2)
|
|
3564
3565
|
}] };
|
|
3565
3566
|
}
|
|
3566
|
-
function registerSearchKnowledgeBase(server, dataDir = DATA_DIR$
|
|
3567
|
+
function registerSearchKnowledgeBase(server, dataDir = DATA_DIR$10) {
|
|
3567
3568
|
server.registerTool("search_knowledge_base", {
|
|
3568
3569
|
description: `Search the knowledge base for articles. Text search on title, body, and tags.
|
|
3569
3570
|
Returns: { count, articles[] } with excerpts`,
|
|
@@ -3582,8 +3583,8 @@ Returns: { count, articles[] } with excerpts`,
|
|
|
3582
3583
|
}
|
|
3583
3584
|
//#endregion
|
|
3584
3585
|
//#region src/mcp/tools/create-kb-article.ts
|
|
3585
|
-
const DATA_DIR$
|
|
3586
|
-
async function handleCreateKbArticle(input, dataDir = DATA_DIR$
|
|
3586
|
+
const DATA_DIR$9 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3587
|
+
async function handleCreateKbArticle(input, dataDir = DATA_DIR$9) {
|
|
3587
3588
|
if (getKbArticle(dataDir, input.id)) return { content: [{
|
|
3588
3589
|
type: "text",
|
|
3589
3590
|
text: JSON.stringify({ error: `Article '${input.id}' already exists` })
|
|
@@ -3611,7 +3612,7 @@ async function handleCreateKbArticle(input, dataDir = DATA_DIR$8) {
|
|
|
3611
3612
|
}, null, 2)
|
|
3612
3613
|
}] };
|
|
3613
3614
|
}
|
|
3614
|
-
function registerCreateKbArticle(server, dataDir = DATA_DIR$
|
|
3615
|
+
function registerCreateKbArticle(server, dataDir = DATA_DIR$9) {
|
|
3615
3616
|
server.registerTool("create_kb_article", {
|
|
3616
3617
|
description: `Create a new knowledge base article. Articles are stored as Markdown files in .agentic/knowledge-base/.
|
|
3617
3618
|
Returns: { id, title, category, path }`,
|
|
@@ -3636,8 +3637,8 @@ Returns: { id, title, category, path }`,
|
|
|
3636
3637
|
}
|
|
3637
3638
|
//#endregion
|
|
3638
3639
|
//#region src/mcp/tools/backup-now.ts
|
|
3639
|
-
const DATA_DIR$
|
|
3640
|
-
async function handleBackupNow(input, dataDir = DATA_DIR$
|
|
3640
|
+
const DATA_DIR$8 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3641
|
+
async function handleBackupNow(input, dataDir = DATA_DIR$8) {
|
|
3641
3642
|
const zipPath = path.join(dataDir, `dxcrm-backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19)}.zip`);
|
|
3642
3643
|
const manifest = await runBackup(zipPath, dataDir, { ...input.remote ? { remote: input.remote } : {} }).catch(() => null);
|
|
3643
3644
|
if (!manifest) return { content: [{
|
|
@@ -3674,8 +3675,8 @@ function registerBackupNow(server) {
|
|
|
3674
3675
|
}
|
|
3675
3676
|
//#endregion
|
|
3676
3677
|
//#region src/mcp/tools/list-backups.ts
|
|
3677
|
-
const DATA_DIR$
|
|
3678
|
-
async function handleListBackups(input, dataDir = DATA_DIR$
|
|
3678
|
+
const DATA_DIR$7 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3679
|
+
async function handleListBackups(input, dataDir = DATA_DIR$7) {
|
|
3679
3680
|
const logEntries = readBackupLog(dataDir);
|
|
3680
3681
|
const fileEntries = listBackupsInDir(dataDir);
|
|
3681
3682
|
const entries = logEntries.length > 0 ? logEntries : fileEntries;
|
|
@@ -3709,8 +3710,8 @@ function registerListBackups(server) {
|
|
|
3709
3710
|
}
|
|
3710
3711
|
//#endregion
|
|
3711
3712
|
//#region src/mcp/tools/trigger-sync.ts
|
|
3712
|
-
const DATA_DIR$
|
|
3713
|
-
async function handleTriggerSync(input, dataDir = DATA_DIR$
|
|
3713
|
+
const DATA_DIR$6 = process.cwd();
|
|
3714
|
+
async function handleTriggerSync(input, dataDir = DATA_DIR$6) {
|
|
3714
3715
|
const auth = getGmailAuth();
|
|
3715
3716
|
if (!auth) return { content: [{
|
|
3716
3717
|
type: "text",
|
|
@@ -3804,8 +3805,8 @@ Returns: { success: boolean, synced: number, skipped: number, customers: [...],
|
|
|
3804
3805
|
}
|
|
3805
3806
|
//#endregion
|
|
3806
3807
|
//#region src/mcp/tools/get-audit-log.ts
|
|
3807
|
-
const DATA_DIR$
|
|
3808
|
-
async function handleGetAuditLog(input, dataDir = DATA_DIR$
|
|
3808
|
+
const DATA_DIR$5 = process.cwd();
|
|
3809
|
+
async function handleGetAuditLog(input, dataDir = DATA_DIR$5) {
|
|
3809
3810
|
const entries = readAuditLog(dataDir);
|
|
3810
3811
|
const filterOpts = { limit: input.limit ?? 50 };
|
|
3811
3812
|
if (input.slug !== void 0) filterOpts.slug = input.slug;
|
|
@@ -3847,8 +3848,8 @@ Returns: { total: number, returned: number, entries: [{timestamp, actor, tool, s
|
|
|
3847
3848
|
}
|
|
3848
3849
|
//#endregion
|
|
3849
3850
|
//#region src/mcp/tools/get-logs.ts
|
|
3850
|
-
const DATA_DIR$
|
|
3851
|
-
async function handleGetLogs(input, dataDir = DATA_DIR$
|
|
3851
|
+
const DATA_DIR$4 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3852
|
+
async function handleGetLogs(input, dataDir = DATA_DIR$4) {
|
|
3852
3853
|
const query = {
|
|
3853
3854
|
...input.level !== void 0 ? { level: input.level } : {},
|
|
3854
3855
|
...input.component !== void 0 ? { component: input.component } : {},
|
|
@@ -3910,8 +3911,8 @@ Returns (summary): { total, byLevel, byComponent, firstTs, lastTs, recentErrors
|
|
|
3910
3911
|
}
|
|
3911
3912
|
//#endregion
|
|
3912
3913
|
//#region src/mcp/tools/get-diagnostics.ts
|
|
3913
|
-
const DATA_DIR$
|
|
3914
|
-
async function handleGetDiagnostics(input, dataDir = DATA_DIR$
|
|
3914
|
+
const DATA_DIR$3 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3915
|
+
async function handleGetDiagnostics(input, dataDir = DATA_DIR$3) {
|
|
3915
3916
|
let cleaned = 0;
|
|
3916
3917
|
if (input.fix) {
|
|
3917
3918
|
const { cleanupTempFiles } = await import("./doctor-CYDaNmFn.js");
|
|
@@ -3943,6 +3944,46 @@ Returns: { ok: boolean, tempFilesRemoved?: number, checks: [{ name, status: "ok"
|
|
|
3943
3944
|
}, async ({ fix }) => handleGetDiagnostics(fix !== void 0 ? { fix } : {}));
|
|
3944
3945
|
}
|
|
3945
3946
|
//#endregion
|
|
3947
|
+
//#region src/mcp/tools/get-pipeline-changes.ts
|
|
3948
|
+
const DATA_DIR$2 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3949
|
+
function daysAgoIso(days) {
|
|
3950
|
+
return (/* @__PURE__ */ new Date(Date.now() - days * 864e5)).toISOString().slice(0, 10);
|
|
3951
|
+
}
|
|
3952
|
+
async function handleGetPipelineChanges(input, dataDir = DATA_DIR$2) {
|
|
3953
|
+
const since = input.since ?? daysAgoIso(input.days ?? 7);
|
|
3954
|
+
const diff = diffAgainstNow(dataDir, since);
|
|
3955
|
+
const payload = diff ? diff : { error: `No pipeline snapshot at or before ${since}. Snapshots accrue daily via the daemon.` };
|
|
3956
|
+
return { content: [{
|
|
3957
|
+
type: "text",
|
|
3958
|
+
text: JSON.stringify(payload, null, 2)
|
|
3959
|
+
}] };
|
|
3960
|
+
}
|
|
3961
|
+
function registerGetPipelineChanges(server) {
|
|
3962
|
+
server.registerTool("get_pipeline_changes", {
|
|
3963
|
+
title: "Get Pipeline Changes",
|
|
3964
|
+
description: `Pipeline time-travel: what changed in the pipeline since a baseline date.
|
|
3965
|
+
Compares the live pipeline against the most recent daily snapshot at/before the
|
|
3966
|
+
baseline. Answers "what moved since last week?", "what did we win/lose?".
|
|
3967
|
+
|
|
3968
|
+
Args:
|
|
3969
|
+
since: Baseline date YYYY-MM-DD (optional)
|
|
3970
|
+
days: Look back this many days instead of a date (default 7)
|
|
3971
|
+
|
|
3972
|
+
Returns: { fromId, toId, added[], removed[], advanced[{from,to}], won[], lost[],
|
|
3973
|
+
valueChanged[{from,to}], openValueBefore, openValueAfter, openValueDelta }
|
|
3974
|
+
or { error } when no baseline snapshot exists yet.`,
|
|
3975
|
+
inputSchema: z.object({
|
|
3976
|
+
since: z.string().optional().describe("Baseline date YYYY-MM-DD"),
|
|
3977
|
+
days: z.number().int().min(1).max(365).optional().describe("Look-back window in days (default 7)")
|
|
3978
|
+
})
|
|
3979
|
+
}, async ({ since, days }) => {
|
|
3980
|
+
const input = {};
|
|
3981
|
+
if (since !== void 0) input.since = since;
|
|
3982
|
+
if (days !== void 0) input.days = days;
|
|
3983
|
+
return handleGetPipelineChanges(input);
|
|
3984
|
+
});
|
|
3985
|
+
}
|
|
3986
|
+
//#endregion
|
|
3946
3987
|
//#region src/mcp/prompts.ts
|
|
3947
3988
|
/**
|
|
3948
3989
|
* CRM playbook prompts exposed via MCP `prompts/list` + `prompts/get`.
|
|
@@ -4200,6 +4241,7 @@ function createMcpServer() {
|
|
|
4200
4241
|
registerGetAuditLog(server);
|
|
4201
4242
|
registerGetLogs(server);
|
|
4202
4243
|
registerGetDiagnostics(server);
|
|
4244
|
+
registerGetPipelineChanges(server);
|
|
4203
4245
|
registerCustomObjectTools(server);
|
|
4204
4246
|
registerPrompts(server);
|
|
4205
4247
|
registerResources(server);
|
|
@@ -4398,4 +4440,4 @@ else startStdio().catch((err) => {
|
|
|
4398
4440
|
//#endregion
|
|
4399
4441
|
export { startHttp, startStdio };
|
|
4400
4442
|
|
|
4401
|
-
//# sourceMappingURL=server-
|
|
4443
|
+
//# sourceMappingURL=server-BbInMUgp.js.map
|