@datasynx/agentic-crm 0.1.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +264 -670
- package/dist/{approvals-DpjxGHFp.js → approvals-CmDT2eUg.js} +7 -24
- package/dist/approvals-CmDT2eUg.js.map +1 -0
- package/dist/{ask-CID3jnuL.js → ask-D8iYqDAr.js} +6 -6
- package/dist/{ask-CID3jnuL.js.map → ask-D8iYqDAr.js.map} +1 -1
- package/dist/atomic-write-8yjqqLtS.js +29 -0
- package/dist/atomic-write-8yjqqLtS.js.map +1 -0
- package/dist/atomic-write-BYmF-ThH.cjs +37 -0
- package/dist/atomic-write-BYmF-ThH.cjs.map +1 -0
- package/dist/auth-B5DcjJ_6.js +2 -0
- package/dist/{auth-DFWwWcYD.js → auth-DDXZTwS0.js} +4 -13
- package/dist/auth-DDXZTwS0.js.map +1 -0
- package/dist/{autofill-Di_-SP7t.js → autofill-B9VtlR2j.js} +2 -2
- package/dist/{autofill-Di_-SP7t.js.map → autofill-B9VtlR2j.js.map} +1 -1
- package/dist/{backup-CeMk9z86.js → backup-CTlIxUdO.js} +5 -7
- package/dist/backup-CTlIxUdO.js.map +1 -0
- package/dist/backup-LFnC09oV.js +2 -0
- package/dist/{churn-C28IgnAj.js → churn-DN9WDGNM.js} +3 -3
- package/dist/{churn-C28IgnAj.js.map → churn-DN9WDGNM.js.map} +1 -1
- package/dist/cli.js +282 -184
- package/dist/cli.js.map +1 -1
- package/dist/{compliance-CKSBoQUe.js → compliance-Bc12Hn9a.js} +3 -3
- package/dist/{compliance-CKSBoQUe.js.map → compliance-Bc12Hn9a.js.map} +1 -1
- package/dist/{compliance-CujOqAKk.js → compliance-TqYQXhBj.js} +1 -1
- package/dist/{compliance-B1kk5-YS.js → compliance-kq0xHRw3.js} +3 -3
- package/dist/{compliance-B1kk5-YS.js.map → compliance-kq0xHRw3.js.map} +1 -1
- package/dist/{compliance-B91zNvCR.cjs → compliance-pAj9FcGI.cjs} +3 -3
- package/dist/{compliance-B91zNvCR.cjs.map → compliance-pAj9FcGI.cjs.map} +1 -1
- package/dist/{context-builder-BzWAp3Zs.js → context-builder-7Uab5-G4.js} +3 -2
- package/dist/context-builder-7Uab5-G4.js.map +1 -0
- package/dist/context-builder-hmOPvgso.js +2 -0
- package/dist/{custom-fields-CzNeD3_v.js → custom-fields-BMyz5Ruh.js} +1 -1
- package/dist/{custom-fields-Pl2t9xzp.js → custom-fields-GzpOHW_2.js} +4 -13
- package/dist/custom-fields-GzpOHW_2.js.map +1 -0
- package/dist/{custom-objects-CIFrmQ2V.js → custom-objects-BNy-ayR-.js} +1 -1
- package/dist/{custom-objects-BHgn1GEX.js → custom-objects-CxW1gHwJ.js} +10 -25
- package/dist/custom-objects-CxW1gHwJ.js.map +1 -0
- package/dist/{customer-dir-DIylZ8Q6.js → customer-dir-CkMMXhb0.js} +9 -4
- package/dist/customer-dir-CkMMXhb0.js.map +1 -0
- package/dist/daemon/worker.js +66 -40
- package/dist/daemon/worker.js.map +1 -1
- package/dist/doctor-C14-vnJ1.js +103 -0
- package/dist/doctor-C14-vnJ1.js.map +1 -0
- package/dist/{enrichment-3XvgGDfB.js → enrichment-CDFdWmvD.js} +3 -3
- package/dist/{enrichment-3XvgGDfB.js.map → enrichment-CDFdWmvD.js.map} +1 -1
- package/dist/{file-lock-B_zi7NQl.js → file-lock-CcHotQkZ.js} +3 -4
- package/dist/file-lock-CcHotQkZ.js.map +1 -0
- package/dist/{gmail-sync-rQaVqKWd.js → gmail-sync-C-NmibzS.js} +13 -9
- package/dist/gmail-sync-C-NmibzS.js.map +1 -0
- package/dist/{gmail-sync-DIaxInDT.js → gmail-sync-DueE6tl5.js} +14 -10
- package/dist/gmail-sync-DueE6tl5.js.map +1 -0
- package/dist/{gmail-sync-hHm9gaWd.cjs → gmail-sync-GEy3oVvw.cjs} +13 -9
- package/dist/gmail-sync-GEy3oVvw.cjs.map +1 -0
- package/dist/{gmail-webhook-handler-DS7OlRPX.js → gmail-webhook-handler-B26COilD.js} +2 -2
- package/dist/{gmail-webhook-handler-e5Od25FX.js → gmail-webhook-handler-kGKpbY9h.js} +4 -4
- package/dist/{gmail-webhook-handler-e5Od25FX.js.map → gmail-webhook-handler-kGKpbY9h.js.map} +1 -1
- package/dist/{goal-engine-KpBftn4V.js → goal-engine-BbroPhqm.js} +10 -11
- package/dist/goal-engine-BbroPhqm.js.map +1 -0
- package/dist/{goal-engine-CUZSpERI.js → goal-engine-CfDAJTFt.js} +1 -1
- package/dist/{google-drive-sync-DEPcqFca.js → google-drive-sync-D1n7WKZn.js} +3 -3
- package/dist/{google-drive-sync-DEPcqFca.js.map → google-drive-sync-D1n7WKZn.js.map} +1 -1
- package/dist/{hygiene-DZqfYpFf.js → hygiene-DzQPnc6P.js} +3 -3
- package/dist/{hygiene-DZqfYpFf.js.map → hygiene-DzQPnc6P.js.map} +1 -1
- package/dist/identity-CB7j-Zr1.js +2 -0
- package/dist/{identity-CI6olMNm.js → identity-_uZ3Lbr2.js} +2 -2
- package/dist/{identity-CI6olMNm.js.map → identity-_uZ3Lbr2.js.map} +1 -1
- package/dist/{import-hubspot-BaK71U_K.js → import-hubspot-DB4n89jy.js} +51 -45
- package/dist/import-hubspot-DB4n89jy.js.map +1 -0
- package/dist/{index-V8BFaH-b.d.ts → index-B0IMMrp_.d.ts} +8 -4
- package/dist/{index-V8BFaH-b.d.ts.map → index-B0IMMrp_.d.ts.map} +1 -1
- package/dist/{index-YqwMd6aQ.d.cts → index-pY7tYXwH.d.cts} +8 -4
- package/dist/{index-YqwMd6aQ.d.cts.map → index-pY7tYXwH.d.cts.map} +1 -1
- package/dist/index.cjs +19 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -4
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +8 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -21
- package/dist/index.js.map +1 -1
- package/dist/{interactions-writer-DO3KcSR3.js → interactions-writer-BZzUIgJd.js} +5 -2
- package/dist/interactions-writer-BZzUIgJd.js.map +1 -0
- package/dist/{interactions-writer-SLHnoEeE.js → interactions-writer-DbSyI2rt.js} +32 -3
- package/dist/interactions-writer-DbSyI2rt.js.map +1 -0
- package/dist/interactions-writer-RJB8SWf2.js +2 -0
- package/dist/{interactions-writer-CrPStUll.cjs → interactions-writer-a2yzBd7T.cjs} +5 -2
- package/dist/interactions-writer-a2yzBd7T.cjs.map +1 -0
- package/dist/json-store-WWsFzXub.js +43 -0
- package/dist/json-store-WWsFzXub.js.map +1 -0
- package/dist/{knowledge-base-D0Fh40kc.js → knowledge-base-DHNc4hVj.js} +43 -16
- package/dist/knowledge-base-DHNc4hVj.js.map +1 -0
- package/dist/{lancedb-CCBbpulq.js → lancedb-CswQEE5K.js} +1 -1
- package/dist/{lancedb-rlvWoPwl.js → lancedb-CuHKNsNZ.js} +4 -3
- package/dist/lancedb-CuHKNsNZ.js.map +1 -0
- package/dist/{lead-model-BCFzyktm.js → lead-model-CEmx7te7.js} +6 -14
- package/dist/lead-model-CEmx7te7.js.map +1 -0
- package/dist/{llm-Z8RIYkpF.js → llm-BnSUBisu.js} +2 -2
- package/dist/{llm-Z8RIYkpF.js.map → llm-BnSUBisu.js.map} +1 -1
- package/dist/{llm-iijeXmgq.cjs → llm-CXycmEl9.cjs} +2 -2
- package/dist/{llm-iijeXmgq.cjs.map → llm-CXycmEl9.cjs.map} +1 -1
- package/dist/{llm-DEjWcqmW.js → llm-DSX1-wFu.js} +1 -1
- package/dist/{llm-DvzZqva0.js → llm-PZzgPphl.js} +3 -3
- package/dist/{llm-DvzZqva0.js.map → llm-PZzgPphl.js.map} +1 -1
- package/dist/logger-BkInaGoV.cjs +167 -0
- package/dist/logger-BkInaGoV.cjs.map +1 -0
- package/dist/logger-Dyl4VcLO.js +147 -0
- package/dist/logger-Dyl4VcLO.js.map +1 -0
- package/dist/logger-UaF5p9d1.js +147 -0
- package/dist/logger-UaF5p9d1.js.map +1 -0
- package/dist/logger-vKQS34w9.js +2 -0
- package/dist/mcp-CdTJWTJf.d.cts.map +1 -1
- package/dist/mcp-CdTJWTJf.d.ts.map +1 -1
- package/dist/mcp.cjs +327 -303
- 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 +327 -303
- package/dist/mcp.js.map +1 -1
- package/dist/{memory-Cy6-Tbyl.js → memory-D8hmgD9d.js} +1 -1
- package/dist/{memory-Bb6ky3kb.js → memory-Dzr9dXSM.js} +4 -11
- package/dist/memory-Dzr9dXSM.js.map +1 -0
- package/dist/{microsoft-calendar-B6MMtUQK.js → microsoft-calendar-jIu9K5zX.js} +4 -4
- package/dist/{microsoft-calendar-B6MMtUQK.js.map → microsoft-calendar-jIu9K5zX.js.map} +1 -1
- package/dist/{microsoft-sync-CpZVoSuq.js → microsoft-sync-R_r8HL-B.js} +5 -5
- package/dist/{microsoft-sync-CpZVoSuq.js.map → microsoft-sync-R_r8HL-B.js.map} +1 -1
- package/dist/{nba-3wanmJ0U.js → nba-mTJ4yEqD.js} +3 -3
- package/dist/{nba-3wanmJ0U.js.map → nba-mTJ4yEqD.js.map} +1 -1
- package/dist/{notification-dispatcher-0vYNngWe.js → notification-dispatcher-inpKyuBz.js} +7 -3
- package/dist/notification-dispatcher-inpKyuBz.js.map +1 -0
- package/dist/{pipeline-writer-BqBrYrQc.js → pipeline-writer-0LJ6Qkat.js} +1 -1
- package/dist/{pipeline-writer-N2omexxp.cjs → pipeline-writer-B1tRAhuD.cjs} +11 -3
- package/dist/pipeline-writer-B1tRAhuD.cjs.map +1 -0
- package/dist/{pipeline-writer-BvVquKIe.js → pipeline-writer-CIllfnZl.js} +5 -3
- package/dist/pipeline-writer-CIllfnZl.js.map +1 -0
- package/dist/{pipeline-writer-eufx_0o1.js → pipeline-writer-rDj-ni6q.js} +6 -4
- package/dist/pipeline-writer-rDj-ni6q.js.map +1 -0
- package/dist/{proactive-agent-BgQXw3ac.js → proactive-agent-B7u3Bj_l.js} +6 -6
- package/dist/{proactive-agent-BgQXw3ac.js.map → proactive-agent-B7u3Bj_l.js.map} +1 -1
- package/dist/{proactive-worker-BrLHNhjH.js → proactive-worker-1zkm6aJD.js} +7 -8
- package/dist/proactive-worker-1zkm6aJD.js.map +1 -0
- package/dist/{push-manager-CowY-0IK.js → push-manager-BXM-IHfP.js} +1 -1
- package/dist/{push-manager-CdqIIkuh.js → push-manager-C0ECQgva.js} +4 -4
- package/dist/push-manager-C0ECQgva.js.map +1 -0
- package/dist/{quote-generator-OhSFsi3x.js → quote-generator-ByUyIYtw.js} +1 -1
- package/dist/{quote-generator-BfwENXzg.js → quote-generator-CTdR8eEI.js} +5 -5
- package/dist/quote-generator-CTdR8eEI.js.map +1 -0
- package/dist/rbac-DzbyFhVH.js +2 -0
- package/dist/{rbac-CTIktZaC.js → rbac-msmBc_tK.js} +19 -12
- package/dist/rbac-msmBc_tK.js.map +1 -0
- package/dist/regex-Jt5DatPi.js +13 -0
- package/dist/regex-Jt5DatPi.js.map +1 -0
- package/dist/{relationship-health-odxEoQdJ.js → relationship-health-ZZNXR1RZ.js} +8 -16
- package/dist/relationship-health-ZZNXR1RZ.js.map +1 -0
- package/dist/{revenue-simulation-Bqf2DLVB.js → revenue-simulation-D8f_YkUY.js} +9 -19
- package/dist/revenue-simulation-D8f_YkUY.js.map +1 -0
- package/dist/{revenue-simulation-BJdRTEHc.js → revenue-simulation-njJZlTqm.js} +1 -1
- package/dist/safe-path-mpp0dKtO.js +18 -0
- package/dist/safe-path-mpp0dKtO.js.map +1 -0
- package/dist/{segments-BqcD5HIl.js → segments-DI3LOQNe.js} +5 -14
- package/dist/segments-DI3LOQNe.js.map +1 -0
- package/dist/sequence-engine-C6nnewHX.js +2 -0
- package/dist/{sequence-engine-J1lTW_in.js → sequence-engine-DNTVLq7o.js} +15 -8
- package/dist/sequence-engine-DNTVLq7o.js.map +1 -0
- package/dist/{sequence-store-DaaWr0Os.js → sequence-store-CmYb6s0g.js} +6 -5
- package/dist/sequence-store-CmYb6s0g.js.map +1 -0
- package/dist/{server-Dyva03K8.js → server-DqSMYhSA.js} +278 -220
- package/dist/server-DqSMYhSA.js.map +1 -0
- package/dist/{session-D9ub6Wl1.js → session-B6XaP83h.js} +3 -3
- package/dist/session-B6XaP83h.js.map +1 -0
- package/dist/{session-B9AilxOE.js → session-BgGDyP2C.js} +3 -3
- package/dist/session-BgGDyP2C.js.map +1 -0
- package/dist/session-Bp4zTh4l.js +2 -0
- package/dist/{session-D0qFkBla.cjs → session-Mm7GQbSH.cjs} +3 -3
- package/dist/session-Mm7GQbSH.cjs.map +1 -0
- package/dist/{session-store-C8tEvMPw.js → session-store-DWxJ5Pof.js} +79 -17
- package/dist/session-store-DWxJ5Pof.js.map +1 -0
- package/dist/{session-store-B0QZE8Bx.cjs → session-store-yfwnj0OC.cjs} +126 -16
- package/dist/session-store-yfwnj0OC.cjs.map +1 -0
- package/dist/{sla-engine-5IhTsBUR.js → sla-engine-CP2KiKDS.js} +1 -1
- package/dist/{sla-engine-BqX-7u-7.js → sla-engine-O-A1ntu_.js} +2 -2
- package/dist/{sla-engine-BqX-7u-7.js.map → sla-engine-O-A1ntu_.js.map} +1 -1
- package/dist/{sop-Vp0UPWFW.js → sop-BV7ICAFR.js} +4 -11
- package/dist/sop-BV7ICAFR.js.map +1 -0
- package/dist/{sop-DkhVChGy.js → sop-D33qTHUb.js} +1 -1
- package/dist/survey-engine-DKctGcLQ.js +2 -0
- package/dist/{survey-engine-DBjCYqCv.js → survey-engine-DngXBv47.js} +5 -4
- package/dist/survey-engine-DngXBv47.js.map +1 -0
- package/dist/{sync-state-CwLSt_1m.js → sync-state-BaA8LbTI.js} +1 -1
- package/dist/{sync-state-ChaLbamC.js → sync-state-DMZgzpez.js} +4 -12
- package/dist/sync-state-DMZgzpez.js.map +1 -0
- package/dist/{ticket-writer-CjqKeIRD.js → ticket-writer-DsfpeLGZ.js} +1 -1
- package/dist/{ticket-writer-j2oX_Wal.js → ticket-writer-a9on36Wb.js} +12 -24
- package/dist/ticket-writer-a9on36Wb.js.map +1 -0
- package/dist/{tone-Bdm5uaht.js → tone-C7bqK69y.js} +5 -12
- package/dist/tone-C7bqK69y.js.map +1 -0
- package/dist/{tone-DRKlZgPr.cjs → tone-Cmc7O2Fx.cjs} +3 -9
- package/dist/tone-Cmc7O2Fx.cjs.map +1 -0
- package/dist/{tone-vNb2DAAD.js → tone-mXSftvTn.js} +3 -8
- package/dist/tone-mXSftvTn.js.map +1 -0
- package/dist/{transcript-watcher-CL2QUygI.js → transcript-watcher-0mh2ZhmH.js} +18 -11
- package/dist/transcript-watcher-0mh2ZhmH.js.map +1 -0
- package/dist/unmatched-transcripts-C92zAoM4.js +2 -0
- package/dist/unmatched-transcripts-DC-VQ9YS.js +16 -0
- package/dist/unmatched-transcripts-DC-VQ9YS.js.map +1 -0
- package/dist/update-deal-CWy1eLJI.js +2 -0
- package/dist/{update-deal-DKC79skb.js → update-deal-DSzr_Aau.js} +3 -3
- package/dist/{update-deal-DKC79skb.js.map → update-deal-DSzr_Aau.js.map} +1 -1
- package/dist/{usage-D0-TYJkw.js → usage-BVlFlKW_.js} +8 -6
- package/dist/usage-BVlFlKW_.js.map +1 -0
- package/dist/usage-CClTf5e6.cjs.map +1 -1
- package/dist/usage-D0u9a-lV.js.map +1 -1
- package/dist/{vault-DXCg29W-.js → vault-CfwZdNzC.js} +3 -4
- package/dist/vault-CfwZdNzC.js.map +1 -0
- package/dist/{vault-C1D3zScD.js → vault-DxKP4_R2.js} +1 -1
- package/dist/{webhooks-Xn6zO6kd.cjs → webhooks-CwW-3kvG.cjs} +5 -19
- package/dist/webhooks-CwW-3kvG.cjs.map +1 -0
- package/dist/{webhooks-7EpA05Qr.js → webhooks-DXr1IoKn.js} +8 -21
- package/dist/webhooks-DXr1IoKn.js.map +1 -0
- package/dist/{webhooks-BO2UAnmn.js → webhooks-sWZ8CJtR.js} +5 -18
- package/dist/webhooks-sWZ8CJtR.js.map +1 -0
- package/package.json +11 -2
- package/dist/approvals-DpjxGHFp.js.map +0 -1
- package/dist/auth-CyFuu9X_.js +0 -2
- package/dist/auth-DFWwWcYD.js.map +0 -1
- package/dist/backup-CeMk9z86.js.map +0 -1
- package/dist/backup-f_hC7rBV.js +0 -2
- package/dist/context-builder-BzWAp3Zs.js.map +0 -1
- package/dist/context-builder-DlrRcqmJ.js +0 -2
- package/dist/custom-fields-Pl2t9xzp.js.map +0 -1
- package/dist/custom-objects-BHgn1GEX.js.map +0 -1
- package/dist/customer-dir-DIylZ8Q6.js.map +0 -1
- package/dist/file-lock-B_zi7NQl.js.map +0 -1
- package/dist/gmail-sync-DIaxInDT.js.map +0 -1
- package/dist/gmail-sync-hHm9gaWd.cjs.map +0 -1
- package/dist/gmail-sync-rQaVqKWd.js.map +0 -1
- package/dist/goal-engine-KpBftn4V.js.map +0 -1
- package/dist/identity-gyfWdrcX.js +0 -2
- package/dist/import-hubspot-BaK71U_K.js.map +0 -1
- package/dist/interactions-writer-CrPStUll.cjs.map +0 -1
- package/dist/interactions-writer-DO3KcSR3.js.map +0 -1
- package/dist/interactions-writer-SLHnoEeE.js.map +0 -1
- package/dist/interactions-writer-dSPy1XfO.js +0 -2
- package/dist/knowledge-base-D0Fh40kc.js.map +0 -1
- package/dist/lancedb-rlvWoPwl.js.map +0 -1
- package/dist/lead-model-BCFzyktm.js.map +0 -1
- package/dist/memory-Bb6ky3kb.js.map +0 -1
- package/dist/notification-dispatcher-0vYNngWe.js.map +0 -1
- package/dist/pipeline-writer-BvVquKIe.js.map +0 -1
- package/dist/pipeline-writer-N2omexxp.cjs.map +0 -1
- package/dist/pipeline-writer-eufx_0o1.js.map +0 -1
- package/dist/proactive-worker-BrLHNhjH.js.map +0 -1
- package/dist/push-manager-CdqIIkuh.js.map +0 -1
- package/dist/quote-generator-BfwENXzg.js.map +0 -1
- package/dist/rbac-C7c8tcES.js +0 -2
- package/dist/rbac-CTIktZaC.js.map +0 -1
- package/dist/relationship-health-odxEoQdJ.js.map +0 -1
- package/dist/revenue-simulation-Bqf2DLVB.js.map +0 -1
- package/dist/segments-BqcD5HIl.js.map +0 -1
- package/dist/sequence-engine-CCTHEBgi.js +0 -2
- package/dist/sequence-engine-J1lTW_in.js.map +0 -1
- package/dist/sequence-store-DaaWr0Os.js.map +0 -1
- package/dist/server-Dyva03K8.js.map +0 -1
- package/dist/session-B9AilxOE.js.map +0 -1
- package/dist/session-D0qFkBla.cjs.map +0 -1
- package/dist/session-D9ub6Wl1.js.map +0 -1
- package/dist/session-mWHA71Lw.js +0 -2
- package/dist/session-store-B0QZE8Bx.cjs.map +0 -1
- package/dist/session-store-C8tEvMPw.js.map +0 -1
- package/dist/sop-Vp0UPWFW.js.map +0 -1
- package/dist/survey-engine-C06hcQt3.js +0 -2
- package/dist/survey-engine-DBjCYqCv.js.map +0 -1
- package/dist/sync-state-ChaLbamC.js.map +0 -1
- package/dist/ticket-writer-j2oX_Wal.js.map +0 -1
- package/dist/tone-Bdm5uaht.js.map +0 -1
- package/dist/tone-DRKlZgPr.cjs.map +0 -1
- package/dist/tone-vNb2DAAD.js.map +0 -1
- package/dist/transcript-watcher-CL2QUygI.js.map +0 -1
- package/dist/unmatched-transcripts-BsH5bhkU.js +0 -26
- package/dist/unmatched-transcripts-BsH5bhkU.js.map +0 -1
- package/dist/unmatched-transcripts-D0PrJ9iz.js +0 -2
- package/dist/update-deal-BNwPGaTV.js +0 -2
- package/dist/usage-D0-TYJkw.js.map +0 -1
- package/dist/vault-DXCg29W-.js.map +0 -1
- package/dist/webhooks-7EpA05Qr.js.map +0 -1
- package/dist/webhooks-BO2UAnmn.js.map +0 -1
- package/dist/webhooks-Xn6zO6kd.cjs.map +0 -1
package/dist/mcp.cjs
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("./chunk-DakpK96I.cjs");
|
|
3
|
-
const require_session_store = require("./session-store-
|
|
3
|
+
const require_session_store = require("./session-store-yfwnj0OC.cjs");
|
|
4
|
+
const require_atomic_write = require("./atomic-write-BYmF-ThH.cjs");
|
|
4
5
|
const require_write_queue = require("./write-queue-BDolUxfs.cjs");
|
|
5
|
-
const require_interactions_writer = require("./interactions-writer-
|
|
6
|
-
const
|
|
7
|
-
const
|
|
6
|
+
const require_interactions_writer = require("./interactions-writer-a2yzBd7T.cjs");
|
|
7
|
+
const require_logger = require("./logger-BkInaGoV.cjs");
|
|
8
|
+
const require_pipeline_writer = require("./pipeline-writer-B1tRAhuD.cjs");
|
|
9
|
+
const require_llm = require("./llm-CXycmEl9.cjs");
|
|
8
10
|
let path = require("path");
|
|
9
11
|
path = require_chunk.__toESM(path, 1);
|
|
10
12
|
let fs = require("fs");
|
|
@@ -63,11 +65,10 @@ async function readSubscriptions(dataDir) {
|
|
|
63
65
|
async function writeSubscriptions(dataDir, subs) {
|
|
64
66
|
const filePath = subscriptionsPath(dataDir);
|
|
65
67
|
fs.default.mkdirSync(path.default.dirname(filePath), { recursive: true });
|
|
66
|
-
|
|
68
|
+
require_session_store.writeJsonFile(filePath, {
|
|
67
69
|
subscriptions: subs,
|
|
68
70
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
69
|
-
};
|
|
70
|
-
fs.default.writeFileSync(filePath, JSON.stringify(file, null, 2), "utf-8");
|
|
71
|
+
});
|
|
71
72
|
}
|
|
72
73
|
function expiresAtForProvider(provider) {
|
|
73
74
|
if (provider === "gmail") return new Date(Date.now() + 10080 * 60 * 1e3).toISOString();
|
|
@@ -98,23 +99,15 @@ function getSyncStatePath(dataDir) {
|
|
|
98
99
|
return path.default.join(dataDir, ".agentic", "sync-state.json");
|
|
99
100
|
}
|
|
100
101
|
function readSyncState(dataDir) {
|
|
101
|
-
|
|
102
|
-
if (!fs.default.existsSync(filePath)) return {};
|
|
103
|
-
try {
|
|
104
|
-
return JSON.parse(fs.default.readFileSync(filePath, "utf-8"));
|
|
105
|
-
} catch {
|
|
106
|
-
return {};
|
|
107
|
-
}
|
|
102
|
+
return require_session_store.readJsonFile(getSyncStatePath(dataDir), {});
|
|
108
103
|
}
|
|
109
104
|
function updateSlugSyncState(dataDir, slug, update) {
|
|
110
|
-
const filePath = getSyncStatePath(dataDir);
|
|
111
|
-
fs.default.mkdirSync(path.default.dirname(filePath), { recursive: true });
|
|
112
105
|
const state = readSyncState(dataDir);
|
|
113
106
|
state[slug] = {
|
|
114
107
|
...state[slug],
|
|
115
108
|
...update
|
|
116
109
|
};
|
|
117
|
-
|
|
110
|
+
require_session_store.writeJsonFile(getSyncStatePath(dataDir), state);
|
|
118
111
|
}
|
|
119
112
|
function getLastGmailSync(dataDir, slug) {
|
|
120
113
|
const ts = readSyncState(dataDir)[slug]?.lastGmailSync;
|
|
@@ -456,6 +449,7 @@ Config: \`.agentic/rbac.json\` | Actor: \`DXCRM_ACTOR\` env var
|
|
|
456
449
|
| list_backups | List available backups with date, size, verification status, and customer count | any |
|
|
457
450
|
| trigger_sync | Force immediate Gmail sync for one or all customers | rep+ |
|
|
458
451
|
| get_audit_log | Read audit log — all write operations with actor, tool, customer | admin |
|
|
452
|
+
| get_logs | Query/aggregate the structured application log (level, component, errors) | admin |
|
|
459
453
|
| define_custom_object | Define a runtime custom object type with typed fields (no migration) | admin |
|
|
460
454
|
| create_record | Create a record of a custom object (validated against its schema) | rep+ |
|
|
461
455
|
| list_records | List records of a custom object | any |
|
|
@@ -1330,6 +1324,16 @@ function registerGetActiveSession(server) {
|
|
|
1330
1324
|
}, async () => handleGetActiveSession());
|
|
1331
1325
|
}
|
|
1332
1326
|
//#endregion
|
|
1327
|
+
//#region src/core/regex.ts
|
|
1328
|
+
/**
|
|
1329
|
+
* Escape a string so it can be embedded safely as a literal inside a `RegExp`.
|
|
1330
|
+
* Prevents both broken patterns and ReDoS/injection when interpolating
|
|
1331
|
+
* field names, section headers, or other dynamic values into a regex.
|
|
1332
|
+
*/
|
|
1333
|
+
function escapeRegExp(value) {
|
|
1334
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1335
|
+
}
|
|
1336
|
+
//#endregion
|
|
1333
1337
|
//#region src/core/context-builder.ts
|
|
1334
1338
|
var context_builder_exports = /* @__PURE__ */ require_chunk.__exportAll({ buildContext: () => buildContext });
|
|
1335
1339
|
const MAX_INTERACTIONS = 10;
|
|
@@ -1345,7 +1349,7 @@ function parsePipelineContent(filePath) {
|
|
|
1345
1349
|
return fs.default.readFileSync(filePath, "utf-8").trim();
|
|
1346
1350
|
}
|
|
1347
1351
|
function extractSection(content, sectionName) {
|
|
1348
|
-
const match = new RegExp(`## ${sectionName}([\\s\\S]*?)(?=^## |$)`, "m").exec(content);
|
|
1352
|
+
const match = new RegExp(`## ${escapeRegExp(sectionName)}([\\s\\S]*?)(?=^## |$)`, "m").exec(content);
|
|
1349
1353
|
return match ? (match[1] ?? "").trim() : "";
|
|
1350
1354
|
}
|
|
1351
1355
|
async function buildContext(dataDir, slug) {
|
|
@@ -1422,7 +1426,7 @@ async function buildContext(dataDir, slug) {
|
|
|
1422
1426
|
}
|
|
1423
1427
|
//#endregion
|
|
1424
1428
|
//#region src/mcp/tools/get-customer-context.ts
|
|
1425
|
-
const DATA_DIR$
|
|
1429
|
+
const DATA_DIR$52 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1426
1430
|
function triggerOnQuerySync(dataDir, slug) {
|
|
1427
1431
|
const auth = getGmailAuth();
|
|
1428
1432
|
if (!auth) return;
|
|
@@ -1435,7 +1439,7 @@ function triggerOnQuerySync(dataDir, slug) {
|
|
|
1435
1439
|
const sources = JSON.parse(fs.default.readFileSync(sourcesPath, "utf-8"));
|
|
1436
1440
|
if (!sources.gmail?.enabled || !sources.gmail.query) return;
|
|
1437
1441
|
const query = sources.gmail.query;
|
|
1438
|
-
Promise.resolve().then(() => require("./gmail-sync-
|
|
1442
|
+
Promise.resolve().then(() => require("./gmail-sync-GEy3oVvw.cjs")).then(({ syncGmail }) => syncGmail({
|
|
1439
1443
|
slug,
|
|
1440
1444
|
dataDir,
|
|
1441
1445
|
auth,
|
|
@@ -1443,7 +1447,7 @@ function triggerOnQuerySync(dataDir, slug) {
|
|
|
1443
1447
|
}).then(() => updateSlugSyncState(dataDir, slug, { lastGmailSync: (/* @__PURE__ */ new Date()).toISOString() })).catch(() => {})).catch(() => {});
|
|
1444
1448
|
} catch {}
|
|
1445
1449
|
}
|
|
1446
|
-
async function handleGetCustomerContext(input, dataDir = DATA_DIR$
|
|
1450
|
+
async function handleGetCustomerContext(input, dataDir = DATA_DIR$52) {
|
|
1447
1451
|
const targetSlug = input.slug ?? require_session_store.getSession()?.customerSlug;
|
|
1448
1452
|
if (!targetSlug) return {
|
|
1449
1453
|
content: [{
|
|
@@ -1559,7 +1563,7 @@ async function indexInLanceDB(dataDir, slug, text, sourceRef, meta) {
|
|
|
1559
1563
|
}]);
|
|
1560
1564
|
await table.mergeInsert("source_ref").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute(data);
|
|
1561
1565
|
} catch (err) {
|
|
1562
|
-
|
|
1566
|
+
require_logger.logger.error("lancedb", "indexInLanceDB failed", { error: err.message });
|
|
1563
1567
|
}
|
|
1564
1568
|
}
|
|
1565
1569
|
async function searchKnowledge(dataDir, slug, query, limit) {
|
|
@@ -1579,8 +1583,8 @@ async function searchKnowledge(dataDir, slug, query, limit) {
|
|
|
1579
1583
|
}
|
|
1580
1584
|
//#endregion
|
|
1581
1585
|
//#region src/mcp/tools/search-customer-knowledge.ts
|
|
1582
|
-
const DATA_DIR$
|
|
1583
|
-
async function handleSearchCustomerKnowledge(input, dataDir = DATA_DIR$
|
|
1586
|
+
const DATA_DIR$51 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1587
|
+
async function handleSearchCustomerKnowledge(input, dataDir = DATA_DIR$51) {
|
|
1584
1588
|
const limit = input.limit ?? 5;
|
|
1585
1589
|
try {
|
|
1586
1590
|
const results = await searchKnowledge(dataDir, input.slug, input.query, limit);
|
|
@@ -1628,14 +1632,14 @@ If no results: returns empty array with a helpful sync suggestion.`,
|
|
|
1628
1632
|
}
|
|
1629
1633
|
//#endregion
|
|
1630
1634
|
//#region src/mcp/tools/list-customers.ts
|
|
1631
|
-
const DATA_DIR$
|
|
1635
|
+
const DATA_DIR$50 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
1632
1636
|
function extractLastInteractionDate(interactionsPath) {
|
|
1633
1637
|
if (!fs.default.existsSync(interactionsPath)) return void 0;
|
|
1634
1638
|
const content = fs.default.readFileSync(interactionsPath, "utf-8");
|
|
1635
1639
|
const match = /^## (\d{4}-\d{2}-\d{2})/m.exec(content);
|
|
1636
1640
|
return match ? match[1] : void 0;
|
|
1637
1641
|
}
|
|
1638
|
-
async function handleListCustomers(input, dataDir = DATA_DIR$
|
|
1642
|
+
async function handleListCustomers(input, dataDir = DATA_DIR$50) {
|
|
1639
1643
|
const customersDir = path.default.join(dataDir, "customers");
|
|
1640
1644
|
const customers = [];
|
|
1641
1645
|
if (!fs.default.existsSync(customersDir)) return { content: [{
|
|
@@ -1643,6 +1647,7 @@ async function handleListCustomers(input, dataDir = DATA_DIR$49) {
|
|
|
1643
1647
|
text: JSON.stringify([], null, 2)
|
|
1644
1648
|
}] };
|
|
1645
1649
|
const entries = fs.default.readdirSync(customersDir);
|
|
1650
|
+
const canSee = require_session_store.customerVisibility(dataDir, process.env["DXCRM_ACTOR"] ?? "system");
|
|
1646
1651
|
for (const entry of entries) {
|
|
1647
1652
|
const customerDir = path.default.join(customersDir, entry);
|
|
1648
1653
|
try {
|
|
@@ -1669,7 +1674,7 @@ async function handleListCustomers(input, dataDir = DATA_DIR$49) {
|
|
|
1669
1674
|
const filterLower = input.filter.toLowerCase();
|
|
1670
1675
|
if (!(name.toLowerCase().includes(filterLower) || entry.toLowerCase().includes(filterLower) || stage.toLowerCase().includes(filterLower))) continue;
|
|
1671
1676
|
}
|
|
1672
|
-
if (!
|
|
1677
|
+
if (!canSee(entry)) continue;
|
|
1673
1678
|
customers.push(summary);
|
|
1674
1679
|
} catch {
|
|
1675
1680
|
continue;
|
|
@@ -1704,8 +1709,7 @@ async function withJsonFile(filePath, updater) {
|
|
|
1704
1709
|
current = null;
|
|
1705
1710
|
}
|
|
1706
1711
|
const next = await updater(current);
|
|
1707
|
-
|
|
1708
|
-
fs.default.writeFileSync(filePath, JSON.stringify(next, null, 2), "utf-8");
|
|
1712
|
+
require_atomic_write.writeFileAtomic(filePath, JSON.stringify(next, null, 2));
|
|
1709
1713
|
return next;
|
|
1710
1714
|
});
|
|
1711
1715
|
}
|
|
@@ -1729,7 +1733,7 @@ function readGraph(dataDir, slug) {
|
|
|
1729
1733
|
try {
|
|
1730
1734
|
return JSON.parse(fs.default.readFileSync(p, "utf-8"));
|
|
1731
1735
|
} catch {
|
|
1732
|
-
|
|
1736
|
+
require_logger.logger.warn("graph", "failed to parse graph file — returning empty graph", { path: p });
|
|
1733
1737
|
return emptyGraph(slug);
|
|
1734
1738
|
}
|
|
1735
1739
|
}
|
|
@@ -1982,23 +1986,13 @@ function healthPath(dataDir, slug) {
|
|
|
1982
1986
|
return path.default.join(dataDir, "customers", slug, "health.json");
|
|
1983
1987
|
}
|
|
1984
1988
|
function readHealth(dataDir, slug) {
|
|
1985
|
-
|
|
1986
|
-
if (!fs.default.existsSync(p)) return null;
|
|
1987
|
-
try {
|
|
1988
|
-
return JSON.parse(fs.default.readFileSync(p, "utf-8"));
|
|
1989
|
-
} catch {
|
|
1990
|
-
return null;
|
|
1991
|
-
}
|
|
1989
|
+
return require_session_store.readJsonFile(healthPath(dataDir, slug), null);
|
|
1992
1990
|
}
|
|
1993
1991
|
function writeHealth(dataDir, slug, health) {
|
|
1994
|
-
|
|
1995
|
-
const dir = path.default.dirname(p);
|
|
1996
|
-
if (!fs.default.existsSync(dir)) fs.default.mkdirSync(dir, { recursive: true });
|
|
1997
|
-
const updated = {
|
|
1992
|
+
require_session_store.writeJsonFile(healthPath(dataDir, slug), {
|
|
1998
1993
|
...health,
|
|
1999
1994
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2000
|
-
};
|
|
2001
|
-
fs.default.writeFileSync(p, JSON.stringify(updated, null, 2), "utf-8");
|
|
1995
|
+
});
|
|
2002
1996
|
}
|
|
2003
1997
|
function parseContactInteractions(content) {
|
|
2004
1998
|
const blocks = content.split(/(?=^## \d{4}-\d{2}-\d{2})/m).filter((b) => b.trim().length > 0);
|
|
@@ -2158,8 +2152,8 @@ async function updateHealthFromInteraction(dataDir, slug) {
|
|
|
2158
2152
|
}
|
|
2159
2153
|
//#endregion
|
|
2160
2154
|
//#region src/mcp/tools/log-interaction.ts
|
|
2161
|
-
const DATA_DIR$
|
|
2162
|
-
async function handleLogInteraction(input, dataDir = DATA_DIR$
|
|
2155
|
+
const DATA_DIR$49 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2156
|
+
async function handleLogInteraction(input, dataDir = DATA_DIR$49) {
|
|
2163
2157
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
2164
2158
|
const interactionDate = input.date ?? today;
|
|
2165
2159
|
const sourceRef = input.source ?? `agent://log/${Date.now()}`;
|
|
@@ -2189,7 +2183,7 @@ async function handleLogInteraction(input, dataDir = DATA_DIR$48) {
|
|
|
2189
2183
|
raw.data.last_touchpoint = interactionDate;
|
|
2190
2184
|
let serialized = gray_matter.default.stringify(raw.content, raw.data);
|
|
2191
2185
|
serialized = serialized.replace(/^(last_touchpoint:\s*)['"](\d{4}-\d{2}-\d{2})['"]/m, "$1$2");
|
|
2192
|
-
|
|
2186
|
+
require_atomic_write.writeFileAtomic(mainFactsPath, serialized);
|
|
2193
2187
|
} catch {}
|
|
2194
2188
|
require_session_store.writeAuditEntry(dataDir, {
|
|
2195
2189
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -2268,8 +2262,8 @@ var update_deal_exports = /* @__PURE__ */ require_chunk.__exportAll({
|
|
|
2268
2262
|
handleUpdateDeal: () => handleUpdateDeal,
|
|
2269
2263
|
registerUpdateDeal: () => registerUpdateDeal
|
|
2270
2264
|
});
|
|
2271
|
-
const DATA_DIR$
|
|
2272
|
-
async function handleUpdateDeal(input, dataDir = DATA_DIR$
|
|
2265
|
+
const DATA_DIR$48 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2266
|
+
async function handleUpdateDeal(input, dataDir = DATA_DIR$48) {
|
|
2273
2267
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
2274
2268
|
const deal = {
|
|
2275
2269
|
name: input.dealName,
|
|
@@ -2352,12 +2346,12 @@ Returns: { success: boolean, deal: object }`,
|
|
|
2352
2346
|
}
|
|
2353
2347
|
//#endregion
|
|
2354
2348
|
//#region src/mcp/tools/export-customer.ts
|
|
2355
|
-
const DATA_DIR$
|
|
2349
|
+
const DATA_DIR$47 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2356
2350
|
function countInteractions(content) {
|
|
2357
2351
|
const matches = content.match(/^## \d{4}-\d{2}-\d{2}/gm);
|
|
2358
2352
|
return matches ? matches.length : 0;
|
|
2359
2353
|
}
|
|
2360
|
-
async function handleExportCustomer(input, dataDir = DATA_DIR$
|
|
2354
|
+
async function handleExportCustomer(input, dataDir = DATA_DIR$47) {
|
|
2361
2355
|
require_session_store.enforceRbac(dataDir, "export_customer");
|
|
2362
2356
|
const customerDir = path.default.join(dataDir, "customers", input.slug);
|
|
2363
2357
|
if (!fs.default.existsSync(customerDir)) return {
|
|
@@ -2450,8 +2444,8 @@ Returns:
|
|
|
2450
2444
|
}
|
|
2451
2445
|
//#endregion
|
|
2452
2446
|
//#region src/mcp/tools/update-customer-facts.ts
|
|
2453
|
-
const DATA_DIR$
|
|
2454
|
-
async function handleUpdateCustomerFacts(input, dataDir = DATA_DIR$
|
|
2447
|
+
const DATA_DIR$46 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2448
|
+
async function handleUpdateCustomerFacts(input, dataDir = DATA_DIR$46) {
|
|
2455
2449
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2456
2450
|
try {
|
|
2457
2451
|
require_session_store.enforceRbac(dataDir, "update_customer_facts");
|
|
@@ -2601,10 +2595,36 @@ function scoreDeal(deal, signals) {
|
|
|
2601
2595
|
warnings
|
|
2602
2596
|
};
|
|
2603
2597
|
}
|
|
2598
|
+
const MS_PER_DAY = 864e5;
|
|
2599
|
+
/**
|
|
2600
|
+
* Derive activity/close timing for a deal relative to `todayDate`. Centralizes
|
|
2601
|
+
* the day-diff math that deal-room and deal-agent each computed identically.
|
|
2602
|
+
* A blank/whitespace close_date yields `undefined` (not a NaN day count).
|
|
2603
|
+
*/
|
|
2604
|
+
function deriveDealTiming(deal, todayDate) {
|
|
2605
|
+
const updatedDate = deal.updated ? new Date(deal.updated) : todayDate;
|
|
2606
|
+
const daysSinceLastActivity = Math.floor((todayDate.getTime() - updatedDate.getTime()) / MS_PER_DAY);
|
|
2607
|
+
const timing = {
|
|
2608
|
+
daysSinceLastActivity,
|
|
2609
|
+
daysInCurrentStage: daysSinceLastActivity
|
|
2610
|
+
};
|
|
2611
|
+
if (deal.close_date && deal.close_date.trim() !== "") timing.daysToClose = Math.floor((new Date(deal.close_date).getTime() - todayDate.getTime()) / MS_PER_DAY);
|
|
2612
|
+
return timing;
|
|
2613
|
+
}
|
|
2614
|
+
/** Score a deal using timing derived from `todayDate` plus the deal's probability. */
|
|
2615
|
+
function scoreDealForToday(deal, todayDate) {
|
|
2616
|
+
const timing = deriveDealTiming(deal, todayDate);
|
|
2617
|
+
return scoreDeal(deal, {
|
|
2618
|
+
daysSinceLastActivity: timing.daysSinceLastActivity,
|
|
2619
|
+
daysInCurrentStage: timing.daysInCurrentStage,
|
|
2620
|
+
...timing.daysToClose !== void 0 ? { daysToClose: timing.daysToClose } : {},
|
|
2621
|
+
...deal.probability !== void 0 ? { probability: deal.probability } : {}
|
|
2622
|
+
});
|
|
2623
|
+
}
|
|
2604
2624
|
//#endregion
|
|
2605
2625
|
//#region src/mcp/tools/get-deal-health.ts
|
|
2606
|
-
const DATA_DIR$
|
|
2607
|
-
async function handleGetDealHealth(input, dataDir = DATA_DIR$
|
|
2626
|
+
const DATA_DIR$45 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2627
|
+
async function handleGetDealHealth(input, dataDir = DATA_DIR$45) {
|
|
2608
2628
|
try {
|
|
2609
2629
|
const deals = await require_pipeline_writer.readPipeline(dataDir, input.slug);
|
|
2610
2630
|
const today = /* @__PURE__ */ new Date();
|
|
@@ -2653,28 +2673,13 @@ Returns: { slug, deals: [{ deal, stage, score, grade, signals, warnings }] }`,
|
|
|
2653
2673
|
}
|
|
2654
2674
|
//#endregion
|
|
2655
2675
|
//#region src/mcp/tools/get-pipeline-forecast.ts
|
|
2656
|
-
const DATA_DIR$
|
|
2657
|
-
async function handleGetPipelineForecast(input, dataDir = DATA_DIR$
|
|
2676
|
+
const DATA_DIR$44 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2677
|
+
async function handleGetPipelineForecast(input, dataDir = DATA_DIR$44) {
|
|
2658
2678
|
try {
|
|
2659
|
-
const
|
|
2660
|
-
if (!fs.default.existsSync(customersDir)) return { content: [{
|
|
2661
|
-
type: "text",
|
|
2662
|
-
text: JSON.stringify({
|
|
2663
|
-
deals: [],
|
|
2664
|
-
totalWeightedValue: 0,
|
|
2665
|
-
byStage: {}
|
|
2666
|
-
}, null, 2)
|
|
2667
|
-
}] };
|
|
2668
|
-
const slugs = fs.default.readdirSync(customersDir).filter((d) => {
|
|
2669
|
-
if (input.filter && !d.includes(input.filter)) return false;
|
|
2670
|
-
return fs.default.statSync(path.default.join(customersDir, d)).isDirectory();
|
|
2671
|
-
});
|
|
2679
|
+
const slugs = require_session_store.listCustomerSlugs(dataDir).filter((d) => !input.filter || d.includes(input.filter));
|
|
2672
2680
|
const allDeals = [];
|
|
2673
2681
|
for (const slug of slugs) {
|
|
2674
|
-
const
|
|
2675
|
-
if (!fs.default.existsSync(pipelinePath)) continue;
|
|
2676
|
-
const { readPipeline } = await Promise.resolve().then(() => require("./pipeline-writer-N2omexxp.cjs")).then((n) => n.pipeline_writer_exports);
|
|
2677
|
-
const deals = await readPipeline(dataDir, slug).catch(() => []);
|
|
2682
|
+
const deals = require_pipeline_writer.readPipelineSync(dataDir, slug);
|
|
2678
2683
|
for (const deal of deals) {
|
|
2679
2684
|
if (deal.stage === "won" || deal.stage === "lost") continue;
|
|
2680
2685
|
const prob = deal.probability ?? 50;
|
|
@@ -2730,13 +2735,13 @@ Returns: { deals: [...], totalWeightedValue: number, byStage: { stage: { count,
|
|
|
2730
2735
|
}
|
|
2731
2736
|
//#endregion
|
|
2732
2737
|
//#region src/mcp/tools/summarize-meeting.ts
|
|
2733
|
-
const DATA_DIR$
|
|
2734
|
-
async function handleSummarizeMeeting(input, dataDir = DATA_DIR$
|
|
2738
|
+
const DATA_DIR$43 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2739
|
+
async function handleSummarizeMeeting(input, dataDir = DATA_DIR$43) {
|
|
2735
2740
|
try {
|
|
2736
2741
|
let summary = input.transcript.slice(0, 400);
|
|
2737
2742
|
let nextSteps = [];
|
|
2738
2743
|
try {
|
|
2739
|
-
const { callLlm } = await Promise.resolve().then(() => require("./llm-
|
|
2744
|
+
const { callLlm } = await Promise.resolve().then(() => require("./llm-CXycmEl9.cjs")).then((n) => n.llm_exports);
|
|
2740
2745
|
const response = await callLlm(`Summarize this meeting transcript in 3-5 sentences and extract action items.\n\nTranscript:\n${input.transcript.slice(0, 3e3)}\n\nRespond as JSON: { "summary": "...", "nextSteps": ["..."] }`);
|
|
2741
2746
|
const parsed = JSON.parse(response);
|
|
2742
2747
|
summary = parsed.summary ?? summary;
|
|
@@ -2850,18 +2855,12 @@ function stagesPath(dataDir) {
|
|
|
2850
2855
|
return path.default.join(dataDir, ".agentic", "pipeline-stages.json");
|
|
2851
2856
|
}
|
|
2852
2857
|
function getPipelineStages(dataDir) {
|
|
2853
|
-
|
|
2854
|
-
if (!fs.default.existsSync(p)) return DEFAULT_STAGES;
|
|
2855
|
-
try {
|
|
2856
|
-
return JSON.parse(fs.default.readFileSync(p, "utf-8"));
|
|
2857
|
-
} catch {
|
|
2858
|
-
return DEFAULT_STAGES;
|
|
2859
|
-
}
|
|
2858
|
+
return require_session_store.readJsonFile(stagesPath(dataDir), DEFAULT_STAGES);
|
|
2860
2859
|
}
|
|
2861
2860
|
//#endregion
|
|
2862
2861
|
//#region src/mcp/tools/get-pipeline-stages.ts
|
|
2863
|
-
const DATA_DIR$
|
|
2864
|
-
async function handleGetPipelineStages(_input, dataDir = DATA_DIR$
|
|
2862
|
+
const DATA_DIR$42 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2863
|
+
async function handleGetPipelineStages(_input, dataDir = DATA_DIR$42) {
|
|
2865
2864
|
const stages = getPipelineStages(dataDir);
|
|
2866
2865
|
return { content: [{
|
|
2867
2866
|
type: "text",
|
|
@@ -2879,21 +2878,18 @@ function registerGetPipelineStages(server) {
|
|
|
2879
2878
|
//#region src/core/cross-customer.ts
|
|
2880
2879
|
async function searchAcrossCustomers(dataDir, query, limit = 5, excludeSlug) {
|
|
2881
2880
|
const slugs = require_session_store.listCustomerSlugs(dataDir).filter((d) => d !== excludeSlug);
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
const results = await searchKnowledge(dataDir, slug, query, 2);
|
|
2885
|
-
for (const r of results) allResults.push({
|
|
2881
|
+
return (await Promise.all(slugs.map(async (slug) => {
|
|
2882
|
+
return (await searchKnowledge(dataDir, slug, query, 2)).map((r) => ({
|
|
2886
2883
|
slug,
|
|
2887
2884
|
relevantContent: r.content.slice(0, 200),
|
|
2888
2885
|
score: r.score
|
|
2889
|
-
});
|
|
2890
|
-
}
|
|
2891
|
-
return allResults.sort((a, b) => b.score - a.score).slice(0, limit);
|
|
2886
|
+
}));
|
|
2887
|
+
}))).flat().sort((a, b) => b.score - a.score).slice(0, limit);
|
|
2892
2888
|
}
|
|
2893
2889
|
//#endregion
|
|
2894
2890
|
//#region src/mcp/tools/get-market-intelligence.ts
|
|
2895
|
-
const DATA_DIR$
|
|
2896
|
-
async function handleGetMarketIntelligence(input, dataDir = DATA_DIR$
|
|
2891
|
+
const DATA_DIR$41 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2892
|
+
async function handleGetMarketIntelligence(input, dataDir = DATA_DIR$41) {
|
|
2897
2893
|
const excludeSlug = input.excludeCurrentCustomer ? input.slug : void 0;
|
|
2898
2894
|
const all = require_session_store.listCustomerSlugs(dataDir);
|
|
2899
2895
|
const totalCustomersSearched = excludeSlug ? all.filter((s) => s !== excludeSlug).length : all.length;
|
|
@@ -2924,7 +2920,7 @@ function registerGetMarketIntelligence(server) {
|
|
|
2924
2920
|
}
|
|
2925
2921
|
//#endregion
|
|
2926
2922
|
//#region src/mcp/tools/get-relationship-graph.ts
|
|
2927
|
-
const DATA_DIR$
|
|
2923
|
+
const DATA_DIR$40 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
2928
2924
|
function summarizeNode(n) {
|
|
2929
2925
|
return {
|
|
2930
2926
|
id: n.id,
|
|
@@ -2932,7 +2928,7 @@ function summarizeNode(n) {
|
|
|
2932
2928
|
email: n.properties["email"]
|
|
2933
2929
|
};
|
|
2934
2930
|
}
|
|
2935
|
-
async function handleGetRelationshipGraph(input, dataDir = DATA_DIR$
|
|
2931
|
+
async function handleGetRelationshipGraph(input, dataDir = DATA_DIR$40) {
|
|
2936
2932
|
try {
|
|
2937
2933
|
const graph = readGraph(dataDir, input.slug);
|
|
2938
2934
|
const stakeholders = getStakeholders(graph);
|
|
@@ -3000,9 +2996,9 @@ Returns: {
|
|
|
3000
2996
|
}
|
|
3001
2997
|
//#endregion
|
|
3002
2998
|
//#region src/mcp/tools/get-relationship-health.ts
|
|
3003
|
-
const DATA_DIR$
|
|
2999
|
+
const DATA_DIR$39 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3004
3000
|
const MAX_HEALTH_AGE_MS = 3600 * 1e3;
|
|
3005
|
-
async function handleGetRelationshipHealth(input, dataDir = DATA_DIR$
|
|
3001
|
+
async function handleGetRelationshipHealth(input, dataDir = DATA_DIR$39) {
|
|
3006
3002
|
try {
|
|
3007
3003
|
let health = readHealth(dataDir, input.slug);
|
|
3008
3004
|
if (health === null || Date.now() - new Date(health.updatedAt).getTime() > MAX_HEALTH_AGE_MS) {
|
|
@@ -3082,8 +3078,7 @@ async function writePlaybook(dataDir, slug, playbook) {
|
|
|
3082
3078
|
const filePath = path.default.join(dir, `${playbook.name}.md`);
|
|
3083
3079
|
await require_write_queue.withFileQueue(filePath, async () => {
|
|
3084
3080
|
fs.default.mkdirSync(dir, { recursive: true });
|
|
3085
|
-
|
|
3086
|
-
fs.default.writeFileSync(filePath, raw, "utf-8");
|
|
3081
|
+
require_atomic_write.writeFileAtomic(filePath, gray_matter.default.stringify(playbook.content, playbook.frontmatter));
|
|
3087
3082
|
});
|
|
3088
3083
|
}
|
|
3089
3084
|
function toKebabCase(name) {
|
|
@@ -3285,11 +3280,10 @@ function writeAgentQueue(dataDir, slug, queue) {
|
|
|
3285
3280
|
const p = agentQueuePath(dataDir, slug);
|
|
3286
3281
|
const dir = path.default.dirname(p);
|
|
3287
3282
|
if (!fs.default.existsSync(dir)) fs.default.mkdirSync(dir, { recursive: true });
|
|
3288
|
-
|
|
3283
|
+
require_session_store.writeJsonFile(p, {
|
|
3289
3284
|
...queue,
|
|
3290
3285
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3291
|
-
};
|
|
3292
|
-
fs.default.writeFileSync(p, JSON.stringify(updated, null, 2), "utf-8");
|
|
3286
|
+
});
|
|
3293
3287
|
}
|
|
3294
3288
|
function makeActionId() {
|
|
3295
3289
|
return `da_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
@@ -3324,17 +3318,9 @@ async function observeDeal(dataDir, slug, dealName, today) {
|
|
|
3324
3318
|
const deal = (await require_pipeline_writer.readPipeline(dataDir, slug).catch(() => [])).find((d) => d.name.toLowerCase() === dealName.toLowerCase());
|
|
3325
3319
|
if (!deal) return null;
|
|
3326
3320
|
const todayDate = new Date(today);
|
|
3327
|
-
const
|
|
3328
|
-
const
|
|
3329
|
-
const
|
|
3330
|
-
const daysToClose = deal.close_date && deal.close_date.trim() !== "" ? Math.floor((new Date(deal.close_date).getTime() - todayDate.getTime()) / 864e5) : void 0;
|
|
3331
|
-
const dealHealthScore = scoreDeal(deal, {
|
|
3332
|
-
daysSinceLastActivity,
|
|
3333
|
-
daysInCurrentStage,
|
|
3334
|
-
...daysToClose !== void 0 ? { daysToClose } : {},
|
|
3335
|
-
...deal.probability !== void 0 ? { probability: deal.probability } : {}
|
|
3336
|
-
});
|
|
3337
|
-
const health = computeCustomerHealth(dataDir, slug, today);
|
|
3321
|
+
const { daysSinceLastActivity, daysInCurrentStage, daysToClose } = deriveDealTiming(deal, todayDate);
|
|
3322
|
+
const dealHealthScore = scoreDealForToday(deal, todayDate);
|
|
3323
|
+
const health = readHealth(dataDir, slug) ?? computeCustomerHealth(dataDir, slug, today);
|
|
3338
3324
|
const atRiskContacts = health.contacts.filter((c) => c.riskFlags.length > 0).map((c) => c.email ?? c.contactId);
|
|
3339
3325
|
const coldContacts = health.contacts.filter((c) => c.trend === "cold").map((c) => c.email ?? c.contactId);
|
|
3340
3326
|
const stakeholders = getStakeholders(readGraph(dataDir, slug));
|
|
@@ -3562,7 +3548,7 @@ async function executeAction(action, dataDir) {
|
|
|
3562
3548
|
if (!slug) return "skipped";
|
|
3563
3549
|
switch (action.type) {
|
|
3564
3550
|
case "log_interaction": {
|
|
3565
|
-
const { appendInteraction } = await Promise.resolve().then(() => require("./interactions-writer-
|
|
3551
|
+
const { appendInteraction } = await Promise.resolve().then(() => require("./interactions-writer-a2yzBd7T.cjs")).then((n) => n.interactions_writer_exports);
|
|
3566
3552
|
await appendInteraction(dataDir, slug, {
|
|
3567
3553
|
date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
3568
3554
|
type: action.payload["type"] ?? "Note",
|
|
@@ -3575,7 +3561,7 @@ async function executeAction(action, dataDir) {
|
|
|
3575
3561
|
return "executed";
|
|
3576
3562
|
}
|
|
3577
3563
|
case "schedule_meeting": {
|
|
3578
|
-
const { appendInteraction } = await Promise.resolve().then(() => require("./interactions-writer-
|
|
3564
|
+
const { appendInteraction } = await Promise.resolve().then(() => require("./interactions-writer-a2yzBd7T.cjs")).then((n) => n.interactions_writer_exports);
|
|
3579
3565
|
await appendInteraction(dataDir, slug, {
|
|
3580
3566
|
date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
3581
3567
|
type: "Note",
|
|
@@ -3681,8 +3667,8 @@ async function runDealAgent(config, dataDir, llmFn = require_llm.callLlm) {
|
|
|
3681
3667
|
}
|
|
3682
3668
|
//#endregion
|
|
3683
3669
|
//#region src/mcp/tools/run-deal-agent.ts
|
|
3684
|
-
const DATA_DIR$
|
|
3685
|
-
async function handleRunDealAgent(input, dataDir = DATA_DIR$
|
|
3670
|
+
const DATA_DIR$38 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3671
|
+
async function handleRunDealAgent(input, dataDir = DATA_DIR$38) {
|
|
3686
3672
|
try {
|
|
3687
3673
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
3688
3674
|
const result = await runDealAgent({
|
|
@@ -3749,8 +3735,8 @@ Returns: { assessment, riskLevel, plan[], actionsQueued[], actionsExecuted[], tr
|
|
|
3749
3735
|
}
|
|
3750
3736
|
//#endregion
|
|
3751
3737
|
//#region src/mcp/tools/approve-agent-action.ts
|
|
3752
|
-
const DATA_DIR$
|
|
3753
|
-
async function handleApproveAgentAction(input, dataDir = DATA_DIR$
|
|
3738
|
+
const DATA_DIR$37 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
3739
|
+
async function handleApproveAgentAction(input, dataDir = DATA_DIR$37) {
|
|
3754
3740
|
try {
|
|
3755
3741
|
const queue = readAgentQueue(dataDir, input.slug);
|
|
3756
3742
|
const idx = queue.pendingActions.findIndex((a) => a.actionId === input.actionId);
|
|
@@ -4010,8 +3996,8 @@ async function buildSimulationInput(dataDir, horizon, today, externalSignals = [
|
|
|
4010
3996
|
}
|
|
4011
3997
|
//#endregion
|
|
4012
3998
|
//#region src/mcp/tools/simulate-revenue.ts
|
|
4013
|
-
const DATA_DIR$
|
|
4014
|
-
async function handleSimulateRevenue(input, dataDir = DATA_DIR$
|
|
3999
|
+
const DATA_DIR$36 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
4000
|
+
async function handleSimulateRevenue(input, dataDir = DATA_DIR$36) {
|
|
4015
4001
|
try {
|
|
4016
4002
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
4017
4003
|
const horizon = input.horizon ?? "quarter";
|
|
@@ -4069,8 +4055,8 @@ Returns: { forecast: { p10, p50, p90, expected, stdDev, atRiskRevenue, byCloseMo
|
|
|
4069
4055
|
}
|
|
4070
4056
|
//#endregion
|
|
4071
4057
|
//#region src/mcp/tools/get-playbook.ts
|
|
4072
|
-
const DATA_DIR$
|
|
4073
|
-
async function handleGetPlaybook(input, dataDir = DATA_DIR$
|
|
4058
|
+
const DATA_DIR$35 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
4059
|
+
async function handleGetPlaybook(input, dataDir = DATA_DIR$35) {
|
|
4074
4060
|
try {
|
|
4075
4061
|
const playbooks = listPlaybooks(dataDir, input.slug);
|
|
4076
4062
|
if (!(input.stage !== void 0 || input.value !== void 0 || input.healthScore !== void 0)) return { content: [{
|
|
@@ -4155,12 +4141,12 @@ Returns: { matches: [{ name, score, trigger, successRate, usedCount, content }],
|
|
|
4155
4141
|
...healthScore !== void 0 ? { healthScore } : {},
|
|
4156
4142
|
...daysSinceContact !== void 0 ? { daysSinceContact } : {},
|
|
4157
4143
|
...championPresent !== void 0 ? { championPresent } : {}
|
|
4158
|
-
}, DATA_DIR$
|
|
4144
|
+
}, DATA_DIR$35));
|
|
4159
4145
|
}
|
|
4160
4146
|
//#endregion
|
|
4161
4147
|
//#region src/mcp/tools/create-playbook.ts
|
|
4162
|
-
const DATA_DIR$
|
|
4163
|
-
async function handleCreatePlaybook(input, dataDir = DATA_DIR$
|
|
4148
|
+
const DATA_DIR$34 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
4149
|
+
async function handleCreatePlaybook(input, dataDir = DATA_DIR$34) {
|
|
4164
4150
|
try {
|
|
4165
4151
|
const name = toKebabCase(input.name);
|
|
4166
4152
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -4233,12 +4219,12 @@ Returns: { success: true, playbook: { name, trigger, successRate, path } }`,
|
|
|
4233
4219
|
trigger,
|
|
4234
4220
|
content,
|
|
4235
4221
|
...successRate !== void 0 ? { successRate } : {}
|
|
4236
|
-
}, DATA_DIR$
|
|
4222
|
+
}, DATA_DIR$34));
|
|
4237
4223
|
}
|
|
4238
4224
|
//#endregion
|
|
4239
4225
|
//#region src/mcp/tools/list-playbooks.ts
|
|
4240
|
-
const DATA_DIR$
|
|
4241
|
-
async function handleListPlaybooks(input, dataDir = DATA_DIR$
|
|
4226
|
+
const DATA_DIR$33 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
4227
|
+
async function handleListPlaybooks(input, dataDir = DATA_DIR$33) {
|
|
4242
4228
|
try {
|
|
4243
4229
|
const playbooks = listPlaybooks(dataDir, input.slug);
|
|
4244
4230
|
return { content: [{
|
|
@@ -4277,12 +4263,12 @@ Args:
|
|
|
4277
4263
|
|
|
4278
4264
|
Returns: { playbooks: [{ name, trigger, successRate, usedCount, lastUpdated }], count, slug }`,
|
|
4279
4265
|
inputSchema: zod.z.object({ slug: zod.z.string().describe("Customer ID") })
|
|
4280
|
-
}, async ({ slug }) => handleListPlaybooks({ slug }, DATA_DIR$
|
|
4266
|
+
}, async ({ slug }) => handleListPlaybooks({ slug }, DATA_DIR$33));
|
|
4281
4267
|
}
|
|
4282
4268
|
//#endregion
|
|
4283
4269
|
//#region src/mcp/tools/distill-playbook.ts
|
|
4284
|
-
const DATA_DIR$
|
|
4285
|
-
async function handleDistillPlaybook(input, dataDir = DATA_DIR$
|
|
4270
|
+
const DATA_DIR$32 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
4271
|
+
async function handleDistillPlaybook(input, dataDir = DATA_DIR$32, llmFn = require_llm.callLlm) {
|
|
4286
4272
|
try {
|
|
4287
4273
|
const result = await distillPlaybook(dataDir, input.slug, input.dealName, input.outcome, llmFn);
|
|
4288
4274
|
if (!result.ok) {
|
|
@@ -4341,7 +4327,7 @@ Returns: { success: true, playbook: { name, trigger, successRate, path }, reason
|
|
|
4341
4327
|
slug,
|
|
4342
4328
|
dealName,
|
|
4343
4329
|
outcome
|
|
4344
|
-
}, DATA_DIR$
|
|
4330
|
+
}, DATA_DIR$32));
|
|
4345
4331
|
}
|
|
4346
4332
|
//#endregion
|
|
4347
4333
|
//#region src/core/goal-engine.ts
|
|
@@ -4559,8 +4545,8 @@ function getActiveGoals(dataDir) {
|
|
|
4559
4545
|
}
|
|
4560
4546
|
//#endregion
|
|
4561
4547
|
//#region src/mcp/tools/pursue-goal.ts
|
|
4562
|
-
const DATA_DIR$
|
|
4563
|
-
async function handlePursueGoal(input, dataDir = DATA_DIR$
|
|
4548
|
+
const DATA_DIR$31 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
4549
|
+
async function handlePursueGoal(input, dataDir = DATA_DIR$31, options = {}) {
|
|
4564
4550
|
try {
|
|
4565
4551
|
require_session_store.enforceRbac(dataDir, "pursue_goal");
|
|
4566
4552
|
const goal = await pursueGoal(dataDir, {
|
|
@@ -4623,12 +4609,12 @@ Returns: { goalId, description, target, deadline, decomposition: { analysis, cur
|
|
|
4623
4609
|
goal,
|
|
4624
4610
|
deadline,
|
|
4625
4611
|
...context !== void 0 ? { context } : {}
|
|
4626
|
-
}, DATA_DIR$
|
|
4612
|
+
}, DATA_DIR$31));
|
|
4627
4613
|
}
|
|
4628
4614
|
//#endregion
|
|
4629
4615
|
//#region src/mcp/tools/get-goal-status.ts
|
|
4630
|
-
const DATA_DIR$
|
|
4631
|
-
async function handleGetGoalStatus(input, dataDir = DATA_DIR$
|
|
4616
|
+
const DATA_DIR$30 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
4617
|
+
async function handleGetGoalStatus(input, dataDir = DATA_DIR$30) {
|
|
4632
4618
|
try {
|
|
4633
4619
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
4634
4620
|
const allGoals = input.goalId ? readGoals(dataDir).filter((g) => g.id === input.goalId) : getActiveGoals(dataDir);
|
|
@@ -4687,17 +4673,17 @@ Args:
|
|
|
4687
4673
|
|
|
4688
4674
|
Returns: { goals: [{ id, description, target, progress, status, deadline, daysRemaining, subGoals }], activeCount, completedCount }`,
|
|
4689
4675
|
inputSchema: zod.z.object({ goalId: zod.z.string().optional().describe("Specific goal ID (omit for all active goals)") })
|
|
4690
|
-
}, async ({ goalId }) => handleGetGoalStatus({ ...goalId !== void 0 ? { goalId } : {} }, DATA_DIR$
|
|
4676
|
+
}, async ({ goalId }) => handleGetGoalStatus({ ...goalId !== void 0 ? { goalId } : {} }, DATA_DIR$30));
|
|
4691
4677
|
}
|
|
4692
4678
|
//#endregion
|
|
4693
4679
|
//#region src/mcp/tools/register-push-subscription.ts
|
|
4694
|
-
const DATA_DIR$
|
|
4680
|
+
const DATA_DIR$29 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
4695
4681
|
const VALID_PROVIDERS = [
|
|
4696
4682
|
"gmail",
|
|
4697
4683
|
"microsoft-graph",
|
|
4698
4684
|
"slack"
|
|
4699
4685
|
];
|
|
4700
|
-
async function handleRegisterPushSubscription(input, dataDir = DATA_DIR$
|
|
4686
|
+
async function handleRegisterPushSubscription(input, dataDir = DATA_DIR$29) {
|
|
4701
4687
|
try {
|
|
4702
4688
|
if (!VALID_PROVIDERS.includes(input.provider)) return { content: [{
|
|
4703
4689
|
type: "text",
|
|
@@ -4783,12 +4769,12 @@ Returns: { subscriptionId, provider, slug, status, expiresAt, createdAt, warning
|
|
|
4783
4769
|
...microsoftResource !== void 0 ? { microsoftResource } : {},
|
|
4784
4770
|
...slackTeamId !== void 0 ? { slackTeamId } : {},
|
|
4785
4771
|
...slackChannelId !== void 0 ? { slackChannelId } : {}
|
|
4786
|
-
}, DATA_DIR$
|
|
4772
|
+
}, DATA_DIR$29));
|
|
4787
4773
|
}
|
|
4788
4774
|
//#endregion
|
|
4789
4775
|
//#region src/mcp/tools/get-push-status.ts
|
|
4790
|
-
const DATA_DIR$
|
|
4791
|
-
async function handleGetPushStatus(input, dataDir = DATA_DIR$
|
|
4776
|
+
const DATA_DIR$28 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
4777
|
+
async function handleGetPushStatus(input, dataDir = DATA_DIR$28) {
|
|
4792
4778
|
try {
|
|
4793
4779
|
let subs = await readSubscriptions(dataDir);
|
|
4794
4780
|
if (input.slug) subs = subs.filter((s) => s.slug === input.slug);
|
|
@@ -4860,7 +4846,7 @@ Returns: { subscriptions: [{ id, provider, slug, status, expiresAt, expiresInHou
|
|
|
4860
4846
|
}, async ({ slug, provider }) => handleGetPushStatus({
|
|
4861
4847
|
...slug !== void 0 ? { slug } : {},
|
|
4862
4848
|
...provider !== void 0 ? { provider } : {}
|
|
4863
|
-
}, DATA_DIR$
|
|
4849
|
+
}, DATA_DIR$28));
|
|
4864
4850
|
}
|
|
4865
4851
|
//#endregion
|
|
4866
4852
|
//#region src/core/org-intelligence.ts
|
|
@@ -4926,8 +4912,8 @@ function deriveRecommendation(people, missingRoles) {
|
|
|
4926
4912
|
}
|
|
4927
4913
|
//#endregion
|
|
4928
4914
|
//#region src/mcp/tools/get-org-intelligence.ts
|
|
4929
|
-
const DATA_DIR$
|
|
4930
|
-
async function handleGetOrgIntelligence(input, dataDir = DATA_DIR$
|
|
4915
|
+
const DATA_DIR$27 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
4916
|
+
async function handleGetOrgIntelligence(input, dataDir = DATA_DIR$27) {
|
|
4931
4917
|
try {
|
|
4932
4918
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
4933
4919
|
const map = buildStakeholderMap(dataDir, input.slug, today, input.dealName);
|
|
@@ -4978,15 +4964,7 @@ async function buildDealRoom(dataDir, slug, dealName, today) {
|
|
|
4978
4964
|
});
|
|
4979
4965
|
const todayDate = new Date(today);
|
|
4980
4966
|
const dealHealth = pipelineDeals.filter((d) => d.stage !== "won" && d.stage !== "lost").map((deal) => {
|
|
4981
|
-
const
|
|
4982
|
-
const daysSinceLastActivity = Math.floor((todayDate.getTime() - updatedDate.getTime()) / 864e5);
|
|
4983
|
-
const daysToClose = deal.close_date ? Math.floor((new Date(deal.close_date).getTime() - todayDate.getTime()) / 864e5) : void 0;
|
|
4984
|
-
const scored = scoreDeal(deal, {
|
|
4985
|
-
daysSinceLastActivity,
|
|
4986
|
-
daysInCurrentStage: daysSinceLastActivity,
|
|
4987
|
-
...daysToClose !== void 0 ? { daysToClose } : {},
|
|
4988
|
-
...deal.probability !== void 0 ? { probability: deal.probability } : {}
|
|
4989
|
-
});
|
|
4967
|
+
const scored = scoreDealForToday(deal, todayDate);
|
|
4990
4968
|
return {
|
|
4991
4969
|
deal: deal.name,
|
|
4992
4970
|
stage: deal.stage,
|
|
@@ -5068,8 +5046,8 @@ function buildExecutiveSummary(slug, dealName, stakeholders, overallHealth, sim,
|
|
|
5068
5046
|
}
|
|
5069
5047
|
//#endregion
|
|
5070
5048
|
//#region src/mcp/tools/open-deal-room.ts
|
|
5071
|
-
const DATA_DIR$
|
|
5072
|
-
async function handleOpenDealRoom(input, dataDir = DATA_DIR$
|
|
5049
|
+
const DATA_DIR$26 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
5050
|
+
async function handleOpenDealRoom(input, dataDir = DATA_DIR$26) {
|
|
5073
5051
|
try {
|
|
5074
5052
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
5075
5053
|
const brief = await buildDealRoom(dataDir, input.slug, input.dealName, today);
|
|
@@ -5152,8 +5130,8 @@ async function buildDailyBriefing(dataDir, today) {
|
|
|
5152
5130
|
}
|
|
5153
5131
|
//#endregion
|
|
5154
5132
|
//#region src/mcp/tools/get-proactive-briefing.ts
|
|
5155
|
-
const DATA_DIR$
|
|
5156
|
-
async function handleGetProactiveBriefing(input, dataDir = DATA_DIR$
|
|
5133
|
+
const DATA_DIR$25 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
5134
|
+
async function handleGetProactiveBriefing(input, dataDir = DATA_DIR$25) {
|
|
5157
5135
|
try {
|
|
5158
5136
|
const briefing = await buildDailyBriefing(dataDir, input.date ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10));
|
|
5159
5137
|
return { content: [{
|
|
@@ -5253,15 +5231,15 @@ function getTemplate(dataDir, id) {
|
|
|
5253
5231
|
}
|
|
5254
5232
|
//#endregion
|
|
5255
5233
|
//#region src/mcp/tools/list-email-templates.ts
|
|
5256
|
-
const DATA_DIR$
|
|
5257
|
-
async function handleListEmailTemplates(input, dataDir = DATA_DIR$
|
|
5234
|
+
const DATA_DIR$24 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
5235
|
+
async function handleListEmailTemplates(input, dataDir = DATA_DIR$24) {
|
|
5258
5236
|
const summary = listTemplates(dataDir, input.category ? { category: input.category } : {}).map(({ body: _body, ...meta }) => meta);
|
|
5259
5237
|
return { content: [{
|
|
5260
5238
|
type: "text",
|
|
5261
5239
|
text: JSON.stringify(summary, null, 2)
|
|
5262
5240
|
}] };
|
|
5263
5241
|
}
|
|
5264
|
-
function registerListEmailTemplates(server, dataDir = DATA_DIR$
|
|
5242
|
+
function registerListEmailTemplates(server, dataDir = DATA_DIR$24) {
|
|
5265
5243
|
server.registerTool("list_email_templates", {
|
|
5266
5244
|
description: "List available email templates. Optionally filter by category (e.g. 'outreach', 'followup', 'support').",
|
|
5267
5245
|
inputSchema: zod.z.object({ category: zod.z.string().optional().describe("Filter by category") })
|
|
@@ -5295,8 +5273,8 @@ async function buildVariablesFromCustomer(dataDir, slug) {
|
|
|
5295
5273
|
}
|
|
5296
5274
|
//#endregion
|
|
5297
5275
|
//#region src/mcp/tools/get-email-template.ts
|
|
5298
|
-
const DATA_DIR$
|
|
5299
|
-
async function handleGetEmailTemplate(input, dataDir = DATA_DIR$
|
|
5276
|
+
const DATA_DIR$23 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
5277
|
+
async function handleGetEmailTemplate(input, dataDir = DATA_DIR$23) {
|
|
5300
5278
|
const tmpl = getTemplate(dataDir, input.id);
|
|
5301
5279
|
if (!tmpl) return { content: [{
|
|
5302
5280
|
type: "text",
|
|
@@ -5312,7 +5290,7 @@ async function handleGetEmailTemplate(input, dataDir = DATA_DIR$22) {
|
|
|
5312
5290
|
}, null, 2)
|
|
5313
5291
|
}] };
|
|
5314
5292
|
}
|
|
5315
|
-
function registerGetEmailTemplate(server, dataDir = DATA_DIR$
|
|
5293
|
+
function registerGetEmailTemplate(server, dataDir = DATA_DIR$23) {
|
|
5316
5294
|
server.registerTool("get_email_template", {
|
|
5317
5295
|
description: "Get a specific email template by ID, including its body and detected variables.",
|
|
5318
5296
|
inputSchema: zod.z.object({ id: zod.z.string().describe("Template ID (e.g. 'enterprise-intro')") })
|
|
@@ -5320,8 +5298,8 @@ function registerGetEmailTemplate(server, dataDir = DATA_DIR$22) {
|
|
|
5320
5298
|
}
|
|
5321
5299
|
//#endregion
|
|
5322
5300
|
//#region src/mcp/tools/draft-email.ts
|
|
5323
|
-
const DATA_DIR$
|
|
5324
|
-
async function handleDraftEmail(input, dataDir = DATA_DIR$
|
|
5301
|
+
const DATA_DIR$22 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
5302
|
+
async function handleDraftEmail(input, dataDir = DATA_DIR$22) {
|
|
5325
5303
|
const tmpl = getTemplate(dataDir, input.templateId);
|
|
5326
5304
|
if (!tmpl) return { content: [{
|
|
5327
5305
|
type: "text",
|
|
@@ -5335,17 +5313,17 @@ async function handleDraftEmail(input, dataDir = DATA_DIR$21) {
|
|
|
5335
5313
|
const interpolatedBody = interpolate(tmpl.body, vars);
|
|
5336
5314
|
let effectiveTone = input.tone;
|
|
5337
5315
|
if (!effectiveTone) {
|
|
5338
|
-
const { resolveTone, toneInstruction } = await Promise.resolve().then(() => require("./tone-
|
|
5316
|
+
const { resolveTone, toneInstruction } = await Promise.resolve().then(() => require("./tone-Cmc7O2Fx.cjs"));
|
|
5339
5317
|
const instr = toneInstruction(resolveTone(dataDir, input.slug));
|
|
5340
5318
|
if (instr) effectiveTone = instr;
|
|
5341
5319
|
}
|
|
5342
5320
|
let body = interpolatedBody;
|
|
5343
5321
|
let polished = false;
|
|
5344
5322
|
if (effectiveTone) try {
|
|
5345
|
-
const { callLlm } = await Promise.resolve().then(() => require("./llm-
|
|
5323
|
+
const { callLlm } = await Promise.resolve().then(() => require("./llm-CXycmEl9.cjs")).then((n) => n.llm_exports);
|
|
5346
5324
|
const refined = await callLlm(`Rewrite the following email in a ${effectiveTone} tone. Keep the same language, preserve all names and facts, and do not invent details. Return ONLY the rewritten email body, no preamble.\n\n---\n${interpolatedBody}`);
|
|
5347
5325
|
if (refined && refined.trim()) {
|
|
5348
|
-
const { labelAiContent } = await Promise.resolve().then(() => require("./compliance-
|
|
5326
|
+
const { labelAiContent } = await Promise.resolve().then(() => require("./compliance-pAj9FcGI.cjs")).then((n) => n.compliance_exports);
|
|
5349
5327
|
body = labelAiContent(refined.trim());
|
|
5350
5328
|
polished = true;
|
|
5351
5329
|
}
|
|
@@ -5365,7 +5343,7 @@ async function handleDraftEmail(input, dataDir = DATA_DIR$21) {
|
|
|
5365
5343
|
}, null, 2)
|
|
5366
5344
|
}] };
|
|
5367
5345
|
}
|
|
5368
|
-
function registerDraftEmail(server, dataDir = DATA_DIR$
|
|
5346
|
+
function registerDraftEmail(server, dataDir = DATA_DIR$22) {
|
|
5369
5347
|
server.registerTool("draft_email", {
|
|
5370
5348
|
description: `Draft a personalized email for a customer using a stored template.
|
|
5371
5349
|
Variables are auto-filled from the customer's main_facts.md. Override any variable manually.
|
|
@@ -5473,8 +5451,8 @@ async function updateEnrollment(dataDir, id, updates) {
|
|
|
5473
5451
|
}
|
|
5474
5452
|
//#endregion
|
|
5475
5453
|
//#region src/mcp/tools/enroll-in-sequence.ts
|
|
5476
|
-
const DATA_DIR$
|
|
5477
|
-
async function handleEnrollInSequence(input, dataDir = DATA_DIR$
|
|
5454
|
+
const DATA_DIR$21 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
5455
|
+
async function handleEnrollInSequence(input, dataDir = DATA_DIR$21) {
|
|
5478
5456
|
const sequence = getSequence(dataDir, input.sequenceId);
|
|
5479
5457
|
if (!sequence) return { content: [{
|
|
5480
5458
|
type: "text",
|
|
@@ -5506,7 +5484,7 @@ async function handleEnrollInSequence(input, dataDir = DATA_DIR$20) {
|
|
|
5506
5484
|
})
|
|
5507
5485
|
}] };
|
|
5508
5486
|
}
|
|
5509
|
-
function registerEnrollInSequence(server, dataDir = DATA_DIR$
|
|
5487
|
+
function registerEnrollInSequence(server, dataDir = DATA_DIR$21) {
|
|
5510
5488
|
server.registerTool("enroll_in_sequence", {
|
|
5511
5489
|
description: `Enroll a contact in an email sequence. Validates that the sequence and its first template exist.
|
|
5512
5490
|
Returns: { enrollmentId, sequenceName, totalSteps }`,
|
|
@@ -5523,8 +5501,8 @@ Returns: { enrollmentId, sequenceName, totalSteps }`,
|
|
|
5523
5501
|
}
|
|
5524
5502
|
//#endregion
|
|
5525
5503
|
//#region src/mcp/tools/list-sequence-enrollments.ts
|
|
5526
|
-
const DATA_DIR$
|
|
5527
|
-
async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$
|
|
5504
|
+
const DATA_DIR$20 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
5505
|
+
async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$20) {
|
|
5528
5506
|
let enrollments = readEnrollments(dataDir);
|
|
5529
5507
|
if (input.slug !== void 0) enrollments = enrollments.filter((e) => e.slug === input.slug);
|
|
5530
5508
|
if (input.status !== void 0) enrollments = enrollments.filter((e) => e.status === input.status);
|
|
@@ -5533,7 +5511,7 @@ async function handleListSequenceEnrollments(input, dataDir = DATA_DIR$19) {
|
|
|
5533
5511
|
text: JSON.stringify({ enrollments }, null, 2)
|
|
5534
5512
|
}] };
|
|
5535
5513
|
}
|
|
5536
|
-
function registerListSequenceEnrollments(server, dataDir = DATA_DIR$
|
|
5514
|
+
function registerListSequenceEnrollments(server, dataDir = DATA_DIR$20) {
|
|
5537
5515
|
server.registerTool("list_sequence_enrollments", {
|
|
5538
5516
|
description: `List email sequence enrollments. Filter by customer slug or status.
|
|
5539
5517
|
Returns: { enrollments: SequenceEnrollment[] }`,
|
|
@@ -5552,8 +5530,8 @@ Returns: { enrollments: SequenceEnrollment[] }`,
|
|
|
5552
5530
|
}
|
|
5553
5531
|
//#endregion
|
|
5554
5532
|
//#region src/mcp/tools/unenroll-from-sequence.ts
|
|
5555
|
-
const DATA_DIR$
|
|
5556
|
-
async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$
|
|
5533
|
+
const DATA_DIR$19 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
5534
|
+
async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$19) {
|
|
5557
5535
|
if (!await updateEnrollment(dataDir, input.enrollmentId, { status: "paused" })) return { content: [{
|
|
5558
5536
|
type: "text",
|
|
5559
5537
|
text: JSON.stringify({
|
|
@@ -5566,7 +5544,7 @@ async function handleUnenrollFromSequence(input, dataDir = DATA_DIR$18) {
|
|
|
5566
5544
|
text: JSON.stringify({ success: true })
|
|
5567
5545
|
}] };
|
|
5568
5546
|
}
|
|
5569
|
-
function registerUnenrollFromSequence(server, dataDir = DATA_DIR$
|
|
5547
|
+
function registerUnenrollFromSequence(server, dataDir = DATA_DIR$19) {
|
|
5570
5548
|
server.registerTool("unenroll_from_sequence", {
|
|
5571
5549
|
description: `Unenroll (pause) a contact from an email sequence. Sets status to "paused" (soft delete).
|
|
5572
5550
|
Returns: { success: boolean }`,
|
|
@@ -5575,8 +5553,8 @@ Returns: { success: boolean }`,
|
|
|
5575
5553
|
}
|
|
5576
5554
|
//#endregion
|
|
5577
5555
|
//#region src/mcp/tools/list-sequences.ts
|
|
5578
|
-
const DATA_DIR$
|
|
5579
|
-
async function handleListSequences(_input, dataDir = DATA_DIR$
|
|
5556
|
+
const DATA_DIR$18 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
5557
|
+
async function handleListSequences(_input, dataDir = DATA_DIR$18) {
|
|
5580
5558
|
const sequences = listSequences(dataDir);
|
|
5581
5559
|
const enrollments = readEnrollments(dataDir);
|
|
5582
5560
|
const result = sequences.map((seq) => ({
|
|
@@ -5590,7 +5568,7 @@ async function handleListSequences(_input, dataDir = DATA_DIR$17) {
|
|
|
5590
5568
|
text: JSON.stringify({ sequences: result }, null, 2)
|
|
5591
5569
|
}] };
|
|
5592
5570
|
}
|
|
5593
|
-
function registerListSequences(server, dataDir = DATA_DIR$
|
|
5571
|
+
function registerListSequences(server, dataDir = DATA_DIR$18) {
|
|
5594
5572
|
server.registerTool("list_sequences", {
|
|
5595
5573
|
description: `List all email sequences with step count and enrollment count.
|
|
5596
5574
|
Returns: { sequences: Array<{ id, name, stepCount, enrollmentCount }> }`,
|
|
@@ -5640,7 +5618,7 @@ function buildHtml(quote, config, customerName) {
|
|
|
5640
5618
|
<p><strong>${config.companyName ?? ""}</strong><br>${config.companyAddress ?? ""}<br>${config.vatId ? `USt-IdNr.: ${config.vatId}` : ""}</p>
|
|
5641
5619
|
<hr>
|
|
5642
5620
|
<p><strong>An:</strong> ${customerName}</p>
|
|
5643
|
-
<p><strong>
|
|
5621
|
+
<p><strong>Date:</strong> ${quote.createdAt.slice(0, 10)} <strong>Valid until:</strong> ${quote.validUntil}</p>
|
|
5644
5622
|
<h2>Leistungen</h2>
|
|
5645
5623
|
<table>
|
|
5646
5624
|
<thead><tr><th>Beschreibung</th><th style="text-align:right">Menge</th><th style="text-align:right">Einzelpreis</th><th style="text-align:right">Gesamt</th></tr></thead>
|
|
@@ -5719,15 +5697,14 @@ async function generateQuote(dataDir, input) {
|
|
|
5719
5697
|
status: "draft",
|
|
5720
5698
|
htmlPath
|
|
5721
5699
|
};
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
fs.default.writeFileSync(htmlPath, html, "utf-8");
|
|
5700
|
+
require_atomic_write.writeFileAtomic(path.default.join(dir, `${quoteNumber}.json`), JSON.stringify(quote, null, 2));
|
|
5701
|
+
require_atomic_write.writeFileAtomic(htmlPath, buildHtml(quote, config, readCustomerName(dataDir, input.slug)));
|
|
5725
5702
|
return quote;
|
|
5726
5703
|
}
|
|
5727
5704
|
//#endregion
|
|
5728
5705
|
//#region src/mcp/tools/generate-quote.ts
|
|
5729
|
-
const DATA_DIR$
|
|
5730
|
-
async function handleGenerateQuote(input, dataDir = DATA_DIR$
|
|
5706
|
+
const DATA_DIR$17 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
5707
|
+
async function handleGenerateQuote(input, dataDir = DATA_DIR$17) {
|
|
5731
5708
|
try {
|
|
5732
5709
|
const quote = await generateQuote(dataDir, input);
|
|
5733
5710
|
return { content: [{
|
|
@@ -5751,7 +5728,7 @@ async function handleGenerateQuote(input, dataDir = DATA_DIR$16) {
|
|
|
5751
5728
|
}] };
|
|
5752
5729
|
}
|
|
5753
5730
|
}
|
|
5754
|
-
function registerGenerateQuote(server, dataDir = DATA_DIR$
|
|
5731
|
+
function registerGenerateQuote(server, dataDir = DATA_DIR$17) {
|
|
5755
5732
|
server.registerTool("generate_quote", {
|
|
5756
5733
|
description: `Generate a professional HTML quote/offer for a customer deal.
|
|
5757
5734
|
Calculates subtotal, VAT, and total. Saves JSON + HTML to .agentic/quotes/.
|
|
@@ -5779,8 +5756,8 @@ Returns: { quoteNumber, htmlPath, total, currency, validUntil }`,
|
|
|
5779
5756
|
}
|
|
5780
5757
|
//#endregion
|
|
5781
5758
|
//#region src/mcp/tools/get-quote-status.ts
|
|
5782
|
-
const DATA_DIR$
|
|
5783
|
-
async function handleGetQuoteStatus(input, dataDir = DATA_DIR$
|
|
5759
|
+
const DATA_DIR$16 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
5760
|
+
async function handleGetQuoteStatus(input, dataDir = DATA_DIR$16) {
|
|
5784
5761
|
if (input.quoteNumber) {
|
|
5785
5762
|
const quote = readQuote(dataDir, input.quoteNumber);
|
|
5786
5763
|
if (!quote) return { content: [{
|
|
@@ -5798,7 +5775,7 @@ async function handleGetQuoteStatus(input, dataDir = DATA_DIR$15) {
|
|
|
5798
5775
|
text: JSON.stringify({ quotes }, null, 2)
|
|
5799
5776
|
}] };
|
|
5800
5777
|
}
|
|
5801
|
-
function registerGetQuoteStatus(server, dataDir = DATA_DIR$
|
|
5778
|
+
function registerGetQuoteStatus(server, dataDir = DATA_DIR$16) {
|
|
5802
5779
|
server.registerTool("get_quote_status", {
|
|
5803
5780
|
description: `Get quote status and details. Filter by quoteNumber (single quote) or slug (all quotes for a customer).
|
|
5804
5781
|
Returns quote with status: draft | sent | viewed | accepted | declined`,
|
|
@@ -5813,7 +5790,7 @@ Returns quote with status: draft | sent | viewed | accepted | declined`,
|
|
|
5813
5790
|
}
|
|
5814
5791
|
//#endregion
|
|
5815
5792
|
//#region src/mcp/tools/get-booking-link.ts
|
|
5816
|
-
const DATA_DIR$
|
|
5793
|
+
const DATA_DIR$15 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
5817
5794
|
function loadCalendlyConfig(dataDir) {
|
|
5818
5795
|
const p = path.default.join(dataDir, ".agentic", "integrations", "calendly.yaml");
|
|
5819
5796
|
if (!fs.default.existsSync(p)) return {};
|
|
@@ -5836,7 +5813,7 @@ function readCustomerFacts(dataDir, slug) {
|
|
|
5836
5813
|
...email ? { email } : {}
|
|
5837
5814
|
};
|
|
5838
5815
|
}
|
|
5839
|
-
async function handleGetBookingLink(input, dataDir = DATA_DIR$
|
|
5816
|
+
async function handleGetBookingLink(input, dataDir = DATA_DIR$15) {
|
|
5840
5817
|
const config = loadCalendlyConfig(dataDir);
|
|
5841
5818
|
const apiKey = config.apiKey ?? process.env["CALENDLY_API_KEY"] ?? "";
|
|
5842
5819
|
if (!apiKey) return { content: [{
|
|
@@ -5864,7 +5841,7 @@ async function handleGetBookingLink(input, dataDir = DATA_DIR$14) {
|
|
|
5864
5841
|
}] };
|
|
5865
5842
|
}
|
|
5866
5843
|
}
|
|
5867
|
-
function registerGetBookingLink(server, dataDir = DATA_DIR$
|
|
5844
|
+
function registerGetBookingLink(server, dataDir = DATA_DIR$15) {
|
|
5868
5845
|
server.registerTool("get_booking_link", {
|
|
5869
5846
|
description: `Get a Calendly booking link for a customer. Optionally pre-fills the customer's name/email.
|
|
5870
5847
|
Requires CALENDLY_API_KEY env var or .agentic/integrations/calendly.yaml config.
|
|
@@ -5912,6 +5889,7 @@ const TICKET_HEADER = "# Tickets\n\n";
|
|
|
5912
5889
|
const TABLE_HEADER = `| ID | Title | Status | Priority | Assignee | Created | SLA Due | Resolved |
|
|
5913
5890
|
|----|-------|--------|----------|----------|---------|---------|---------|`;
|
|
5914
5891
|
function ticketsPath(dataDir, slug) {
|
|
5892
|
+
require_session_store.assertSafeSlug(slug);
|
|
5915
5893
|
return path.default.join(dataDir, "customers", slug, "tickets.md");
|
|
5916
5894
|
}
|
|
5917
5895
|
function escapeMd(s) {
|
|
@@ -5964,7 +5942,7 @@ async function upsertTicket(dataDir, slug, ticket) {
|
|
|
5964
5942
|
const idx = existing.findIndex((t) => t.id === ticket.id);
|
|
5965
5943
|
if (idx >= 0) existing[idx] = ticket;
|
|
5966
5944
|
else existing.push(ticket);
|
|
5967
|
-
|
|
5945
|
+
require_atomic_write.writeFileAtomic(p, serializeTickets(existing));
|
|
5968
5946
|
}
|
|
5969
5947
|
function nextTicketId(tickets) {
|
|
5970
5948
|
const nums = tickets.map((t) => parseInt(t.id.replace("T-", ""), 10)).filter((n) => !isNaN(n));
|
|
@@ -5972,28 +5950,13 @@ function nextTicketId(tickets) {
|
|
|
5972
5950
|
return `T-${String(max + 1).padStart(3, "0")}`;
|
|
5973
5951
|
}
|
|
5974
5952
|
async function listAllTickets(dataDir, filter) {
|
|
5975
|
-
const
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
}
|
|
5981
|
-
|
|
5982
|
-
}
|
|
5983
|
-
});
|
|
5984
|
-
const results = [];
|
|
5985
|
-
for (const slug of slugs) {
|
|
5986
|
-
const tickets = await readTickets(dataDir, slug);
|
|
5987
|
-
for (const ticket of tickets) {
|
|
5988
|
-
if (filter?.status && ticket.status !== filter.status) continue;
|
|
5989
|
-
if (filter?.priority && ticket.priority !== filter.priority) continue;
|
|
5990
|
-
if (filter?.assignee && ticket.assignee !== filter.assignee) continue;
|
|
5991
|
-
results.push({
|
|
5992
|
-
slug,
|
|
5993
|
-
ticket
|
|
5994
|
-
});
|
|
5995
|
-
}
|
|
5996
|
-
}
|
|
5953
|
+
const slugs = filter?.slug ? [filter.slug] : require_session_store.listCustomerSlugs(dataDir);
|
|
5954
|
+
const results = (await Promise.all(slugs.map(async (slug) => {
|
|
5955
|
+
return (await readTickets(dataDir, slug)).filter((ticket) => (!filter?.status || ticket.status === filter.status) && (!filter?.priority || ticket.priority === filter.priority) && (!filter?.assignee || ticket.assignee === filter.assignee)).map((ticket) => ({
|
|
5956
|
+
slug,
|
|
5957
|
+
ticket
|
|
5958
|
+
}));
|
|
5959
|
+
}))).flat();
|
|
5997
5960
|
const priorityOrder = {
|
|
5998
5961
|
urgent: 0,
|
|
5999
5962
|
high: 1,
|
|
@@ -6048,8 +6011,8 @@ function calcSlaDue(createdDate, priority, rules) {
|
|
|
6048
6011
|
}
|
|
6049
6012
|
//#endregion
|
|
6050
6013
|
//#region src/mcp/tools/create-ticket.ts
|
|
6051
|
-
const DATA_DIR$
|
|
6052
|
-
async function handleCreateTicket(input, dataDir = DATA_DIR$
|
|
6014
|
+
const DATA_DIR$14 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
6015
|
+
async function handleCreateTicket(input, dataDir = DATA_DIR$14) {
|
|
6053
6016
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
6054
6017
|
const rules = loadSlaRules(dataDir);
|
|
6055
6018
|
const priority = input.priority ?? "normal";
|
|
@@ -6071,7 +6034,7 @@ async function handleCreateTicket(input, dataDir = DATA_DIR$13) {
|
|
|
6071
6034
|
text: JSON.stringify({ ticket }, null, 2)
|
|
6072
6035
|
}] };
|
|
6073
6036
|
}
|
|
6074
|
-
function registerCreateTicket(server, dataDir = DATA_DIR$
|
|
6037
|
+
function registerCreateTicket(server, dataDir = DATA_DIR$14) {
|
|
6075
6038
|
server.registerTool("create_ticket", {
|
|
6076
6039
|
description: `Create a support ticket for a customer. Auto-calculates SLA due date based on priority.
|
|
6077
6040
|
Returns: { ticket } with id T-NNN, status=open, slaDue`,
|
|
@@ -6097,8 +6060,8 @@ Returns: { ticket } with id T-NNN, status=open, slaDue`,
|
|
|
6097
6060
|
}
|
|
6098
6061
|
//#endregion
|
|
6099
6062
|
//#region src/mcp/tools/update-ticket.ts
|
|
6100
|
-
const DATA_DIR$
|
|
6101
|
-
async function handleUpdateTicket(input, dataDir = DATA_DIR$
|
|
6063
|
+
const DATA_DIR$13 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
6064
|
+
async function handleUpdateTicket(input, dataDir = DATA_DIR$13) {
|
|
6102
6065
|
const ticket = (await readTickets(dataDir, input.slug)).find((t) => t.id === input.ticketId);
|
|
6103
6066
|
if (!ticket) return { content: [{
|
|
6104
6067
|
type: "text",
|
|
@@ -6117,7 +6080,7 @@ async function handleUpdateTicket(input, dataDir = DATA_DIR$12) {
|
|
|
6117
6080
|
text: JSON.stringify({ ticket: updated }, null, 2)
|
|
6118
6081
|
}] };
|
|
6119
6082
|
}
|
|
6120
|
-
function registerUpdateTicket(server, dataDir = DATA_DIR$
|
|
6083
|
+
function registerUpdateTicket(server, dataDir = DATA_DIR$13) {
|
|
6121
6084
|
server.registerTool("update_ticket", {
|
|
6122
6085
|
description: `Update a ticket's status or assignee. Setting status=resolved auto-sets resolved date.
|
|
6123
6086
|
Returns: { ticket }`,
|
|
@@ -6142,8 +6105,8 @@ Returns: { ticket }`,
|
|
|
6142
6105
|
}
|
|
6143
6106
|
//#endregion
|
|
6144
6107
|
//#region src/mcp/tools/list-tickets.ts
|
|
6145
|
-
const DATA_DIR$
|
|
6146
|
-
async function handleListTickets(input, dataDir = DATA_DIR$
|
|
6108
|
+
const DATA_DIR$12 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
6109
|
+
async function handleListTickets(input, dataDir = DATA_DIR$12) {
|
|
6147
6110
|
const results = await listAllTickets(dataDir, {
|
|
6148
6111
|
...input.slug !== void 0 ? { slug: input.slug } : {},
|
|
6149
6112
|
...input.status !== void 0 ? { status: input.status } : {},
|
|
@@ -6155,7 +6118,7 @@ async function handleListTickets(input, dataDir = DATA_DIR$11) {
|
|
|
6155
6118
|
text: JSON.stringify({ tickets: results }, null, 2)
|
|
6156
6119
|
}] };
|
|
6157
6120
|
}
|
|
6158
|
-
function registerListTickets(server, dataDir = DATA_DIR$
|
|
6121
|
+
function registerListTickets(server, dataDir = DATA_DIR$12) {
|
|
6159
6122
|
server.registerTool("list_tickets", {
|
|
6160
6123
|
description: `List support tickets. Filter by customer, status, priority, or assignee. Sorted by priority then date.
|
|
6161
6124
|
Returns: { tickets: Array<{ slug, ticket }> }`,
|
|
@@ -6185,8 +6148,8 @@ Returns: { tickets: Array<{ slug, ticket }> }`,
|
|
|
6185
6148
|
}
|
|
6186
6149
|
//#endregion
|
|
6187
6150
|
//#region src/mcp/tools/close-ticket.ts
|
|
6188
|
-
const DATA_DIR$
|
|
6189
|
-
async function handleCloseTicket(input, dataDir = DATA_DIR$
|
|
6151
|
+
const DATA_DIR$11 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
6152
|
+
async function handleCloseTicket(input, dataDir = DATA_DIR$11) {
|
|
6190
6153
|
const ticket = (await readTickets(dataDir, input.slug)).find((t) => t.id === input.ticketId);
|
|
6191
6154
|
if (!ticket) return { content: [{
|
|
6192
6155
|
type: "text",
|
|
@@ -6213,7 +6176,7 @@ async function handleCloseTicket(input, dataDir = DATA_DIR$10) {
|
|
|
6213
6176
|
text: JSON.stringify({ ticket: updated }, null, 2)
|
|
6214
6177
|
}] };
|
|
6215
6178
|
}
|
|
6216
|
-
function registerCloseTicket(server, dataDir = DATA_DIR$
|
|
6179
|
+
function registerCloseTicket(server, dataDir = DATA_DIR$11) {
|
|
6217
6180
|
server.registerTool("close_ticket", {
|
|
6218
6181
|
description: `Close a support ticket. Optionally logs the resolution as an interaction.
|
|
6219
6182
|
Returns: { ticket } with status=closed`,
|
|
@@ -6323,7 +6286,7 @@ async function recordSurveyResponse(dataDir, token, score, comment) {
|
|
|
6323
6286
|
const dir = responsesDir(dataDir, pending.surveyId);
|
|
6324
6287
|
fs.default.mkdirSync(dir, { recursive: true });
|
|
6325
6288
|
const filename = `${pending.slug}_${pending.contactEmail.replace("@", "_at_")}_${Date.now()}.json`;
|
|
6326
|
-
|
|
6289
|
+
require_atomic_write.writeFileAtomic(path.default.join(dir, filename), JSON.stringify(response, null, 2));
|
|
6327
6290
|
fs.default.unlinkSync(path.default.join(pendingDir, file));
|
|
6328
6291
|
return response;
|
|
6329
6292
|
} catch {
|
|
@@ -6363,12 +6326,12 @@ async function savePendingSurvey(dataDir, surveyId, slug, contactEmail, token) {
|
|
|
6363
6326
|
contactEmail,
|
|
6364
6327
|
sentAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6365
6328
|
};
|
|
6366
|
-
|
|
6329
|
+
require_atomic_write.writeFileAtomic(path.default.join(pendingDir, filename), JSON.stringify(pending, null, 2));
|
|
6367
6330
|
}
|
|
6368
6331
|
//#endregion
|
|
6369
6332
|
//#region src/mcp/tools/send-nps-survey.ts
|
|
6370
|
-
const DATA_DIR$
|
|
6371
|
-
async function handleSendNpsSurvey(input, dataDir = DATA_DIR$
|
|
6333
|
+
const DATA_DIR$10 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
6334
|
+
async function handleSendNpsSurvey(input, dataDir = DATA_DIR$10) {
|
|
6372
6335
|
const survey = getSurvey(dataDir, input.surveyId);
|
|
6373
6336
|
if (!survey) return { content: [{
|
|
6374
6337
|
type: "text",
|
|
@@ -6389,7 +6352,7 @@ async function handleSendNpsSurvey(input, dataDir = DATA_DIR$9) {
|
|
|
6389
6352
|
}, null, 2)
|
|
6390
6353
|
}] };
|
|
6391
6354
|
}
|
|
6392
|
-
function registerSendNpsSurvey(server, dataDir = DATA_DIR$
|
|
6355
|
+
function registerSendNpsSurvey(server, dataDir = DATA_DIR$10) {
|
|
6393
6356
|
server.registerTool("send_nps_survey", {
|
|
6394
6357
|
description: `Generate an NPS/CSAT survey email for a customer contact. Returns subject, HTML body, and a token-based response URL.
|
|
6395
6358
|
Does NOT send automatically — returns draft for review.
|
|
@@ -6409,8 +6372,8 @@ Returns: { token, subject, body, surveyUrl }`,
|
|
|
6409
6372
|
}
|
|
6410
6373
|
//#endregion
|
|
6411
6374
|
//#region src/mcp/tools/get-survey-results.ts
|
|
6412
|
-
const DATA_DIR$
|
|
6413
|
-
async function handleGetSurveyResults(input, dataDir = DATA_DIR$
|
|
6375
|
+
const DATA_DIR$9 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
6376
|
+
async function handleGetSurveyResults(input, dataDir = DATA_DIR$9) {
|
|
6414
6377
|
const responses = loadSurveyResponses(dataDir, input.surveyId, input.slug);
|
|
6415
6378
|
const nps = calcNpsScore(responses);
|
|
6416
6379
|
const promoters = responses.filter((r) => r.score >= 9).length;
|
|
@@ -6436,7 +6399,7 @@ async function handleGetSurveyResults(input, dataDir = DATA_DIR$8) {
|
|
|
6436
6399
|
}, null, 2)
|
|
6437
6400
|
}] };
|
|
6438
6401
|
}
|
|
6439
|
-
function registerGetSurveyResults(server, dataDir = DATA_DIR$
|
|
6402
|
+
function registerGetSurveyResults(server, dataDir = DATA_DIR$9) {
|
|
6440
6403
|
server.registerTool("get_survey_results", {
|
|
6441
6404
|
description: `Get NPS/CSAT survey results with score breakdown. Calculates Net Promoter Score.
|
|
6442
6405
|
Returns: { npsScore, totalResponses, promoters, passives, detractors, responses[] }`,
|
|
@@ -6466,18 +6429,21 @@ const KbArticleSchema = zod.z.object({
|
|
|
6466
6429
|
function kbDir(dataDir) {
|
|
6467
6430
|
return path.default.join(dataDir, ".agentic", "knowledge-base");
|
|
6468
6431
|
}
|
|
6469
|
-
|
|
6470
|
-
|
|
6432
|
+
/** Category subdirectories of the knowledge base. */
|
|
6433
|
+
function kbCategories(dir) {
|
|
6471
6434
|
if (!fs.default.existsSync(dir)) return [];
|
|
6472
|
-
|
|
6473
|
-
const categories = fs.default.readdirSync(dir).filter((f) => {
|
|
6435
|
+
return fs.default.readdirSync(dir).filter((f) => {
|
|
6474
6436
|
try {
|
|
6475
6437
|
return fs.default.statSync(path.default.join(dir, f)).isDirectory();
|
|
6476
6438
|
} catch {
|
|
6477
6439
|
return false;
|
|
6478
6440
|
}
|
|
6479
6441
|
});
|
|
6480
|
-
|
|
6442
|
+
}
|
|
6443
|
+
function listKbArticles(dataDir, opts) {
|
|
6444
|
+
const dir = kbDir(dataDir);
|
|
6445
|
+
const results = [];
|
|
6446
|
+
for (const cat of kbCategories(dir)) {
|
|
6481
6447
|
const catDir = path.default.join(dir, cat);
|
|
6482
6448
|
const files = fs.default.readdirSync(catDir).filter((f) => f.endsWith(".md"));
|
|
6483
6449
|
for (const file of files) try {
|
|
@@ -6497,14 +6463,31 @@ function listKbArticles(dataDir, opts) {
|
|
|
6497
6463
|
return results;
|
|
6498
6464
|
}
|
|
6499
6465
|
function getKbArticle(dataDir, id) {
|
|
6500
|
-
|
|
6466
|
+
if (!require_session_store.isSafePathSegment(id)) return null;
|
|
6467
|
+
const dir = kbDir(dataDir);
|
|
6468
|
+
for (const cat of kbCategories(dir)) {
|
|
6469
|
+
const filePath = path.default.join(dir, cat, `${id}.md`);
|
|
6470
|
+
if (!fs.default.existsSync(filePath)) continue;
|
|
6471
|
+
try {
|
|
6472
|
+
const parsed = (0, gray_matter.default)(fs.default.readFileSync(filePath, "utf-8"));
|
|
6473
|
+
const meta = KbArticleSchema.safeParse(parsed.data);
|
|
6474
|
+
if (!meta.success) return null;
|
|
6475
|
+
return {
|
|
6476
|
+
...meta.data,
|
|
6477
|
+
body: parsed.content.trim()
|
|
6478
|
+
};
|
|
6479
|
+
} catch {
|
|
6480
|
+
return null;
|
|
6481
|
+
}
|
|
6482
|
+
}
|
|
6483
|
+
return null;
|
|
6501
6484
|
}
|
|
6502
6485
|
function writeKbArticle(dataDir, article) {
|
|
6503
|
-
|
|
6504
|
-
|
|
6486
|
+
require_session_store.assertSafePathSegment(article.category, "knowledge-base category");
|
|
6487
|
+
require_session_store.assertSafePathSegment(article.id, "knowledge-base article id");
|
|
6505
6488
|
const { body, ...meta } = article;
|
|
6506
6489
|
const content = gray_matter.default.stringify(body, meta);
|
|
6507
|
-
|
|
6490
|
+
require_atomic_write.writeFileAtomic(path.default.join(kbDir(dataDir), article.category, `${article.id}.md`), content);
|
|
6508
6491
|
}
|
|
6509
6492
|
function searchKbSimple(dataDir, query, opts) {
|
|
6510
6493
|
const all = listKbArticles(dataDir, opts?.publicOnly ? { publicOnly: true } : {});
|
|
@@ -6517,8 +6500,8 @@ function getKbMetaForExport(article) {
|
|
|
6517
6500
|
}
|
|
6518
6501
|
//#endregion
|
|
6519
6502
|
//#region src/mcp/tools/search-knowledge-base.ts
|
|
6520
|
-
const DATA_DIR$
|
|
6521
|
-
async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$
|
|
6503
|
+
const DATA_DIR$8 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
6504
|
+
async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$8) {
|
|
6522
6505
|
const results = searchKbSimple(dataDir, input.query, { ...input.publicOnly ? { publicOnly: true } : {} });
|
|
6523
6506
|
const limited = (input.category ? results.filter((a) => a.category === input.category) : results).slice(0, input.limit ?? 10);
|
|
6524
6507
|
return { content: [{
|
|
@@ -6533,7 +6516,7 @@ async function handleSearchKnowledgeBase(input, dataDir = DATA_DIR$7) {
|
|
|
6533
6516
|
}, null, 2)
|
|
6534
6517
|
}] };
|
|
6535
6518
|
}
|
|
6536
|
-
function registerSearchKnowledgeBase(server, dataDir = DATA_DIR$
|
|
6519
|
+
function registerSearchKnowledgeBase(server, dataDir = DATA_DIR$8) {
|
|
6537
6520
|
server.registerTool("search_knowledge_base", {
|
|
6538
6521
|
description: `Search the knowledge base for articles. Text search on title, body, and tags.
|
|
6539
6522
|
Returns: { count, articles[] } with excerpts`,
|
|
@@ -6552,8 +6535,8 @@ Returns: { count, articles[] } with excerpts`,
|
|
|
6552
6535
|
}
|
|
6553
6536
|
//#endregion
|
|
6554
6537
|
//#region src/mcp/tools/create-kb-article.ts
|
|
6555
|
-
const DATA_DIR$
|
|
6556
|
-
async function handleCreateKbArticle(input, dataDir = DATA_DIR$
|
|
6538
|
+
const DATA_DIR$7 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
6539
|
+
async function handleCreateKbArticle(input, dataDir = DATA_DIR$7) {
|
|
6557
6540
|
if (getKbArticle(dataDir, input.id)) return { content: [{
|
|
6558
6541
|
type: "text",
|
|
6559
6542
|
text: JSON.stringify({ error: `Article '${input.id}' already exists` })
|
|
@@ -6581,7 +6564,7 @@ async function handleCreateKbArticle(input, dataDir = DATA_DIR$6) {
|
|
|
6581
6564
|
}, null, 2)
|
|
6582
6565
|
}] };
|
|
6583
6566
|
}
|
|
6584
|
-
function registerCreateKbArticle(server, dataDir = DATA_DIR$
|
|
6567
|
+
function registerCreateKbArticle(server, dataDir = DATA_DIR$7) {
|
|
6585
6568
|
server.registerTool("create_kb_article", {
|
|
6586
6569
|
description: `Create a new knowledge base article. Articles are stored as Markdown files in .agentic/knowledge-base/.
|
|
6587
6570
|
Returns: { id, title, category, path }`,
|
|
@@ -6606,8 +6589,8 @@ Returns: { id, title, category, path }`,
|
|
|
6606
6589
|
}
|
|
6607
6590
|
//#endregion
|
|
6608
6591
|
//#region src/mcp/tools/backup-now.ts
|
|
6609
|
-
const DATA_DIR$
|
|
6610
|
-
async function handleBackupNow(input, dataDir = DATA_DIR$
|
|
6592
|
+
const DATA_DIR$6 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
6593
|
+
async function handleBackupNow(input, dataDir = DATA_DIR$6) {
|
|
6611
6594
|
const zipPath = path.default.join(dataDir, `dxcrm-backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19)}.zip`);
|
|
6612
6595
|
const manifest = await require_session_store.runBackup(zipPath, dataDir, { ...input.remote ? { remote: input.remote } : {} }).catch(() => null);
|
|
6613
6596
|
if (!manifest) return { content: [{
|
|
@@ -6644,8 +6627,8 @@ function registerBackupNow(server) {
|
|
|
6644
6627
|
}
|
|
6645
6628
|
//#endregion
|
|
6646
6629
|
//#region src/mcp/tools/list-backups.ts
|
|
6647
|
-
const DATA_DIR$
|
|
6648
|
-
async function handleListBackups(input, dataDir = DATA_DIR$
|
|
6630
|
+
const DATA_DIR$5 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
6631
|
+
async function handleListBackups(input, dataDir = DATA_DIR$5) {
|
|
6649
6632
|
const logEntries = require_session_store.readBackupLog(dataDir);
|
|
6650
6633
|
const fileEntries = require_session_store.listBackupsInDir(dataDir);
|
|
6651
6634
|
const entries = logEntries.length > 0 ? logEntries : fileEntries;
|
|
@@ -6679,8 +6662,8 @@ function registerListBackups(server) {
|
|
|
6679
6662
|
}
|
|
6680
6663
|
//#endregion
|
|
6681
6664
|
//#region src/mcp/tools/trigger-sync.ts
|
|
6682
|
-
const DATA_DIR$
|
|
6683
|
-
async function handleTriggerSync(input, dataDir = DATA_DIR$
|
|
6665
|
+
const DATA_DIR$4 = process.cwd();
|
|
6666
|
+
async function handleTriggerSync(input, dataDir = DATA_DIR$4) {
|
|
6684
6667
|
const auth = getGmailAuth();
|
|
6685
6668
|
if (!auth) return { content: [{
|
|
6686
6669
|
type: "text",
|
|
@@ -6715,7 +6698,7 @@ async function handleTriggerSync(input, dataDir = DATA_DIR$3) {
|
|
|
6715
6698
|
try {
|
|
6716
6699
|
const sources = JSON.parse(fs.default.readFileSync(sourcesPath, "utf-8"));
|
|
6717
6700
|
if (!sources.gmail?.enabled || !sources.gmail.query) continue;
|
|
6718
|
-
const { syncGmail } = await Promise.resolve().then(() => require("./gmail-sync-
|
|
6701
|
+
const { syncGmail } = await Promise.resolve().then(() => require("./gmail-sync-GEy3oVvw.cjs"));
|
|
6719
6702
|
const result = await syncGmail({
|
|
6720
6703
|
slug,
|
|
6721
6704
|
dataDir,
|
|
@@ -6774,8 +6757,8 @@ Returns: { success: boolean, synced: number, skipped: number, customers: [...],
|
|
|
6774
6757
|
}
|
|
6775
6758
|
//#endregion
|
|
6776
6759
|
//#region src/mcp/tools/get-audit-log.ts
|
|
6777
|
-
const DATA_DIR$
|
|
6778
|
-
async function handleGetAuditLog(input, dataDir = DATA_DIR$
|
|
6760
|
+
const DATA_DIR$3 = process.cwd();
|
|
6761
|
+
async function handleGetAuditLog(input, dataDir = DATA_DIR$3) {
|
|
6779
6762
|
const entries = require_session_store.readAuditLog(dataDir);
|
|
6780
6763
|
const filterOpts = { limit: input.limit ?? 50 };
|
|
6781
6764
|
if (input.slug !== void 0) filterOpts.slug = input.slug;
|
|
@@ -6816,6 +6799,69 @@ Returns: { total: number, returned: number, entries: [{timestamp, actor, tool, s
|
|
|
6816
6799
|
});
|
|
6817
6800
|
}
|
|
6818
6801
|
//#endregion
|
|
6802
|
+
//#region src/mcp/tools/get-logs.ts
|
|
6803
|
+
const DATA_DIR$2 = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
|
|
6804
|
+
async function handleGetLogs(input, dataDir = DATA_DIR$2) {
|
|
6805
|
+
const query = {
|
|
6806
|
+
...input.level !== void 0 ? { level: input.level } : {},
|
|
6807
|
+
...input.component !== void 0 ? { component: input.component } : {},
|
|
6808
|
+
...input.since !== void 0 ? { since: input.since } : {},
|
|
6809
|
+
...input.contains !== void 0 ? { contains: input.contains } : {},
|
|
6810
|
+
limit: input.limit ?? 100
|
|
6811
|
+
};
|
|
6812
|
+
const payload = input.summary ? require_logger.summarizeLogs(dataDir, query) : (() => {
|
|
6813
|
+
const entries = require_logger.queryLogs(dataDir, query);
|
|
6814
|
+
return {
|
|
6815
|
+
returned: entries.length,
|
|
6816
|
+
entries
|
|
6817
|
+
};
|
|
6818
|
+
})();
|
|
6819
|
+
return { content: [{
|
|
6820
|
+
type: "text",
|
|
6821
|
+
text: JSON.stringify(payload, null, 2)
|
|
6822
|
+
}] };
|
|
6823
|
+
}
|
|
6824
|
+
function registerGetLogs(server) {
|
|
6825
|
+
server.registerTool("get_logs", {
|
|
6826
|
+
title: "Get Logs",
|
|
6827
|
+
description: `Read and analyze the structured application log (.agentic/logs.ndjson).
|
|
6828
|
+
Use to answer "what went wrong recently?", "show errors from gmail sync", or "summarize today's activity".
|
|
6829
|
+
|
|
6830
|
+
Args:
|
|
6831
|
+
level: Minimum level to include — debug | info | warn | error (optional)
|
|
6832
|
+
component: Filter by component, e.g. "gmail-sync", "lancedb" (optional)
|
|
6833
|
+
since: ISO timestamp; only entries at or after it (optional)
|
|
6834
|
+
contains: Case-insensitive substring of the message (optional)
|
|
6835
|
+
limit: Max entries to return (default 100, most recent)
|
|
6836
|
+
summary: When true, return aggregated counts (by level + component) and recent errors instead of raw entries
|
|
6837
|
+
|
|
6838
|
+
Returns (entries): { returned: number, entries: [{ts, level, component, message, context?}] }
|
|
6839
|
+
Returns (summary): { total, byLevel, byComponent, firstTs, lastTs, recentErrors }`,
|
|
6840
|
+
inputSchema: zod.z.object({
|
|
6841
|
+
level: zod.z.enum([
|
|
6842
|
+
"debug",
|
|
6843
|
+
"info",
|
|
6844
|
+
"warn",
|
|
6845
|
+
"error"
|
|
6846
|
+
]).optional().describe("Minimum level"),
|
|
6847
|
+
component: zod.z.string().optional().describe("Filter by component"),
|
|
6848
|
+
since: zod.z.string().optional().describe("ISO timestamp lower bound"),
|
|
6849
|
+
contains: zod.z.string().optional().describe("Message substring filter"),
|
|
6850
|
+
limit: zod.z.number().int().min(1).max(1e3).optional().describe("Max entries (default 100)"),
|
|
6851
|
+
summary: zod.z.boolean().optional().describe("Return aggregated summary instead of entries")
|
|
6852
|
+
})
|
|
6853
|
+
}, async ({ level, component, since, contains, limit, summary }) => {
|
|
6854
|
+
const input = {};
|
|
6855
|
+
if (level !== void 0) input.level = level;
|
|
6856
|
+
if (component !== void 0) input.component = component;
|
|
6857
|
+
if (since !== void 0) input.since = since;
|
|
6858
|
+
if (contains !== void 0) input.contains = contains;
|
|
6859
|
+
if (limit !== void 0) input.limit = limit;
|
|
6860
|
+
if (summary !== void 0) input.summary = summary;
|
|
6861
|
+
return handleGetLogs(input);
|
|
6862
|
+
});
|
|
6863
|
+
}
|
|
6864
|
+
//#endregion
|
|
6819
6865
|
//#region src/mcp/prompts.ts
|
|
6820
6866
|
/**
|
|
6821
6867
|
* CRM playbook prompts exposed via MCP `prompts/list` + `prompts/get`.
|
|
@@ -6897,7 +6943,7 @@ function registerResources(server, dataDir = DATA_DIR$1) {
|
|
|
6897
6943
|
description: "Open and closed deals for a customer",
|
|
6898
6944
|
mimeType: "application/json"
|
|
6899
6945
|
}, async (uri, variables) => {
|
|
6900
|
-
const { readPipeline } = await Promise.resolve().then(() => require("./pipeline-writer-
|
|
6946
|
+
const { readPipeline } = await Promise.resolve().then(() => require("./pipeline-writer-B1tRAhuD.cjs")).then((n) => n.pipeline_writer_exports);
|
|
6901
6947
|
const deals = await readPipeline(dataDir, String(variables["slug"]));
|
|
6902
6948
|
return { contents: [{
|
|
6903
6949
|
uri: uri.href,
|
|
@@ -6910,7 +6956,7 @@ function registerResources(server, dataDir = DATA_DIR$1) {
|
|
|
6910
6956
|
description: "Newest-first interaction history for a customer",
|
|
6911
6957
|
mimeType: "text/markdown"
|
|
6912
6958
|
}, async (uri, variables) => {
|
|
6913
|
-
const { readInteractions } = await Promise.resolve().then(() => require("./interactions-writer-
|
|
6959
|
+
const { readInteractions } = await Promise.resolve().then(() => require("./interactions-writer-a2yzBd7T.cjs")).then((n) => n.interactions_writer_exports);
|
|
6914
6960
|
const text = await readInteractions(dataDir, String(variables["slug"]));
|
|
6915
6961
|
return { contents: [{
|
|
6916
6962
|
uri: uri.href,
|
|
@@ -6969,46 +7015,30 @@ function objectsSchemaPath(dataDir) {
|
|
|
6969
7015
|
return path.default.join(dataDir, ".agentic", "schema", "custom-objects.json");
|
|
6970
7016
|
}
|
|
6971
7017
|
function recordsPath(dataDir, name) {
|
|
7018
|
+
require_session_store.assertSafePathSegment(name, "custom object name");
|
|
6972
7019
|
return path.default.join(dataDir, ".agentic", "objects", `${name}.json`);
|
|
6973
7020
|
}
|
|
6974
7021
|
function loadCustomObjects(dataDir) {
|
|
6975
|
-
|
|
6976
|
-
if (!fs.default.existsSync(p)) return [];
|
|
6977
|
-
try {
|
|
6978
|
-
const data = JSON.parse(fs.default.readFileSync(p, "utf-8"));
|
|
6979
|
-
return Array.isArray(data.objects) ? data.objects : [];
|
|
6980
|
-
} catch {
|
|
6981
|
-
return [];
|
|
6982
|
-
}
|
|
7022
|
+
return require_session_store.readJsonArray(objectsSchemaPath(dataDir), "objects");
|
|
6983
7023
|
}
|
|
6984
7024
|
function getObjectDefinition(dataDir, name) {
|
|
6985
7025
|
return loadCustomObjects(dataDir).find((o) => o.name === name);
|
|
6986
7026
|
}
|
|
6987
7027
|
/** Add or update (by name) a custom object definition. */
|
|
6988
7028
|
function defineCustomObject(dataDir, def) {
|
|
7029
|
+
require_session_store.assertSafePathSegment(def.name, "custom object name");
|
|
6989
7030
|
const objs = loadCustomObjects(dataDir);
|
|
6990
7031
|
const idx = objs.findIndex((o) => o.name === def.name);
|
|
6991
7032
|
if (idx >= 0) objs[idx] = def;
|
|
6992
7033
|
else objs.push(def);
|
|
6993
|
-
|
|
6994
|
-
fs.default.mkdirSync(path.default.dirname(p), { recursive: true });
|
|
6995
|
-
fs.default.writeFileSync(p, JSON.stringify({ objects: objs }, null, 2), "utf-8");
|
|
7034
|
+
require_session_store.writeJsonArray(objectsSchemaPath(dataDir), "objects", objs);
|
|
6996
7035
|
return objs;
|
|
6997
7036
|
}
|
|
6998
7037
|
function listRecords(dataDir, name) {
|
|
6999
|
-
|
|
7000
|
-
if (!fs.default.existsSync(p)) return [];
|
|
7001
|
-
try {
|
|
7002
|
-
const data = JSON.parse(fs.default.readFileSync(p, "utf-8"));
|
|
7003
|
-
return Array.isArray(data.records) ? data.records : [];
|
|
7004
|
-
} catch {
|
|
7005
|
-
return [];
|
|
7006
|
-
}
|
|
7038
|
+
return require_session_store.readJsonArray(recordsPath(dataDir, name), "records");
|
|
7007
7039
|
}
|
|
7008
7040
|
function writeRecords(dataDir, name, records) {
|
|
7009
|
-
|
|
7010
|
-
fs.default.mkdirSync(path.default.dirname(p), { recursive: true });
|
|
7011
|
-
fs.default.writeFileSync(p, JSON.stringify({ records }, null, 2), "utf-8");
|
|
7041
|
+
require_session_store.writeJsonArray(recordsPath(dataDir, name), "records", records);
|
|
7012
7042
|
}
|
|
7013
7043
|
function createRecord(dataDir, name, values) {
|
|
7014
7044
|
const def = getObjectDefinition(dataDir, name);
|
|
@@ -7066,7 +7096,7 @@ function handleCreateRecord(input, dataDir = DATA_DIR) {
|
|
|
7066
7096
|
require_session_store.enforceRbac(dataDir, "create_record");
|
|
7067
7097
|
const res = createRecord(dataDir, input.object, input.values);
|
|
7068
7098
|
if (!res.ok) return json({ error: (res.errors ?? []).join("; ") });
|
|
7069
|
-
Promise.resolve().then(() => require("./webhooks-
|
|
7099
|
+
Promise.resolve().then(() => require("./webhooks-CwW-3kvG.cjs")).then(({ emitEvent }) => emitEvent(dataDir, "record.created", {
|
|
7070
7100
|
object: input.object,
|
|
7071
7101
|
record: res.record
|
|
7072
7102
|
}));
|
|
@@ -7128,14 +7158,7 @@ function hashToken(token) {
|
|
|
7128
7158
|
return (0, crypto.createHash)("sha256").update(token).digest("hex");
|
|
7129
7159
|
}
|
|
7130
7160
|
function loadMcpTokens(dataDir) {
|
|
7131
|
-
|
|
7132
|
-
if (!fs.default.existsSync(p)) return [];
|
|
7133
|
-
try {
|
|
7134
|
-
const data = JSON.parse(fs.default.readFileSync(p, "utf-8"));
|
|
7135
|
-
return Array.isArray(data.tokens) ? data.tokens : [];
|
|
7136
|
-
} catch {
|
|
7137
|
-
return [];
|
|
7138
|
-
}
|
|
7161
|
+
return require_session_store.readJsonArray(tokensPath(dataDir), "tokens");
|
|
7139
7162
|
}
|
|
7140
7163
|
/**
|
|
7141
7164
|
* Whether the HTTP MCP endpoint must require a bearer token.
|
|
@@ -7254,6 +7277,7 @@ function createMcpServer() {
|
|
|
7254
7277
|
registerListBackups(server);
|
|
7255
7278
|
registerTriggerSync(server);
|
|
7256
7279
|
registerGetAuditLog(server);
|
|
7280
|
+
registerGetLogs(server);
|
|
7257
7281
|
registerCustomObjectTools(server);
|
|
7258
7282
|
registerPrompts(server);
|
|
7259
7283
|
registerResources(server);
|
|
@@ -7264,7 +7288,7 @@ async function startStdio() {
|
|
|
7264
7288
|
const server = createMcpServer();
|
|
7265
7289
|
const transport = new _modelcontextprotocol_sdk_server_stdio_js.StdioServerTransport();
|
|
7266
7290
|
await server.connect(transport);
|
|
7267
|
-
|
|
7291
|
+
require_logger.logger.info("mcp-server", "running via stdio");
|
|
7268
7292
|
}
|
|
7269
7293
|
async function startHttp(port = 3847) {
|
|
7270
7294
|
await initOAuthFromDisk(process.cwd());
|
|
@@ -7304,7 +7328,7 @@ async function startHttp(port = 3847) {
|
|
|
7304
7328
|
});
|
|
7305
7329
|
app.get("/sessions", async (_req, res) => {
|
|
7306
7330
|
try {
|
|
7307
|
-
const { readAllSessions } = await Promise.resolve().then(() => require("./session-
|
|
7331
|
+
const { readAllSessions } = await Promise.resolve().then(() => require("./session-Mm7GQbSH.cjs"));
|
|
7308
7332
|
const sessions = readAllSessions(dataDir);
|
|
7309
7333
|
res.json({ sessions });
|
|
7310
7334
|
} catch {
|
|
@@ -7438,15 +7462,15 @@ button{margin-top:12px;padding:12px 28px;background:#1a1a2e;color:#fff;border:no
|
|
|
7438
7462
|
res.send(surveyThankYouPage(numScore, commentText));
|
|
7439
7463
|
});
|
|
7440
7464
|
app.listen(port, () => {
|
|
7441
|
-
|
|
7465
|
+
require_logger.logger.info("mcp-server", "running over http", { url: `http://0.0.0.0:${port}/mcp` });
|
|
7442
7466
|
});
|
|
7443
7467
|
}
|
|
7444
7468
|
if ((process.env["DXCRM_MCP_MODE"] ?? "stdio") === "http") startHttp(parseInt(process.env["DXCRM_MCP_PORT"] ?? "3847", 10)).catch((err) => {
|
|
7445
|
-
|
|
7469
|
+
require_logger.logger.error("mcp-server", "fatal error", { error: err.message });
|
|
7446
7470
|
process.exit(1);
|
|
7447
7471
|
});
|
|
7448
7472
|
else startStdio().catch((err) => {
|
|
7449
|
-
|
|
7473
|
+
require_logger.logger.error("mcp-server", "fatal error", { error: err.message });
|
|
7450
7474
|
process.exit(1);
|
|
7451
7475
|
});
|
|
7452
7476
|
//#endregion
|