@datasynx/agentic-crm 1.7.0 → 1.9.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 +101 -8
- package/dist/cli.js.map +1 -1
- package/dist/daemon/worker.js +3 -3
- package/dist/funnel-B2mwpZE1.js +89 -0
- package/dist/funnel-B2mwpZE1.js.map +1 -0
- package/dist/funnel-CJ7fy7hG.js +2 -0
- package/dist/{index-DcDaz_cu.d.cts → index-BAutNcAT.d.cts} +11 -11
- package/dist/index-BAutNcAT.d.cts.map +1 -0
- package/dist/index.d.cts +11 -11
- package/dist/index.d.cts.map +1 -1
- package/dist/{knowledge-base-Cc0niBFf.js → knowledge-base-yo-BLUcB.js} +3 -1
- package/dist/knowledge-base-yo-BLUcB.js.map +1 -0
- package/dist/{login-yt9OOQQk.js → login-dc_Hqosw.js} +2 -2
- package/dist/{login-yt9OOQQk.js.map → login-dc_Hqosw.js.map} +1 -1
- package/dist/mailbox-config-BU3vib2T.js +2 -0
- package/dist/{mailbox-config-Dn2xTn9N.js → mailbox-config-trjLPHPG.js} +2 -2
- package/dist/{mailbox-config-Dn2xTn9N.js.map → mailbox-config-trjLPHPG.js.map} +1 -1
- package/dist/{mailbox-poll-B8dvFAXT.js → mailbox-poll-Ban7C3X0.js} +3 -3
- package/dist/{mailbox-poll-B8dvFAXT.js.map → mailbox-poll-Ban7C3X0.js.map} +1 -1
- package/dist/mcp-CdTJWTJf.d.cts.map +1 -1
- package/dist/mcp-CdTJWTJf.d.ts.map +1 -1
- package/dist/mcp.cjs +415 -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 +415 -137
- package/dist/mcp.js.map +1 -1
- package/dist/{server-BbInMUgp.js → server-DAcwmRPE.js} +195 -133
- package/dist/server-DAcwmRPE.js.map +1 -0
- package/dist/{token-resolver-D98qPOOf.js → token-resolver-CL8-CSgZ.js} +2 -2
- package/dist/{token-resolver-D98qPOOf.js.map → token-resolver-CL8-CSgZ.js.map} +1 -1
- package/dist/{token-store-B0h0USqe.js → token-store-BPDwePNT.js} +13 -2
- package/dist/token-store-BPDwePNT.js.map +1 -0
- package/dist/token-store-D3HCeXmE.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-DcDaz_cu.d.cts.map +0 -1
- package/dist/knowledge-base-Cc0niBFf.js.map +0 -1
- package/dist/mailbox-config-Bu-J1O4I.js +0 -2
- package/dist/server-BbInMUgp.js.map +0 -1
- package/dist/token-store-B0h0USqe.js.map +0 -1
- package/dist/token-store-CEmz8d-0.js +0 -2
package/dist/cli.js
CHANGED
|
@@ -5,7 +5,7 @@ import { i as writeJsonFile } from "./json-store-WWsFzXub.js";
|
|
|
5
5
|
import { a as warning, i as success, n as error, r as info, t as bold } from "./colors-BG07TZQz.js";
|
|
6
6
|
import { n as getSession } from "./session-store-CEa39Dxs.js";
|
|
7
7
|
import { i as sessionCommand, r as readAllSessions } from "./session-BgGDyP2C.js";
|
|
8
|
-
import { a as searchKbSimple, i as listKbArticles, n as getKbArticle, o as writeKbArticle, s as CAPABILITIES_TEXT, t as deleteKbArticle } from "./knowledge-base-
|
|
8
|
+
import { a as searchKbSimple, i as listKbArticles, n as getKbArticle, o as writeKbArticle, s as CAPABILITIES_TEXT, t as deleteKbArticle } from "./knowledge-base-yo-BLUcB.js";
|
|
9
9
|
import { a as restoreCommand, t as backupCommand } from "./backup-CTlIxUdO.js";
|
|
10
10
|
import { n as readSyncState } from "./sync-state-DMZgzpez.js";
|
|
11
11
|
import { n as readUnmatched } from "./unmatched-transcripts-DC-VQ9YS.js";
|
|
@@ -23,7 +23,8 @@ import { n as listQuotes, r as readQuote, t as generateQuote } from "./quote-gen
|
|
|
23
23
|
import { i as upsertTicket, n as nextTicketId, r as readTickets, t as listAllTickets } from "./ticket-writer-a9on36Wb.js";
|
|
24
24
|
import { i as loadSlaRules, t as calcSlaDue } from "./sla-engine-O-A1ntu_.js";
|
|
25
25
|
import { a as listSurveys, d as writeSurvey, i as getSurvey, l as savePendingSurvey, n as calcNpsScore, o as loadSurveyResponses, r as generateSurveyToken } from "./survey-engine-DngXBv47.js";
|
|
26
|
-
import { i as resolveAccountConfig, n as imapConfigFromEnv } from "./mailbox-config-
|
|
26
|
+
import { i as resolveAccountConfig, n as imapConfigFromEnv, r as parseAccount } from "./mailbox-config-trjLPHPG.js";
|
|
27
|
+
import { i as removeMailboxToken, n as listMailboxTokens, t as isTokenExpired } from "./token-store-BPDwePNT.js";
|
|
27
28
|
import { Command } from "commander";
|
|
28
29
|
import path from "path";
|
|
29
30
|
import fs from "fs";
|
|
@@ -242,14 +243,14 @@ mcpCommand.command("start").description("Start MCP server (stdio by default)").o
|
|
|
242
243
|
if (opts.http) {
|
|
243
244
|
const port = parseInt(opts.port, 10);
|
|
244
245
|
console.error(info(`Starting MCP server in HTTP mode on port ${port}...`));
|
|
245
|
-
const { startHttp } = await import("./server-
|
|
246
|
+
const { startHttp } = await import("./server-DAcwmRPE.js");
|
|
246
247
|
await startHttp(port);
|
|
247
248
|
} else {
|
|
248
|
-
const { startStdio } = await import("./server-
|
|
249
|
+
const { startStdio } = await import("./server-DAcwmRPE.js");
|
|
249
250
|
await startStdio();
|
|
250
251
|
}
|
|
251
252
|
});
|
|
252
|
-
const TOOL_COUNT =
|
|
253
|
+
const TOOL_COUNT = 61;
|
|
253
254
|
/** Claude Code: CLAUDE.md in CRM dataDir */
|
|
254
255
|
function buildClaudeMd(dataDir) {
|
|
255
256
|
return `# DatasynxOpenCRM v2 — Agent Instructions (${TOOL_COUNT} MCP Tools)
|
|
@@ -378,6 +379,8 @@ It combines graph, health, revenue simulation, playbook, and org intelligence in
|
|
|
378
379
|
- \`get_logs({ level?, component?, since?, contains?, limit?, summary? })\` — query/aggregate the structured application log
|
|
379
380
|
- \`get_diagnostics({ fix? })\` — self-diagnostic health check (data integrity, temp files, log errors, backups)
|
|
380
381
|
- \`get_pipeline_changes({ since?, days? })\` — pipeline time-travel: what changed (won/lost/moved/value) since a date
|
|
382
|
+
- \`get_pipeline_velocity({ stalledDays? })\` — stage dwell times, sales cycle, and stalled deals from snapshot history
|
|
383
|
+
- \`get_pipeline_funnel()\` — conversion funnel & win rate: where deals leak out of the pipeline
|
|
381
384
|
|
|
382
385
|
### Custom Objects (Platform / metadata)
|
|
383
386
|
- \`define_custom_object({ name, label?, fields })\` — define a runtime entity type with typed fields (no migration), admin
|
|
@@ -639,7 +642,8 @@ create_ticket · update_ticket · list_tickets · close_ticket ·
|
|
|
639
642
|
send_nps_survey · get_survey_results ·
|
|
640
643
|
search_knowledge_base · create_kb_article ·
|
|
641
644
|
backup_now · list_backups ·
|
|
642
|
-
trigger_sync · get_audit_log · get_logs · get_diagnostics ·
|
|
645
|
+
trigger_sync · get_audit_log · get_logs · get_diagnostics ·
|
|
646
|
+
get_pipeline_changes · get_pipeline_velocity · get_pipeline_funnel ·
|
|
643
647
|
define_custom_object · create_record · list_records · list_custom_objects
|
|
644
648
|
|
|
645
649
|
## Data: ${dataDir}`.trim();
|
|
@@ -1844,6 +1848,12 @@ async function runStatus(opts, dataDir) {
|
|
|
1844
1848
|
const daemonLine = daemon.running ? success(`running (PID ${daemon.pid})`) : error("not running");
|
|
1845
1849
|
console.log(` Daemon: ${daemonLine}`);
|
|
1846
1850
|
console.log(` Customers: ${slugs.length} active`);
|
|
1851
|
+
const { listMailboxTokens, isTokenExpired } = await import("./token-store-D3HCeXmE.js");
|
|
1852
|
+
const mailboxTokens = listMailboxTokens(dir);
|
|
1853
|
+
if (mailboxTokens.length > 0) {
|
|
1854
|
+
const valid = mailboxTokens.filter((t) => !isTokenExpired(t)).length;
|
|
1855
|
+
console.log(` Mailboxes: ${mailboxTokens.length} linked (${valid} valid)`);
|
|
1856
|
+
}
|
|
1847
1857
|
const session = getSession() ?? readAllSessions(dir)[0] ?? null;
|
|
1848
1858
|
if (session) {
|
|
1849
1859
|
const ownerPart = session.owner ? ` [${session.owner}]` : "";
|
|
@@ -3018,6 +3028,54 @@ pipelineCommand.command("changes").description("Show what changed in the pipelin
|
|
|
3018
3028
|
for (const d of diff.added) console.log(` ${d.slug}/${d.name}`);
|
|
3019
3029
|
}
|
|
3020
3030
|
});
|
|
3031
|
+
pipelineCommand.command("velocity").description("Stage dwell times, sales cycle, and stalled deals from snapshot history").option("--stalled-days <n>", "Days in one stage before a deal counts as stalled (default 14)").action(async (opts) => {
|
|
3032
|
+
const { analyzeVelocity } = await import("./velocity-BtX1l5Gh.js");
|
|
3033
|
+
const analyzeOpts = {};
|
|
3034
|
+
if (opts.stalledDays !== void 0) {
|
|
3035
|
+
const n = parseInt(opts.stalledDays, 10);
|
|
3036
|
+
if (Number.isFinite(n) && n > 0) analyzeOpts.stalledDays = n;
|
|
3037
|
+
}
|
|
3038
|
+
const report = analyzeVelocity(dataDir$17(), analyzeOpts);
|
|
3039
|
+
if (report.snapshotCount === 0) {
|
|
3040
|
+
console.log(info("No snapshots yet. Run 'dxcrm pipeline snapshot' (or let the daemon take daily ones)."));
|
|
3041
|
+
return;
|
|
3042
|
+
}
|
|
3043
|
+
console.log(bold(`Pipeline velocity (${report.snapshotCount} snapshots, ${report.fromId} → ${report.toId})`));
|
|
3044
|
+
if (report.stageDurations.length) {
|
|
3045
|
+
console.log(info("\nAvg time in stage:"));
|
|
3046
|
+
for (const s of report.stageDurations) {
|
|
3047
|
+
const samples = `${s.samples} sample${s.samples === 1 ? "" : "s"}`;
|
|
3048
|
+
console.log(` ${s.stage.padEnd(14)} ${s.avgDays}d (${samples})`);
|
|
3049
|
+
}
|
|
3050
|
+
}
|
|
3051
|
+
const cycle = report.avgSalesCycleDays;
|
|
3052
|
+
const cycleStr = cycle === null ? "n/a (no won deals yet)" : `${cycle}d avg`;
|
|
3053
|
+
console.log(`\n ${"Sales cycle".padEnd(14)} ${cycleStr} over ${report.wonCount} won`);
|
|
3054
|
+
if (report.stalledDeals.length) {
|
|
3055
|
+
console.log(error(`\nStalled deals (> ${report.stalledThresholdDays}d in stage):`));
|
|
3056
|
+
for (const d of report.stalledDeals) console.log(` ${d.slug}/${d.name}: ${d.stage}, ${d.daysInStage}d €${d.value.toLocaleString()}`);
|
|
3057
|
+
} else console.log(success(`\nNo stalled deals (threshold ${report.stalledThresholdDays}d).`));
|
|
3058
|
+
});
|
|
3059
|
+
pipelineCommand.command("funnel").description("Conversion funnel & win rate: where deals leak out of the pipeline").action(async () => {
|
|
3060
|
+
const { analyzeFunnel } = await import("./funnel-CJ7fy7hG.js");
|
|
3061
|
+
const report = analyzeFunnel(dataDir$17());
|
|
3062
|
+
if (report.snapshotCount === 0) {
|
|
3063
|
+
console.log(info("No snapshots yet. Run 'dxcrm pipeline snapshot' (or let the daemon take daily ones)."));
|
|
3064
|
+
return;
|
|
3065
|
+
}
|
|
3066
|
+
console.log(bold(`Pipeline funnel (${report.snapshotCount} snapshots, ${report.fromId} → ${report.toId})`));
|
|
3067
|
+
for (const s of report.stages) {
|
|
3068
|
+
const conv = s.conversionPctToNext === null ? "" : ` → ${s.conversionPctToNext}% convert`;
|
|
3069
|
+
console.log(` ${s.stage.padEnd(14)} ${String(s.reached).padStart(4)} reached${conv}`);
|
|
3070
|
+
}
|
|
3071
|
+
const wr = report.winRatePct;
|
|
3072
|
+
const wrStr = wr === null ? "n/a (nothing closed yet)" : `${wr}%`;
|
|
3073
|
+
console.log(`\n ${"Win rate".padEnd(14)} ${wrStr} (${report.wonCount} won / ${report.lostCount} lost)`);
|
|
3074
|
+
if (report.biggestLeak) {
|
|
3075
|
+
const l = report.biggestLeak;
|
|
3076
|
+
console.log(error(`\nBiggest leak: ${l.from} → ${l.to} (only ${l.conversionPct}% convert)`));
|
|
3077
|
+
}
|
|
3078
|
+
});
|
|
3021
3079
|
//#endregion
|
|
3022
3080
|
//#region src/commands/rbac.ts
|
|
3023
3081
|
const ROLES = [
|
|
@@ -4483,6 +4541,22 @@ complianceCommand.command("status", { isDefault: true }).description("Show the a
|
|
|
4483
4541
|
});
|
|
4484
4542
|
//#endregion
|
|
4485
4543
|
//#region src/commands/mailbox.ts
|
|
4544
|
+
/** Summarize every stored mailbox OAuth account. */
|
|
4545
|
+
function runMailboxList(dataDir) {
|
|
4546
|
+
return listMailboxTokens(dataDir).map((t) => ({
|
|
4547
|
+
account: `${t.provider}:${t.user}`,
|
|
4548
|
+
provider: t.provider,
|
|
4549
|
+
user: t.user,
|
|
4550
|
+
status: isTokenExpired(t) ? "expired" : "valid",
|
|
4551
|
+
expiresAt: new Date(t.expiresAt).toISOString()
|
|
4552
|
+
}));
|
|
4553
|
+
}
|
|
4554
|
+
/** Remove a stored mailbox account by "provider:user". */
|
|
4555
|
+
function runMailboxLogout(dataDir, account) {
|
|
4556
|
+
const parsed = parseAccount(account);
|
|
4557
|
+
if (!parsed) return { error: `Invalid account '${account}'. Use 'gmail:you@gmail.com' or 'microsoft:you@org.com'.` };
|
|
4558
|
+
return { removed: removeMailboxToken(dataDir, parsed.provider, parsed.user) };
|
|
4559
|
+
}
|
|
4486
4560
|
/**
|
|
4487
4561
|
* Sync an IMAP mailbox (any provider). With a slug, all mail goes to that one
|
|
4488
4562
|
* customer; without, mail is auto-routed to customers by sender/recipient
|
|
@@ -4536,7 +4610,7 @@ async function runLogin(provider, user) {
|
|
|
4536
4610
|
return;
|
|
4537
4611
|
}
|
|
4538
4612
|
const account = user ?? (await ask("Gmail address: ")).trim();
|
|
4539
|
-
const { runGmailLogin } = await import("./login-
|
|
4613
|
+
const { runGmailLogin } = await import("./login-dc_Hqosw.js");
|
|
4540
4614
|
await runGmailLogin({
|
|
4541
4615
|
dataDir,
|
|
4542
4616
|
clientId,
|
|
@@ -4556,7 +4630,7 @@ async function runLogin(provider, user) {
|
|
|
4556
4630
|
}
|
|
4557
4631
|
const tenant = process.env["DXCRM_MS_TENANT"] ?? "common";
|
|
4558
4632
|
const account = user ?? (await ask("Outlook/Microsoft address: ")).trim();
|
|
4559
|
-
const { runMicrosoftLogin } = await import("./login-
|
|
4633
|
+
const { runMicrosoftLogin } = await import("./login-dc_Hqosw.js");
|
|
4560
4634
|
await runMicrosoftLogin({
|
|
4561
4635
|
dataDir,
|
|
4562
4636
|
clientId,
|
|
@@ -4582,6 +4656,25 @@ mailboxCommand.command("sync").description("Sync an IMAP mailbox; auto-routes to
|
|
|
4582
4656
|
includeAttachments: options.attachments !== false
|
|
4583
4657
|
});
|
|
4584
4658
|
});
|
|
4659
|
+
mailboxCommand.command("list").description("List logged-in mailbox accounts and their token status").action(() => {
|
|
4660
|
+
const accounts = runMailboxList(process.env["DXCRM_DATA_DIR"] ?? process.cwd());
|
|
4661
|
+
if (accounts.length === 0) {
|
|
4662
|
+
console.log(info("No mailbox accounts. Run 'dxcrm mailbox login gmail|microsoft'."));
|
|
4663
|
+
return;
|
|
4664
|
+
}
|
|
4665
|
+
for (const a of accounts) {
|
|
4666
|
+
const tag = a.status === "valid" ? success("valid") : error("expired");
|
|
4667
|
+
console.log(`${bold(a.account)} — token ${tag} (expires ${a.expiresAt})`);
|
|
4668
|
+
}
|
|
4669
|
+
});
|
|
4670
|
+
mailboxCommand.command("logout").description("Remove a stored mailbox account").argument("<account>", "provider:user (e.g. gmail:you@gmail.com)").action((account) => {
|
|
4671
|
+
const result = runMailboxLogout(process.env["DXCRM_DATA_DIR"] ?? process.cwd(), account);
|
|
4672
|
+
if ("error" in result) {
|
|
4673
|
+
console.error(error(result.error));
|
|
4674
|
+
return;
|
|
4675
|
+
}
|
|
4676
|
+
console.log(result.removed ? success(`✓ Removed ${bold(account)}.`) : info(`No stored account '${account}'.`));
|
|
4677
|
+
});
|
|
4585
4678
|
//#endregion
|
|
4586
4679
|
//#region src/commands/registry.ts
|
|
4587
4680
|
/** Every top-level `dxcrm` command, in display order. */
|