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