@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.
Files changed (286) hide show
  1. package/README.md +264 -670
  2. package/dist/{approvals-DpjxGHFp.js → approvals-CmDT2eUg.js} +7 -24
  3. package/dist/approvals-CmDT2eUg.js.map +1 -0
  4. package/dist/{ask-CID3jnuL.js → ask-D8iYqDAr.js} +6 -6
  5. package/dist/{ask-CID3jnuL.js.map → ask-D8iYqDAr.js.map} +1 -1
  6. package/dist/atomic-write-8yjqqLtS.js +29 -0
  7. package/dist/atomic-write-8yjqqLtS.js.map +1 -0
  8. package/dist/atomic-write-BYmF-ThH.cjs +37 -0
  9. package/dist/atomic-write-BYmF-ThH.cjs.map +1 -0
  10. package/dist/auth-B5DcjJ_6.js +2 -0
  11. package/dist/{auth-DFWwWcYD.js → auth-DDXZTwS0.js} +4 -13
  12. package/dist/auth-DDXZTwS0.js.map +1 -0
  13. package/dist/{autofill-Di_-SP7t.js → autofill-B9VtlR2j.js} +2 -2
  14. package/dist/{autofill-Di_-SP7t.js.map → autofill-B9VtlR2j.js.map} +1 -1
  15. package/dist/{backup-CeMk9z86.js → backup-CTlIxUdO.js} +5 -7
  16. package/dist/backup-CTlIxUdO.js.map +1 -0
  17. package/dist/backup-LFnC09oV.js +2 -0
  18. package/dist/{churn-C28IgnAj.js → churn-DN9WDGNM.js} +3 -3
  19. package/dist/{churn-C28IgnAj.js.map → churn-DN9WDGNM.js.map} +1 -1
  20. package/dist/cli.js +282 -184
  21. package/dist/cli.js.map +1 -1
  22. package/dist/{compliance-CKSBoQUe.js → compliance-Bc12Hn9a.js} +3 -3
  23. package/dist/{compliance-CKSBoQUe.js.map → compliance-Bc12Hn9a.js.map} +1 -1
  24. package/dist/{compliance-CujOqAKk.js → compliance-TqYQXhBj.js} +1 -1
  25. package/dist/{compliance-B1kk5-YS.js → compliance-kq0xHRw3.js} +3 -3
  26. package/dist/{compliance-B1kk5-YS.js.map → compliance-kq0xHRw3.js.map} +1 -1
  27. package/dist/{compliance-B91zNvCR.cjs → compliance-pAj9FcGI.cjs} +3 -3
  28. package/dist/{compliance-B91zNvCR.cjs.map → compliance-pAj9FcGI.cjs.map} +1 -1
  29. package/dist/{context-builder-BzWAp3Zs.js → context-builder-7Uab5-G4.js} +3 -2
  30. package/dist/context-builder-7Uab5-G4.js.map +1 -0
  31. package/dist/context-builder-hmOPvgso.js +2 -0
  32. package/dist/{custom-fields-CzNeD3_v.js → custom-fields-BMyz5Ruh.js} +1 -1
  33. package/dist/{custom-fields-Pl2t9xzp.js → custom-fields-GzpOHW_2.js} +4 -13
  34. package/dist/custom-fields-GzpOHW_2.js.map +1 -0
  35. package/dist/{custom-objects-CIFrmQ2V.js → custom-objects-BNy-ayR-.js} +1 -1
  36. package/dist/{custom-objects-BHgn1GEX.js → custom-objects-CxW1gHwJ.js} +10 -25
  37. package/dist/custom-objects-CxW1gHwJ.js.map +1 -0
  38. package/dist/{customer-dir-DIylZ8Q6.js → customer-dir-CkMMXhb0.js} +9 -4
  39. package/dist/customer-dir-CkMMXhb0.js.map +1 -0
  40. package/dist/daemon/worker.js +66 -40
  41. package/dist/daemon/worker.js.map +1 -1
  42. package/dist/doctor-C14-vnJ1.js +103 -0
  43. package/dist/doctor-C14-vnJ1.js.map +1 -0
  44. package/dist/{enrichment-3XvgGDfB.js → enrichment-CDFdWmvD.js} +3 -3
  45. package/dist/{enrichment-3XvgGDfB.js.map → enrichment-CDFdWmvD.js.map} +1 -1
  46. package/dist/{file-lock-B_zi7NQl.js → file-lock-CcHotQkZ.js} +3 -4
  47. package/dist/file-lock-CcHotQkZ.js.map +1 -0
  48. package/dist/{gmail-sync-rQaVqKWd.js → gmail-sync-C-NmibzS.js} +13 -9
  49. package/dist/gmail-sync-C-NmibzS.js.map +1 -0
  50. package/dist/{gmail-sync-DIaxInDT.js → gmail-sync-DueE6tl5.js} +14 -10
  51. package/dist/gmail-sync-DueE6tl5.js.map +1 -0
  52. package/dist/{gmail-sync-hHm9gaWd.cjs → gmail-sync-GEy3oVvw.cjs} +13 -9
  53. package/dist/gmail-sync-GEy3oVvw.cjs.map +1 -0
  54. package/dist/{gmail-webhook-handler-DS7OlRPX.js → gmail-webhook-handler-B26COilD.js} +2 -2
  55. package/dist/{gmail-webhook-handler-e5Od25FX.js → gmail-webhook-handler-kGKpbY9h.js} +4 -4
  56. package/dist/{gmail-webhook-handler-e5Od25FX.js.map → gmail-webhook-handler-kGKpbY9h.js.map} +1 -1
  57. package/dist/{goal-engine-KpBftn4V.js → goal-engine-BbroPhqm.js} +10 -11
  58. package/dist/goal-engine-BbroPhqm.js.map +1 -0
  59. package/dist/{goal-engine-CUZSpERI.js → goal-engine-CfDAJTFt.js} +1 -1
  60. package/dist/{google-drive-sync-DEPcqFca.js → google-drive-sync-D1n7WKZn.js} +3 -3
  61. package/dist/{google-drive-sync-DEPcqFca.js.map → google-drive-sync-D1n7WKZn.js.map} +1 -1
  62. package/dist/{hygiene-DZqfYpFf.js → hygiene-DzQPnc6P.js} +3 -3
  63. package/dist/{hygiene-DZqfYpFf.js.map → hygiene-DzQPnc6P.js.map} +1 -1
  64. package/dist/identity-CB7j-Zr1.js +2 -0
  65. package/dist/{identity-CI6olMNm.js → identity-_uZ3Lbr2.js} +2 -2
  66. package/dist/{identity-CI6olMNm.js.map → identity-_uZ3Lbr2.js.map} +1 -1
  67. package/dist/{import-hubspot-BaK71U_K.js → import-hubspot-DB4n89jy.js} +51 -45
  68. package/dist/import-hubspot-DB4n89jy.js.map +1 -0
  69. package/dist/{index-V8BFaH-b.d.ts → index-B0IMMrp_.d.ts} +8 -4
  70. package/dist/{index-V8BFaH-b.d.ts.map → index-B0IMMrp_.d.ts.map} +1 -1
  71. package/dist/{index-YqwMd6aQ.d.cts → index-pY7tYXwH.d.cts} +8 -4
  72. package/dist/{index-YqwMd6aQ.d.cts.map → index-pY7tYXwH.d.cts.map} +1 -1
  73. package/dist/index.cjs +19 -21
  74. package/dist/index.cjs.map +1 -1
  75. package/dist/index.d.cts +8 -4
  76. package/dist/index.d.cts.map +1 -1
  77. package/dist/index.d.ts +8 -4
  78. package/dist/index.d.ts.map +1 -1
  79. package/dist/index.js +19 -21
  80. package/dist/index.js.map +1 -1
  81. package/dist/{interactions-writer-DO3KcSR3.js → interactions-writer-BZzUIgJd.js} +5 -2
  82. package/dist/interactions-writer-BZzUIgJd.js.map +1 -0
  83. package/dist/{interactions-writer-SLHnoEeE.js → interactions-writer-DbSyI2rt.js} +32 -3
  84. package/dist/interactions-writer-DbSyI2rt.js.map +1 -0
  85. package/dist/interactions-writer-RJB8SWf2.js +2 -0
  86. package/dist/{interactions-writer-CrPStUll.cjs → interactions-writer-a2yzBd7T.cjs} +5 -2
  87. package/dist/interactions-writer-a2yzBd7T.cjs.map +1 -0
  88. package/dist/json-store-WWsFzXub.js +43 -0
  89. package/dist/json-store-WWsFzXub.js.map +1 -0
  90. package/dist/{knowledge-base-D0Fh40kc.js → knowledge-base-DHNc4hVj.js} +43 -16
  91. package/dist/knowledge-base-DHNc4hVj.js.map +1 -0
  92. package/dist/{lancedb-CCBbpulq.js → lancedb-CswQEE5K.js} +1 -1
  93. package/dist/{lancedb-rlvWoPwl.js → lancedb-CuHKNsNZ.js} +4 -3
  94. package/dist/lancedb-CuHKNsNZ.js.map +1 -0
  95. package/dist/{lead-model-BCFzyktm.js → lead-model-CEmx7te7.js} +6 -14
  96. package/dist/lead-model-CEmx7te7.js.map +1 -0
  97. package/dist/{llm-Z8RIYkpF.js → llm-BnSUBisu.js} +2 -2
  98. package/dist/{llm-Z8RIYkpF.js.map → llm-BnSUBisu.js.map} +1 -1
  99. package/dist/{llm-iijeXmgq.cjs → llm-CXycmEl9.cjs} +2 -2
  100. package/dist/{llm-iijeXmgq.cjs.map → llm-CXycmEl9.cjs.map} +1 -1
  101. package/dist/{llm-DEjWcqmW.js → llm-DSX1-wFu.js} +1 -1
  102. package/dist/{llm-DvzZqva0.js → llm-PZzgPphl.js} +3 -3
  103. package/dist/{llm-DvzZqva0.js.map → llm-PZzgPphl.js.map} +1 -1
  104. package/dist/logger-BkInaGoV.cjs +167 -0
  105. package/dist/logger-BkInaGoV.cjs.map +1 -0
  106. package/dist/logger-Dyl4VcLO.js +147 -0
  107. package/dist/logger-Dyl4VcLO.js.map +1 -0
  108. package/dist/logger-UaF5p9d1.js +147 -0
  109. package/dist/logger-UaF5p9d1.js.map +1 -0
  110. package/dist/logger-vKQS34w9.js +2 -0
  111. package/dist/mcp-CdTJWTJf.d.cts.map +1 -1
  112. package/dist/mcp-CdTJWTJf.d.ts.map +1 -1
  113. package/dist/mcp.cjs +327 -303
  114. package/dist/mcp.cjs.map +1 -1
  115. package/dist/mcp.d.cts.map +1 -1
  116. package/dist/mcp.d.ts.map +1 -1
  117. package/dist/mcp.js +327 -303
  118. package/dist/mcp.js.map +1 -1
  119. package/dist/{memory-Cy6-Tbyl.js → memory-D8hmgD9d.js} +1 -1
  120. package/dist/{memory-Bb6ky3kb.js → memory-Dzr9dXSM.js} +4 -11
  121. package/dist/memory-Dzr9dXSM.js.map +1 -0
  122. package/dist/{microsoft-calendar-B6MMtUQK.js → microsoft-calendar-jIu9K5zX.js} +4 -4
  123. package/dist/{microsoft-calendar-B6MMtUQK.js.map → microsoft-calendar-jIu9K5zX.js.map} +1 -1
  124. package/dist/{microsoft-sync-CpZVoSuq.js → microsoft-sync-R_r8HL-B.js} +5 -5
  125. package/dist/{microsoft-sync-CpZVoSuq.js.map → microsoft-sync-R_r8HL-B.js.map} +1 -1
  126. package/dist/{nba-3wanmJ0U.js → nba-mTJ4yEqD.js} +3 -3
  127. package/dist/{nba-3wanmJ0U.js.map → nba-mTJ4yEqD.js.map} +1 -1
  128. package/dist/{notification-dispatcher-0vYNngWe.js → notification-dispatcher-inpKyuBz.js} +7 -3
  129. package/dist/notification-dispatcher-inpKyuBz.js.map +1 -0
  130. package/dist/{pipeline-writer-BqBrYrQc.js → pipeline-writer-0LJ6Qkat.js} +1 -1
  131. package/dist/{pipeline-writer-N2omexxp.cjs → pipeline-writer-B1tRAhuD.cjs} +11 -3
  132. package/dist/pipeline-writer-B1tRAhuD.cjs.map +1 -0
  133. package/dist/{pipeline-writer-BvVquKIe.js → pipeline-writer-CIllfnZl.js} +5 -3
  134. package/dist/pipeline-writer-CIllfnZl.js.map +1 -0
  135. package/dist/{pipeline-writer-eufx_0o1.js → pipeline-writer-rDj-ni6q.js} +6 -4
  136. package/dist/pipeline-writer-rDj-ni6q.js.map +1 -0
  137. package/dist/{proactive-agent-BgQXw3ac.js → proactive-agent-B7u3Bj_l.js} +6 -6
  138. package/dist/{proactive-agent-BgQXw3ac.js.map → proactive-agent-B7u3Bj_l.js.map} +1 -1
  139. package/dist/{proactive-worker-BrLHNhjH.js → proactive-worker-1zkm6aJD.js} +7 -8
  140. package/dist/proactive-worker-1zkm6aJD.js.map +1 -0
  141. package/dist/{push-manager-CowY-0IK.js → push-manager-BXM-IHfP.js} +1 -1
  142. package/dist/{push-manager-CdqIIkuh.js → push-manager-C0ECQgva.js} +4 -4
  143. package/dist/push-manager-C0ECQgva.js.map +1 -0
  144. package/dist/{quote-generator-OhSFsi3x.js → quote-generator-ByUyIYtw.js} +1 -1
  145. package/dist/{quote-generator-BfwENXzg.js → quote-generator-CTdR8eEI.js} +5 -5
  146. package/dist/quote-generator-CTdR8eEI.js.map +1 -0
  147. package/dist/rbac-DzbyFhVH.js +2 -0
  148. package/dist/{rbac-CTIktZaC.js → rbac-msmBc_tK.js} +19 -12
  149. package/dist/rbac-msmBc_tK.js.map +1 -0
  150. package/dist/regex-Jt5DatPi.js +13 -0
  151. package/dist/regex-Jt5DatPi.js.map +1 -0
  152. package/dist/{relationship-health-odxEoQdJ.js → relationship-health-ZZNXR1RZ.js} +8 -16
  153. package/dist/relationship-health-ZZNXR1RZ.js.map +1 -0
  154. package/dist/{revenue-simulation-Bqf2DLVB.js → revenue-simulation-D8f_YkUY.js} +9 -19
  155. package/dist/revenue-simulation-D8f_YkUY.js.map +1 -0
  156. package/dist/{revenue-simulation-BJdRTEHc.js → revenue-simulation-njJZlTqm.js} +1 -1
  157. package/dist/safe-path-mpp0dKtO.js +18 -0
  158. package/dist/safe-path-mpp0dKtO.js.map +1 -0
  159. package/dist/{segments-BqcD5HIl.js → segments-DI3LOQNe.js} +5 -14
  160. package/dist/segments-DI3LOQNe.js.map +1 -0
  161. package/dist/sequence-engine-C6nnewHX.js +2 -0
  162. package/dist/{sequence-engine-J1lTW_in.js → sequence-engine-DNTVLq7o.js} +15 -8
  163. package/dist/sequence-engine-DNTVLq7o.js.map +1 -0
  164. package/dist/{sequence-store-DaaWr0Os.js → sequence-store-CmYb6s0g.js} +6 -5
  165. package/dist/sequence-store-CmYb6s0g.js.map +1 -0
  166. package/dist/{server-Dyva03K8.js → server-DqSMYhSA.js} +278 -220
  167. package/dist/server-DqSMYhSA.js.map +1 -0
  168. package/dist/{session-D9ub6Wl1.js → session-B6XaP83h.js} +3 -3
  169. package/dist/session-B6XaP83h.js.map +1 -0
  170. package/dist/{session-B9AilxOE.js → session-BgGDyP2C.js} +3 -3
  171. package/dist/session-BgGDyP2C.js.map +1 -0
  172. package/dist/session-Bp4zTh4l.js +2 -0
  173. package/dist/{session-D0qFkBla.cjs → session-Mm7GQbSH.cjs} +3 -3
  174. package/dist/session-Mm7GQbSH.cjs.map +1 -0
  175. package/dist/{session-store-C8tEvMPw.js → session-store-DWxJ5Pof.js} +79 -17
  176. package/dist/session-store-DWxJ5Pof.js.map +1 -0
  177. package/dist/{session-store-B0QZE8Bx.cjs → session-store-yfwnj0OC.cjs} +126 -16
  178. package/dist/session-store-yfwnj0OC.cjs.map +1 -0
  179. package/dist/{sla-engine-5IhTsBUR.js → sla-engine-CP2KiKDS.js} +1 -1
  180. package/dist/{sla-engine-BqX-7u-7.js → sla-engine-O-A1ntu_.js} +2 -2
  181. package/dist/{sla-engine-BqX-7u-7.js.map → sla-engine-O-A1ntu_.js.map} +1 -1
  182. package/dist/{sop-Vp0UPWFW.js → sop-BV7ICAFR.js} +4 -11
  183. package/dist/sop-BV7ICAFR.js.map +1 -0
  184. package/dist/{sop-DkhVChGy.js → sop-D33qTHUb.js} +1 -1
  185. package/dist/survey-engine-DKctGcLQ.js +2 -0
  186. package/dist/{survey-engine-DBjCYqCv.js → survey-engine-DngXBv47.js} +5 -4
  187. package/dist/survey-engine-DngXBv47.js.map +1 -0
  188. package/dist/{sync-state-CwLSt_1m.js → sync-state-BaA8LbTI.js} +1 -1
  189. package/dist/{sync-state-ChaLbamC.js → sync-state-DMZgzpez.js} +4 -12
  190. package/dist/sync-state-DMZgzpez.js.map +1 -0
  191. package/dist/{ticket-writer-CjqKeIRD.js → ticket-writer-DsfpeLGZ.js} +1 -1
  192. package/dist/{ticket-writer-j2oX_Wal.js → ticket-writer-a9on36Wb.js} +12 -24
  193. package/dist/ticket-writer-a9on36Wb.js.map +1 -0
  194. package/dist/{tone-Bdm5uaht.js → tone-C7bqK69y.js} +5 -12
  195. package/dist/tone-C7bqK69y.js.map +1 -0
  196. package/dist/{tone-DRKlZgPr.cjs → tone-Cmc7O2Fx.cjs} +3 -9
  197. package/dist/tone-Cmc7O2Fx.cjs.map +1 -0
  198. package/dist/{tone-vNb2DAAD.js → tone-mXSftvTn.js} +3 -8
  199. package/dist/tone-mXSftvTn.js.map +1 -0
  200. package/dist/{transcript-watcher-CL2QUygI.js → transcript-watcher-0mh2ZhmH.js} +18 -11
  201. package/dist/transcript-watcher-0mh2ZhmH.js.map +1 -0
  202. package/dist/unmatched-transcripts-C92zAoM4.js +2 -0
  203. package/dist/unmatched-transcripts-DC-VQ9YS.js +16 -0
  204. package/dist/unmatched-transcripts-DC-VQ9YS.js.map +1 -0
  205. package/dist/update-deal-CWy1eLJI.js +2 -0
  206. package/dist/{update-deal-DKC79skb.js → update-deal-DSzr_Aau.js} +3 -3
  207. package/dist/{update-deal-DKC79skb.js.map → update-deal-DSzr_Aau.js.map} +1 -1
  208. package/dist/{usage-D0-TYJkw.js → usage-BVlFlKW_.js} +8 -6
  209. package/dist/usage-BVlFlKW_.js.map +1 -0
  210. package/dist/usage-CClTf5e6.cjs.map +1 -1
  211. package/dist/usage-D0u9a-lV.js.map +1 -1
  212. package/dist/{vault-DXCg29W-.js → vault-CfwZdNzC.js} +3 -4
  213. package/dist/vault-CfwZdNzC.js.map +1 -0
  214. package/dist/{vault-C1D3zScD.js → vault-DxKP4_R2.js} +1 -1
  215. package/dist/{webhooks-Xn6zO6kd.cjs → webhooks-CwW-3kvG.cjs} +5 -19
  216. package/dist/webhooks-CwW-3kvG.cjs.map +1 -0
  217. package/dist/{webhooks-7EpA05Qr.js → webhooks-DXr1IoKn.js} +8 -21
  218. package/dist/webhooks-DXr1IoKn.js.map +1 -0
  219. package/dist/{webhooks-BO2UAnmn.js → webhooks-sWZ8CJtR.js} +5 -18
  220. package/dist/webhooks-sWZ8CJtR.js.map +1 -0
  221. package/package.json +11 -2
  222. package/dist/approvals-DpjxGHFp.js.map +0 -1
  223. package/dist/auth-CyFuu9X_.js +0 -2
  224. package/dist/auth-DFWwWcYD.js.map +0 -1
  225. package/dist/backup-CeMk9z86.js.map +0 -1
  226. package/dist/backup-f_hC7rBV.js +0 -2
  227. package/dist/context-builder-BzWAp3Zs.js.map +0 -1
  228. package/dist/context-builder-DlrRcqmJ.js +0 -2
  229. package/dist/custom-fields-Pl2t9xzp.js.map +0 -1
  230. package/dist/custom-objects-BHgn1GEX.js.map +0 -1
  231. package/dist/customer-dir-DIylZ8Q6.js.map +0 -1
  232. package/dist/file-lock-B_zi7NQl.js.map +0 -1
  233. package/dist/gmail-sync-DIaxInDT.js.map +0 -1
  234. package/dist/gmail-sync-hHm9gaWd.cjs.map +0 -1
  235. package/dist/gmail-sync-rQaVqKWd.js.map +0 -1
  236. package/dist/goal-engine-KpBftn4V.js.map +0 -1
  237. package/dist/identity-gyfWdrcX.js +0 -2
  238. package/dist/import-hubspot-BaK71U_K.js.map +0 -1
  239. package/dist/interactions-writer-CrPStUll.cjs.map +0 -1
  240. package/dist/interactions-writer-DO3KcSR3.js.map +0 -1
  241. package/dist/interactions-writer-SLHnoEeE.js.map +0 -1
  242. package/dist/interactions-writer-dSPy1XfO.js +0 -2
  243. package/dist/knowledge-base-D0Fh40kc.js.map +0 -1
  244. package/dist/lancedb-rlvWoPwl.js.map +0 -1
  245. package/dist/lead-model-BCFzyktm.js.map +0 -1
  246. package/dist/memory-Bb6ky3kb.js.map +0 -1
  247. package/dist/notification-dispatcher-0vYNngWe.js.map +0 -1
  248. package/dist/pipeline-writer-BvVquKIe.js.map +0 -1
  249. package/dist/pipeline-writer-N2omexxp.cjs.map +0 -1
  250. package/dist/pipeline-writer-eufx_0o1.js.map +0 -1
  251. package/dist/proactive-worker-BrLHNhjH.js.map +0 -1
  252. package/dist/push-manager-CdqIIkuh.js.map +0 -1
  253. package/dist/quote-generator-BfwENXzg.js.map +0 -1
  254. package/dist/rbac-C7c8tcES.js +0 -2
  255. package/dist/rbac-CTIktZaC.js.map +0 -1
  256. package/dist/relationship-health-odxEoQdJ.js.map +0 -1
  257. package/dist/revenue-simulation-Bqf2DLVB.js.map +0 -1
  258. package/dist/segments-BqcD5HIl.js.map +0 -1
  259. package/dist/sequence-engine-CCTHEBgi.js +0 -2
  260. package/dist/sequence-engine-J1lTW_in.js.map +0 -1
  261. package/dist/sequence-store-DaaWr0Os.js.map +0 -1
  262. package/dist/server-Dyva03K8.js.map +0 -1
  263. package/dist/session-B9AilxOE.js.map +0 -1
  264. package/dist/session-D0qFkBla.cjs.map +0 -1
  265. package/dist/session-D9ub6Wl1.js.map +0 -1
  266. package/dist/session-mWHA71Lw.js +0 -2
  267. package/dist/session-store-B0QZE8Bx.cjs.map +0 -1
  268. package/dist/session-store-C8tEvMPw.js.map +0 -1
  269. package/dist/sop-Vp0UPWFW.js.map +0 -1
  270. package/dist/survey-engine-C06hcQt3.js +0 -2
  271. package/dist/survey-engine-DBjCYqCv.js.map +0 -1
  272. package/dist/sync-state-ChaLbamC.js.map +0 -1
  273. package/dist/ticket-writer-j2oX_Wal.js.map +0 -1
  274. package/dist/tone-Bdm5uaht.js.map +0 -1
  275. package/dist/tone-DRKlZgPr.cjs.map +0 -1
  276. package/dist/tone-vNb2DAAD.js.map +0 -1
  277. package/dist/transcript-watcher-CL2QUygI.js.map +0 -1
  278. package/dist/unmatched-transcripts-BsH5bhkU.js +0 -26
  279. package/dist/unmatched-transcripts-BsH5bhkU.js.map +0 -1
  280. package/dist/unmatched-transcripts-D0PrJ9iz.js +0 -2
  281. package/dist/update-deal-BNwPGaTV.js +0 -2
  282. package/dist/usage-D0-TYJkw.js.map +0 -1
  283. package/dist/vault-DXCg29W-.js.map +0 -1
  284. package/dist/webhooks-7EpA05Qr.js.map +0 -1
  285. package/dist/webhooks-BO2UAnmn.js.map +0 -1
  286. package/dist/webhooks-Xn6zO6kd.cjs.map +0 -1
@@ -1,3 +1,5 @@
1
+ import { i as listCustomerSlugs, t as assertSafeSlug } from "./customer-dir-CkMMXhb0.js";
2
+ import { t as writeFileAtomic } from "./atomic-write-8yjqqLtS.js";
1
3
  import path from "path";
2
4
  import fs from "fs";
3
5
  import { z } from "zod";
@@ -32,6 +34,7 @@ const TICKET_HEADER = "# Tickets\n\n";
32
34
  const TABLE_HEADER = `| ID | Title | Status | Priority | Assignee | Created | SLA Due | Resolved |
33
35
  |----|-------|--------|----------|----------|---------|---------|---------|`;
34
36
  function ticketsPath(dataDir, slug) {
37
+ assertSafeSlug(slug);
35
38
  return path.join(dataDir, "customers", slug, "tickets.md");
36
39
  }
37
40
  function escapeMd(s) {
@@ -84,7 +87,7 @@ async function upsertTicket(dataDir, slug, ticket) {
84
87
  const idx = existing.findIndex((t) => t.id === ticket.id);
85
88
  if (idx >= 0) existing[idx] = ticket;
86
89
  else existing.push(ticket);
87
- fs.writeFileSync(p, serializeTickets(existing), "utf-8");
90
+ writeFileAtomic(p, serializeTickets(existing));
88
91
  }
89
92
  function nextTicketId(tickets) {
90
93
  const nums = tickets.map((t) => parseInt(t.id.replace("T-", ""), 10)).filter((n) => !isNaN(n));
@@ -92,28 +95,13 @@ function nextTicketId(tickets) {
92
95
  return `T-${String(max + 1).padStart(3, "0")}`;
93
96
  }
94
97
  async function listAllTickets(dataDir, filter) {
95
- const customersDir = path.join(dataDir, "customers");
96
- if (!fs.existsSync(customersDir)) return [];
97
- const slugs = filter?.slug ? [filter.slug] : fs.readdirSync(customersDir).filter((s) => {
98
- try {
99
- return fs.statSync(path.join(customersDir, s)).isDirectory();
100
- } catch {
101
- return false;
102
- }
103
- });
104
- const results = [];
105
- for (const slug of slugs) {
106
- const tickets = await readTickets(dataDir, slug);
107
- for (const ticket of tickets) {
108
- if (filter?.status && ticket.status !== filter.status) continue;
109
- if (filter?.priority && ticket.priority !== filter.priority) continue;
110
- if (filter?.assignee && ticket.assignee !== filter.assignee) continue;
111
- results.push({
112
- slug,
113
- ticket
114
- });
115
- }
116
- }
98
+ const slugs = filter?.slug ? [filter.slug] : listCustomerSlugs(dataDir);
99
+ const results = (await Promise.all(slugs.map(async (slug) => {
100
+ 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) => ({
101
+ slug,
102
+ ticket
103
+ }));
104
+ }))).flat();
117
105
  const priorityOrder = {
118
106
  urgent: 0,
119
107
  high: 1,
@@ -131,4 +119,4 @@ async function listAllTickets(dataDir, filter) {
131
119
  //#endregion
132
120
  export { upsertTicket as i, nextTicketId as n, readTickets as r, listAllTickets as t };
133
121
 
134
- //# sourceMappingURL=ticket-writer-j2oX_Wal.js.map
122
+ //# sourceMappingURL=ticket-writer-a9on36Wb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ticket-writer-a9on36Wb.js","names":[],"sources":["../src/schemas/ticket.ts","../src/fs/ticket-writer.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport const TicketStatusSchema = z.enum([\"open\", \"in-progress\", \"waiting\", \"resolved\", \"closed\"]);\nexport const TicketPrioritySchema = z.enum([\"urgent\", \"high\", \"normal\", \"low\"]);\n\nexport const TicketSchema = z.object({\n id: z.string().regex(/^T-\\d{3,}$/),\n title: z.string().min(1),\n status: TicketStatusSchema,\n priority: TicketPrioritySchema.default(\"normal\"),\n assignee: z.string().optional(),\n created: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}$/),\n slaDue: z\n .string()\n .regex(/^\\d{4}-\\d{2}-\\d{2}$/)\n .optional(),\n resolved: z\n .string()\n .regex(/^\\d{4}-\\d{2}-\\d{2}$/)\n .optional(),\n description: z.string().optional(),\n});\n\nexport type Ticket = z.infer<typeof TicketSchema>;\nexport type TicketStatus = z.infer<typeof TicketStatusSchema>;\nexport type TicketPriority = z.infer<typeof TicketPrioritySchema>;\n","import fs from \"fs\";\nimport path from \"path\";\nimport { TicketSchema, type Ticket } from \"../schemas/ticket.js\";\nimport { listCustomerSlugs, assertSafeSlug } from \"./customer-dir.js\";\nimport { writeFileAtomic } from \"./atomic-write.js\";\n\nconst TICKET_HEADER = \"# Tickets\\n\\n\";\nconst TABLE_HEADER = `| ID | Title | Status | Priority | Assignee | Created | SLA Due | Resolved |\n|----|-------|--------|----------|----------|---------|---------|---------|`;\n\nfunction ticketsPath(dataDir: string, slug: string): string {\n assertSafeSlug(slug);\n return path.join(dataDir, \"customers\", slug, \"tickets.md\");\n}\n\nfunction escapeMd(s: string | undefined): string {\n return (s ?? \"\").replace(/\\|/g, \"\\\\|\").replace(/\\n/g, \" \");\n}\n\nfunction parseTicketsFromMarkdown(content: string): Ticket[] {\n const tickets: Ticket[] = [];\n const lines = content.split(\"\\n\");\n let inTable = false;\n\n for (const line of lines) {\n if (line.startsWith(\"| ID |\") || line.startsWith(\"|----\")) {\n inTable = true;\n continue;\n }\n if (!inTable) continue;\n if (!line.startsWith(\"|\")) {\n inTable = false;\n continue;\n }\n\n const cols = line\n .split(\"|\")\n .slice(1, -1)\n .map((c) => c.trim());\n if (cols.length < 8) continue;\n const [id, title, status, priority, assignee, created, slaDue, resolved] = cols;\n if (!id || !title || id === \"ID\") continue;\n\n const raw = {\n id,\n title,\n status: status || \"open\",\n priority: priority || \"normal\",\n ...(assignee ? { assignee } : {}),\n created: created || new Date().toISOString().slice(0, 10),\n ...(slaDue ? { slaDue } : {}),\n ...(resolved ? { resolved } : {}),\n };\n\n const parsed = TicketSchema.safeParse(raw);\n if (parsed.success) tickets.push(parsed.data);\n }\n return tickets;\n}\n\nfunction serializeTickets(tickets: Ticket[]): string {\n const rows = tickets.map(\n (t) =>\n `| ${t.id} | ${escapeMd(t.title)} | ${t.status} | ${t.priority} | ${t.assignee ?? \"\"} | ${t.created} | ${t.slaDue ?? \"\"} | ${t.resolved ?? \"\"} |`\n );\n return `${TICKET_HEADER}${TABLE_HEADER}\\n${rows.join(\"\\n\")}\\n`;\n}\n\nexport async function readTickets(dataDir: string, slug: string): Promise<Ticket[]> {\n const p = ticketsPath(dataDir, slug);\n if (!fs.existsSync(p)) return [];\n return parseTicketsFromMarkdown(fs.readFileSync(p, \"utf-8\") as string);\n}\n\nexport async function upsertTicket(dataDir: string, slug: string, ticket: Ticket): Promise<void> {\n const p = ticketsPath(dataDir, slug);\n const existing = await readTickets(dataDir, slug);\n const idx = existing.findIndex((t) => t.id === ticket.id);\n if (idx >= 0) {\n existing[idx] = ticket;\n } else {\n existing.push(ticket);\n }\n writeFileAtomic(p, serializeTickets(existing));\n}\n\nexport function nextTicketId(tickets: Ticket[]): string {\n const nums = tickets.map((t) => parseInt(t.id.replace(\"T-\", \"\"), 10)).filter((n) => !isNaN(n));\n const max = nums.length > 0 ? Math.max(...nums) : 0;\n return `T-${String(max + 1).padStart(3, \"0\")}`;\n}\n\nexport async function listAllTickets(\n dataDir: string,\n filter?: { slug?: string; status?: string; priority?: string; assignee?: string }\n): Promise<Array<{ slug: string; ticket: Ticket }>> {\n const slugs = filter?.slug ? [filter.slug] : listCustomerSlugs(dataDir);\n\n // Each customer's tickets file is independent — read them in parallel.\n const perCustomer = await Promise.all(\n slugs.map(async (slug) => {\n const tickets = await readTickets(dataDir, slug);\n return tickets\n .filter(\n (ticket) =>\n (!filter?.status || ticket.status === filter.status) &&\n (!filter?.priority || ticket.priority === filter.priority) &&\n (!filter?.assignee || ticket.assignee === filter.assignee)\n )\n .map((ticket) => ({ slug, ticket }));\n })\n );\n const results = perCustomer.flat();\n\n // Sort: urgent first, then by created date\n const priorityOrder: Record<string, number> = { urgent: 0, high: 1, normal: 2, low: 3 };\n results.sort((a, b) => {\n const pa = priorityOrder[a.ticket.priority] ?? 2;\n const pb = priorityOrder[b.ticket.priority] ?? 2;\n if (pa !== pb) return pa - pb;\n return a.ticket.created.localeCompare(b.ticket.created);\n });\n\n return results;\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
+ import { i as writeJsonFile, n as readJsonFile } from "./json-store-WWsFzXub.js";
1
2
  import path from "path";
2
- import fs from "fs";
3
3
  //#region src/core/tone.ts
4
4
  function globalPath(dataDir) {
5
5
  return path.join(dataDir, ".agentic", "tone.json");
@@ -8,21 +8,14 @@ function customerPath(dataDir, slug) {
8
8
  return path.join(dataDir, "customers", slug, "tone.json");
9
9
  }
10
10
  function readProfile(p) {
11
- if (!fs.existsSync(p)) return {};
12
- try {
13
- return JSON.parse(fs.readFileSync(p, "utf-8"));
14
- } catch {
15
- return {};
16
- }
11
+ return readJsonFile(p, {});
17
12
  }
18
13
  function setTone(dataDir, profile, slug) {
19
14
  const p = slug ? customerPath(dataDir, slug) : globalPath(dataDir);
20
- const merged = {
15
+ writeJsonFile(p, {
21
16
  ...readProfile(p),
22
17
  ...profile
23
- };
24
- fs.mkdirSync(path.dirname(p), { recursive: true });
25
- fs.writeFileSync(p, JSON.stringify(merged, null, 2), "utf-8");
18
+ });
26
19
  }
27
20
  /** Effective profile: global as base, customer fields override. */
28
21
  function resolveTone(dataDir, slug) {
@@ -45,4 +38,4 @@ function toneInstruction(profile) {
45
38
  //#endregion
46
39
  export { resolveTone, setTone, toneInstruction };
47
40
 
48
- //# sourceMappingURL=tone-Bdm5uaht.js.map
41
+ //# sourceMappingURL=tone-C7bqK69y.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tone-C7bqK69y.js","names":[],"sources":["../src/core/tone.ts"],"sourcesContent":["import path from \"path\";\nimport { readJsonFile, writeJsonFile } from \"../fs/json-store.js\";\n\n/**\n * Customer tonality (domino D8 / F2): per-customer (and global) tone profiles\n * applied automatically to generated communication. Customer profile fields\n * override the global default; the merged profile is rendered into a tone\n * instruction for the LLM (used by draft_email / sequences / journeys).\n */\nexport interface ToneProfile {\n formality?: string; // e.g. formal | casual | friendly\n language?: string; // e.g. de | en\n dos?: string[];\n donts?: string[];\n examples?: string[];\n}\n\nfunction globalPath(dataDir: string): string {\n return path.join(dataDir, \".agentic\", \"tone.json\");\n}\nfunction customerPath(dataDir: string, slug: string): string {\n return path.join(dataDir, \"customers\", slug, \"tone.json\");\n}\n\nfunction readProfile(p: string): ToneProfile {\n return readJsonFile<ToneProfile>(p, {});\n}\n\nexport function setTone(dataDir: string, profile: ToneProfile, slug?: string): void {\n const p = slug ? customerPath(dataDir, slug) : globalPath(dataDir);\n writeJsonFile(p, { ...readProfile(p), ...profile });\n}\n\n/** Effective profile: global as base, customer fields override. */\nexport function resolveTone(dataDir: string, slug?: string): ToneProfile {\n const global = readProfile(globalPath(dataDir));\n if (!slug) return global;\n return { ...global, ...readProfile(customerPath(dataDir, slug)) };\n}\n\n/** Render a tone profile into an instruction string (\"\" when blank). */\nexport function toneInstruction(profile: ToneProfile): string {\n const parts: string[] = [];\n if (profile.formality) parts.push(`tone: ${profile.formality}`);\n if (profile.language) parts.push(`language: ${profile.language}`);\n if (profile.dos && profile.dos.length) parts.push(`prefer: ${profile.dos.join(\", \")}`);\n if (profile.donts && profile.donts.length) parts.push(`avoid: ${profile.donts.join(\", \")}`);\n return parts.join(\"; \");\n}\n"],"mappings":";;;AAiBA,SAAS,WAAW,SAAyB;CAC3C,OAAO,KAAK,KAAK,SAAS,YAAY,WAAW;AACnD;AACA,SAAS,aAAa,SAAiB,MAAsB;CAC3D,OAAO,KAAK,KAAK,SAAS,aAAa,MAAM,WAAW;AAC1D;AAEA,SAAS,YAAY,GAAwB;CAC3C,OAAO,aAA0B,GAAG,CAAC,CAAC;AACxC;AAEA,SAAgB,QAAQ,SAAiB,SAAsB,MAAqB;CAClF,MAAM,IAAI,OAAO,aAAa,SAAS,IAAI,IAAI,WAAW,OAAO;CACjE,cAAc,GAAG;EAAE,GAAG,YAAY,CAAC;EAAG,GAAG;CAAQ,CAAC;AACpD;;AAGA,SAAgB,YAAY,SAAiB,MAA4B;CACvE,MAAM,SAAS,YAAY,WAAW,OAAO,CAAC;CAC9C,IAAI,CAAC,MAAM,OAAO;CAClB,OAAO;EAAE,GAAG;EAAQ,GAAG,YAAY,aAAa,SAAS,IAAI,CAAC;CAAE;AAClE;;AAGA,SAAgB,gBAAgB,SAA8B;CAC5D,MAAM,QAAkB,CAAC;CACzB,IAAI,QAAQ,WAAW,MAAM,KAAK,SAAS,QAAQ,WAAW;CAC9D,IAAI,QAAQ,UAAU,MAAM,KAAK,aAAa,QAAQ,UAAU;CAChE,IAAI,QAAQ,OAAO,QAAQ,IAAI,QAAQ,MAAM,KAAK,WAAW,QAAQ,IAAI,KAAK,IAAI,GAAG;CACrF,IAAI,QAAQ,SAAS,QAAQ,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,KAAK,IAAI,GAAG;CAC1F,OAAO,MAAM,KAAK,IAAI;AACxB"}
@@ -1,8 +1,7 @@
1
1
  const require_chunk = require("./chunk-DakpK96I.cjs");
2
+ const require_session_store = require("./session-store-yfwnj0OC.cjs");
2
3
  let path = require("path");
3
4
  path = require_chunk.__toESM(path, 1);
4
- let fs = require("fs");
5
- fs = require_chunk.__toESM(fs, 1);
6
5
  //#region src/core/tone.ts
7
6
  function globalPath(dataDir) {
8
7
  return path.default.join(dataDir, ".agentic", "tone.json");
@@ -11,12 +10,7 @@ function customerPath(dataDir, slug) {
11
10
  return path.default.join(dataDir, "customers", slug, "tone.json");
12
11
  }
13
12
  function readProfile(p) {
14
- if (!fs.default.existsSync(p)) return {};
15
- try {
16
- return JSON.parse(fs.default.readFileSync(p, "utf-8"));
17
- } catch {
18
- return {};
19
- }
13
+ return require_session_store.readJsonFile(p, {});
20
14
  }
21
15
  /** Effective profile: global as base, customer fields override. */
22
16
  function resolveTone(dataDir, slug) {
@@ -40,4 +34,4 @@ function toneInstruction(profile) {
40
34
  exports.resolveTone = resolveTone;
41
35
  exports.toneInstruction = toneInstruction;
42
36
 
43
- //# sourceMappingURL=tone-DRKlZgPr.cjs.map
37
+ //# sourceMappingURL=tone-Cmc7O2Fx.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tone-Cmc7O2Fx.cjs","names":["readJsonFile"],"sources":["../src/core/tone.ts"],"sourcesContent":["import path from \"path\";\nimport { readJsonFile, writeJsonFile } from \"../fs/json-store.js\";\n\n/**\n * Customer tonality (domino D8 / F2): per-customer (and global) tone profiles\n * applied automatically to generated communication. Customer profile fields\n * override the global default; the merged profile is rendered into a tone\n * instruction for the LLM (used by draft_email / sequences / journeys).\n */\nexport interface ToneProfile {\n formality?: string; // e.g. formal | casual | friendly\n language?: string; // e.g. de | en\n dos?: string[];\n donts?: string[];\n examples?: string[];\n}\n\nfunction globalPath(dataDir: string): string {\n return path.join(dataDir, \".agentic\", \"tone.json\");\n}\nfunction customerPath(dataDir: string, slug: string): string {\n return path.join(dataDir, \"customers\", slug, \"tone.json\");\n}\n\nfunction readProfile(p: string): ToneProfile {\n return readJsonFile<ToneProfile>(p, {});\n}\n\nexport function setTone(dataDir: string, profile: ToneProfile, slug?: string): void {\n const p = slug ? customerPath(dataDir, slug) : globalPath(dataDir);\n writeJsonFile(p, { ...readProfile(p), ...profile });\n}\n\n/** Effective profile: global as base, customer fields override. */\nexport function resolveTone(dataDir: string, slug?: string): ToneProfile {\n const global = readProfile(globalPath(dataDir));\n if (!slug) return global;\n return { ...global, ...readProfile(customerPath(dataDir, slug)) };\n}\n\n/** Render a tone profile into an instruction string (\"\" when blank). */\nexport function toneInstruction(profile: ToneProfile): string {\n const parts: string[] = [];\n if (profile.formality) parts.push(`tone: ${profile.formality}`);\n if (profile.language) parts.push(`language: ${profile.language}`);\n if (profile.dos && profile.dos.length) parts.push(`prefer: ${profile.dos.join(\", \")}`);\n if (profile.donts && profile.donts.length) parts.push(`avoid: ${profile.donts.join(\", \")}`);\n return parts.join(\"; \");\n}\n"],"mappings":";;;;;AAiBA,SAAS,WAAW,SAAyB;CAC3C,OAAO,KAAA,QAAK,KAAK,SAAS,YAAY,WAAW;AACnD;AACA,SAAS,aAAa,SAAiB,MAAsB;CAC3D,OAAO,KAAA,QAAK,KAAK,SAAS,aAAa,MAAM,WAAW;AAC1D;AAEA,SAAS,YAAY,GAAwB;CAC3C,OAAOA,sBAAAA,aAA0B,GAAG,CAAC,CAAC;AACxC;;AAQA,SAAgB,YAAY,SAAiB,MAA4B;CACvE,MAAM,SAAS,YAAY,WAAW,OAAO,CAAC;CAC9C,IAAI,CAAC,MAAM,OAAO;CAClB,OAAO;EAAE,GAAG;EAAQ,GAAG,YAAY,aAAa,SAAS,IAAI,CAAC;CAAE;AAClE;;AAGA,SAAgB,gBAAgB,SAA8B;CAC5D,MAAM,QAAkB,CAAC;CACzB,IAAI,QAAQ,WAAW,MAAM,KAAK,SAAS,QAAQ,WAAW;CAC9D,IAAI,QAAQ,UAAU,MAAM,KAAK,aAAa,QAAQ,UAAU;CAChE,IAAI,QAAQ,OAAO,QAAQ,IAAI,QAAQ,MAAM,KAAK,WAAW,QAAQ,IAAI,KAAK,IAAI,GAAG;CACrF,IAAI,QAAQ,SAAS,QAAQ,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,KAAK,IAAI,GAAG;CAC1F,OAAO,MAAM,KAAK,IAAI;AACxB"}
@@ -1,5 +1,5 @@
1
+ import { S as readJsonFile } from "./session-store-DWxJ5Pof.js";
1
2
  import path from "path";
2
- import fs from "fs";
3
3
  //#region src/core/tone.ts
4
4
  function globalPath(dataDir) {
5
5
  return path.join(dataDir, ".agentic", "tone.json");
@@ -8,12 +8,7 @@ function customerPath(dataDir, slug) {
8
8
  return path.join(dataDir, "customers", slug, "tone.json");
9
9
  }
10
10
  function readProfile(p) {
11
- if (!fs.existsSync(p)) return {};
12
- try {
13
- return JSON.parse(fs.readFileSync(p, "utf-8"));
14
- } catch {
15
- return {};
16
- }
11
+ return readJsonFile(p, {});
17
12
  }
18
13
  /** Effective profile: global as base, customer fields override. */
19
14
  function resolveTone(dataDir, slug) {
@@ -36,4 +31,4 @@ function toneInstruction(profile) {
36
31
  //#endregion
37
32
  export { resolveTone, toneInstruction };
38
33
 
39
- //# sourceMappingURL=tone-vNb2DAAD.js.map
34
+ //# sourceMappingURL=tone-mXSftvTn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tone-mXSftvTn.js","names":[],"sources":["../src/core/tone.ts"],"sourcesContent":["import path from \"path\";\nimport { readJsonFile, writeJsonFile } from \"../fs/json-store.js\";\n\n/**\n * Customer tonality (domino D8 / F2): per-customer (and global) tone profiles\n * applied automatically to generated communication. Customer profile fields\n * override the global default; the merged profile is rendered into a tone\n * instruction for the LLM (used by draft_email / sequences / journeys).\n */\nexport interface ToneProfile {\n formality?: string; // e.g. formal | casual | friendly\n language?: string; // e.g. de | en\n dos?: string[];\n donts?: string[];\n examples?: string[];\n}\n\nfunction globalPath(dataDir: string): string {\n return path.join(dataDir, \".agentic\", \"tone.json\");\n}\nfunction customerPath(dataDir: string, slug: string): string {\n return path.join(dataDir, \"customers\", slug, \"tone.json\");\n}\n\nfunction readProfile(p: string): ToneProfile {\n return readJsonFile<ToneProfile>(p, {});\n}\n\nexport function setTone(dataDir: string, profile: ToneProfile, slug?: string): void {\n const p = slug ? customerPath(dataDir, slug) : globalPath(dataDir);\n writeJsonFile(p, { ...readProfile(p), ...profile });\n}\n\n/** Effective profile: global as base, customer fields override. */\nexport function resolveTone(dataDir: string, slug?: string): ToneProfile {\n const global = readProfile(globalPath(dataDir));\n if (!slug) return global;\n return { ...global, ...readProfile(customerPath(dataDir, slug)) };\n}\n\n/** Render a tone profile into an instruction string (\"\" when blank). */\nexport function toneInstruction(profile: ToneProfile): string {\n const parts: string[] = [];\n if (profile.formality) parts.push(`tone: ${profile.formality}`);\n if (profile.language) parts.push(`language: ${profile.language}`);\n if (profile.dos && profile.dos.length) parts.push(`prefer: ${profile.dos.join(\", \")}`);\n if (profile.donts && profile.donts.length) parts.push(`avoid: ${profile.donts.join(\", \")}`);\n return parts.join(\"; \");\n}\n"],"mappings":";;;AAiBA,SAAS,WAAW,SAAyB;CAC3C,OAAO,KAAK,KAAK,SAAS,YAAY,WAAW;AACnD;AACA,SAAS,aAAa,SAAiB,MAAsB;CAC3D,OAAO,KAAK,KAAK,SAAS,aAAa,MAAM,WAAW;AAC1D;AAEA,SAAS,YAAY,GAAwB;CAC3C,OAAO,aAA0B,GAAG,CAAC,CAAC;AACxC;;AAQA,SAAgB,YAAY,SAAiB,MAA4B;CACvE,MAAM,SAAS,YAAY,WAAW,OAAO,CAAC;CAC9C,IAAI,CAAC,MAAM,OAAO;CAClB,OAAO;EAAE,GAAG;EAAQ,GAAG,YAAY,aAAa,SAAS,IAAI,CAAC;CAAE;AAClE;;AAGA,SAAgB,gBAAgB,SAA8B;CAC5D,MAAM,QAAkB,CAAC;CACzB,IAAI,QAAQ,WAAW,MAAM,KAAK,SAAS,QAAQ,WAAW;CAC9D,IAAI,QAAQ,UAAU,MAAM,KAAK,aAAa,QAAQ,UAAU;CAChE,IAAI,QAAQ,OAAO,QAAQ,IAAI,QAAQ,MAAM,KAAK,WAAW,QAAQ,IAAI,KAAK,IAAI,GAAG;CACrF,IAAI,QAAQ,SAAS,QAAQ,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,KAAK,IAAI,GAAG;CAC1F,OAAO,MAAM,KAAK,IAAI;AACxB"}
@@ -1,3 +1,5 @@
1
+ import { n as logger } from "./logger-Dyl4VcLO.js";
2
+ import { t as escapeRegExp } from "./regex-Jt5DatPi.js";
1
3
  import path from "path";
2
4
  import fs from "fs";
3
5
  import matter from "gray-matter";
@@ -19,14 +21,17 @@ function watchTranscripts(opts) {
19
21
  });
20
22
  watcher.on("add", (filePath) => {
21
23
  onFile(filePath).catch((err) => {
22
- console.error(`[transcript-watcher] Error processing ${filePath}:`, err.message);
24
+ logger.error("transcript-watcher", "error processing file", {
25
+ filePath,
26
+ error: err.message
27
+ });
23
28
  });
24
29
  });
25
30
  return watcher;
26
31
  }
27
32
  async function processTranscriptFile(filePath, slug, dataDir) {
28
33
  const source = `file://${filePath}`;
29
- const { readInteractions, appendInteraction } = await import("./interactions-writer-dSPy1XfO.js");
34
+ const { readInteractions, appendInteraction } = await import("./interactions-writer-RJB8SWf2.js");
30
35
  if ((await readInteractions(dataDir, slug)).includes(source)) return;
31
36
  const content = fs.readFileSync(filePath, "utf-8");
32
37
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -41,12 +46,12 @@ async function processTranscriptFile(filePath, slug, dataDir) {
41
46
  sourceRef: source,
42
47
  synced: (/* @__PURE__ */ new Date()).toISOString()
43
48
  });
44
- const { indexInLanceDB } = await import("./lancedb-CCBbpulq.js");
49
+ const { indexInLanceDB } = await import("./lancedb-CswQEE5K.js");
45
50
  await indexInLanceDB(dataDir, slug, content.slice(0, 2e3), source, {
46
51
  date,
47
52
  type: "Meeting"
48
53
  }).catch((err) => {
49
- process.stderr.write(`[transcript-watcher] LanceDB index failed: ${err.message}\n`);
54
+ logger.error("transcript-watcher", "LanceDB index failed", { error: err.message });
50
55
  });
51
56
  }
52
57
  function readCustomerName(customersDir, slug) {
@@ -68,8 +73,7 @@ function fuzzyMatchCustomer(filePath, content, candidates) {
68
73
  const nameLower = name.toLowerCase();
69
74
  const slugLower = slug.toLowerCase();
70
75
  if (filename.includes(slugLower) || filename.includes(nameLower.replace(/\s+/g, "-"))) score += 10;
71
- const escaped = nameLower.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
72
- score += contentPreview.match(new RegExp(escaped, "g"))?.length ?? 0;
76
+ score += contentPreview.match(new RegExp(escapeRegExp(nameLower), "g"))?.length ?? 0;
73
77
  if (score > 0 && (!best || score > best.score)) best = {
74
78
  slug,
75
79
  score
@@ -109,24 +113,27 @@ async function processTranscriptFileAutoMatch(filePath, dataDir) {
109
113
  */
110
114
  async function matchCustomer(filePath, content, candidates) {
111
115
  try {
112
- const { recognizeCustomer } = await import("./llm-DEjWcqmW.js");
116
+ const { recognizeCustomer } = await import("./llm-DSX1-wFu.js");
113
117
  const llm = await recognizeCustomer(content, candidates);
114
118
  if (llm.slug && llm.confidence !== "low" && candidates.some((c) => c.slug === llm.slug)) return llm.slug;
115
119
  } catch (err) {
116
- process.stderr.write(`[transcript-watcher] LLM recognition failed, using heuristic: ${err.message}\n`);
120
+ logger.warn("transcript-watcher", "LLM recognition failed, using heuristic", { error: err.message });
117
121
  }
118
122
  return fuzzyMatchCustomer(filePath, content, candidates)?.slug ?? null;
119
123
  }
120
124
  async function recordUnmatched(dataDir, filePath, reason) {
121
- const { appendUnmatched } = await import("./unmatched-transcripts-D0PrJ9iz.js");
125
+ const { appendUnmatched } = await import("./unmatched-transcripts-C92zAoM4.js");
122
126
  appendUnmatched(dataDir, {
123
127
  filePath,
124
128
  addedAt: (/* @__PURE__ */ new Date()).toISOString(),
125
129
  reason
126
130
  });
127
- process.stderr.write(`[transcript-watcher] Unmatched: ${filePath} (${reason})\n`);
131
+ logger.info("transcript-watcher", "unmatched transcript", {
132
+ filePath,
133
+ reason
134
+ });
128
135
  }
129
136
  //#endregion
130
137
  export { processTranscriptFile, processTranscriptFileAutoMatch, watchTranscripts };
131
138
 
132
- //# sourceMappingURL=transcript-watcher-CL2QUygI.js.map
139
+ //# sourceMappingURL=transcript-watcher-0mh2ZhmH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript-watcher-0mh2ZhmH.js","names":[],"sources":["../src/sync/transcript-watcher.ts"],"sourcesContent":["// src/sync/transcript-watcher.ts\n// chokidar v4 — NO glob support in watch(), use ignored as a function\nimport chokidar, { type FSWatcher } from \"chokidar\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport matter from \"gray-matter\";\nimport { escapeRegExp } from \"../core/regex.js\";\nimport { logger } from \"../core/logger.js\";\n\ninterface WatchOptions {\n paths: string[];\n extensions: string[];\n dataDir: string;\n onFile: (filePath: string) => Promise<void>;\n}\n\nexport function watchTranscripts(opts: WatchOptions): FSWatcher {\n const { paths, extensions, onFile } = opts;\n\n const watcher = chokidar.watch(paths, {\n // v4: ignored is a function (no glob strings)\n ignored: (p: string, stats?: fs.Stats) => {\n if (stats?.isDirectory()) return false;\n return !extensions.some((ext) => p.endsWith(ext));\n },\n awaitWriteFinish: { stabilityThreshold: 2000, pollInterval: 100 },\n ignoreInitial: false,\n persistent: true,\n });\n\n watcher.on(\"add\", (filePath) => {\n onFile(filePath).catch((err: unknown) => {\n logger.error(\"transcript-watcher\", \"error processing file\", {\n filePath,\n error: (err as Error).message,\n });\n });\n });\n\n return watcher;\n}\n\nexport async function processTranscriptFile(\n filePath: string,\n slug: string,\n dataDir: string\n): Promise<void> {\n const source = `file://${filePath}`;\n\n const { readInteractions, appendInteraction } = await import(\"../fs/interactions-writer.js\");\n const existing = await readInteractions(dataDir, slug);\n if (existing.includes(source)) return;\n\n const content = fs.readFileSync(filePath, \"utf-8\");\n const date = new Date().toISOString().slice(0, 10);\n const filename = filePath.split(\"/\").pop() ?? filePath;\n\n await appendInteraction(dataDir, slug, {\n date,\n type: \"Meeting\",\n with: filename,\n subject: filename,\n summary: content.slice(0, 500) + (content.length > 500 ? \"...\" : \"\"),\n nextSteps: [],\n sourceRef: source,\n synced: new Date().toISOString(),\n });\n\n const { indexInLanceDB } = await import(\"../core/lancedb.js\");\n await indexInLanceDB(dataDir, slug, content.slice(0, 2000), source, {\n date,\n type: \"Meeting\",\n }).catch((err: unknown) => {\n logger.error(\"transcript-watcher\", \"LanceDB index failed\", { error: (err as Error).message });\n });\n}\n\nfunction readCustomerName(customersDir: string, slug: string): string {\n const mainFactsPath = path.join(customersDir, slug, \"main_facts.md\");\n if (!fs.existsSync(mainFactsPath)) return slug;\n try {\n const raw = matter(fs.readFileSync(mainFactsPath, \"utf-8\"));\n return typeof raw.data[\"name\"] === \"string\" ? raw.data[\"name\"] : slug;\n } catch {\n return slug;\n }\n}\n\nfunction fuzzyMatchCustomer(\n filePath: string,\n content: string,\n candidates: Array<{ slug: string; name: string }>\n): { slug: string } | null {\n const filename = path.basename(filePath).toLowerCase();\n const contentPreview = content.toLowerCase().slice(0, 5_000);\n\n let best: { slug: string; score: number } | null = null;\n\n for (const { slug, name } of candidates) {\n let score = 0;\n const nameLower = name.toLowerCase();\n const slugLower = slug.toLowerCase();\n\n // Filename match is the strongest signal\n if (filename.includes(slugLower) || filename.includes(nameLower.replace(/\\s+/g, \"-\"))) {\n score += 10;\n }\n\n // Count name occurrences in content\n score += contentPreview.match(new RegExp(escapeRegExp(nameLower), \"g\"))?.length ?? 0;\n\n if (score > 0 && (!best || score > best.score)) {\n best = { slug, score };\n }\n }\n\n return best ? { slug: best.slug } : null;\n}\n\nexport async function processTranscriptFileAutoMatch(\n filePath: string,\n dataDir: string\n): Promise<void> {\n const customersDir = path.join(dataDir, \"customers\");\n if (!fs.existsSync(customersDir)) {\n await recordUnmatched(dataDir, filePath, \"no_customers_defined\");\n return;\n }\n\n const slugs = fs.readdirSync(customersDir).filter((s) => {\n try {\n return fs.statSync(path.join(customersDir, s)).isDirectory();\n } catch {\n return false;\n }\n });\n\n if (slugs.length === 0) {\n await recordUnmatched(dataDir, filePath, \"no_customers_defined\");\n return;\n }\n\n const content = fs.readFileSync(filePath, \"utf-8\");\n const candidates = slugs.map((slug) => ({\n slug,\n name: readCustomerName(customersDir, slug),\n }));\n\n const matchedSlug = await matchCustomer(filePath, content, candidates);\n\n if (matchedSlug) {\n await processTranscriptFile(filePath, matchedSlug, dataDir);\n } else {\n await recordUnmatched(dataDir, filePath, \"no_customer_match\");\n }\n}\n\n/**\n * Resolve a transcript to a customer slug. Prefers LLM recognition (when an\n * ANTHROPIC_API_KEY is configured) and falls back to the filename/content\n * heuristic. The LLM result is only trusted when it names a known candidate\n * with at least medium confidence — guarding against hallucinated slugs.\n */\nasync function matchCustomer(\n filePath: string,\n content: string,\n candidates: Array<{ slug: string; name: string }>\n): Promise<string | null> {\n try {\n const { recognizeCustomer } = await import(\"../core/llm.js\");\n const llm = await recognizeCustomer(content, candidates);\n if (llm.slug && llm.confidence !== \"low\" && candidates.some((c) => c.slug === llm.slug)) {\n return llm.slug;\n }\n } catch (err: unknown) {\n logger.warn(\"transcript-watcher\", \"LLM recognition failed, using heuristic\", {\n error: (err as Error).message,\n });\n }\n\n return fuzzyMatchCustomer(filePath, content, candidates)?.slug ?? null;\n}\n\nasync function recordUnmatched(\n dataDir: string,\n filePath: string,\n reason: \"no_customer_match\" | \"no_customers_defined\"\n): Promise<void> {\n const { appendUnmatched } = await import(\"../fs/unmatched-transcripts.js\");\n appendUnmatched(dataDir, { filePath, addedAt: new Date().toISOString(), reason });\n logger.info(\"transcript-watcher\", \"unmatched transcript\", { filePath, reason });\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { t as appendUnmatched } from "./unmatched-transcripts-DC-VQ9YS.js";
2
+ export { appendUnmatched };
@@ -0,0 +1,16 @@
1
+ import { i as writeJsonFile, n as readJsonFile } from "./json-store-WWsFzXub.js";
2
+ import path from "path";
3
+ //#region src/fs/unmatched-transcripts.ts
4
+ function getUnmatchedPath(dataDir) {
5
+ return path.join(dataDir, ".agentic", "unmatched-transcripts.json");
6
+ }
7
+ function readUnmatched(dataDir) {
8
+ return readJsonFile(getUnmatchedPath(dataDir), []);
9
+ }
10
+ function appendUnmatched(dataDir, entry) {
11
+ writeJsonFile(getUnmatchedPath(dataDir), [...readUnmatched(dataDir), entry]);
12
+ }
13
+ //#endregion
14
+ export { readUnmatched as n, appendUnmatched as t };
15
+
16
+ //# sourceMappingURL=unmatched-transcripts-DC-VQ9YS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unmatched-transcripts-DC-VQ9YS.js","names":[],"sources":["../src/fs/unmatched-transcripts.ts"],"sourcesContent":["import path from \"path\";\nimport { readJsonFile, writeJsonFile } from \"./json-store.js\";\n\nexport interface UnmatchedTranscript {\n filePath: string;\n addedAt: string; // ISO timestamp\n reason: \"no_customer_match\" | \"no_customers_defined\";\n}\n\nfunction getUnmatchedPath(dataDir: string): string {\n return path.join(dataDir, \".agentic\", \"unmatched-transcripts.json\");\n}\n\nexport function readUnmatched(dataDir: string): UnmatchedTranscript[] {\n return readJsonFile<UnmatchedTranscript[]>(getUnmatchedPath(dataDir), []);\n}\n\nexport function appendUnmatched(dataDir: string, entry: UnmatchedTranscript): void {\n writeJsonFile(getUnmatchedPath(dataDir), [...readUnmatched(dataDir), entry]);\n}\n\nexport function clearUnmatched(dataDir: string): void {\n writeJsonFile(getUnmatchedPath(dataDir), []);\n}\n"],"mappings":";;;AASA,SAAS,iBAAiB,SAAyB;CACjD,OAAO,KAAK,KAAK,SAAS,YAAY,4BAA4B;AACpE;AAEA,SAAgB,cAAc,SAAwC;CACpE,OAAO,aAAoC,iBAAiB,OAAO,GAAG,CAAC,CAAC;AAC1E;AAEA,SAAgB,gBAAgB,SAAiB,OAAkC;CACjF,cAAc,iBAAiB,OAAO,GAAG,CAAC,GAAG,cAAc,OAAO,GAAG,KAAK,CAAC;AAC7E"}
@@ -0,0 +1,2 @@
1
+ import { t as handleUpdateDeal } from "./update-deal-DSzr_Aau.js";
2
+ export { handleUpdateDeal };
@@ -1,6 +1,6 @@
1
1
  import { i as writeAuditEntry, n as getActor } from "./audit-log-DNMY9mUZ.js";
2
- import { a as enforceRbac } from "./rbac-CTIktZaC.js";
3
- import { r as upsertDeal } from "./pipeline-writer-BvVquKIe.js";
2
+ import { o as enforceRbac } from "./rbac-msmBc_tK.js";
3
+ import { r as upsertDeal } from "./pipeline-writer-CIllfnZl.js";
4
4
  import { z } from "zod";
5
5
  //#region src/mcp/tools/update-deal.ts
6
6
  const DATA_DIR = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
@@ -88,4 +88,4 @@ Returns: { success: boolean, deal: object }`,
88
88
  //#endregion
89
89
  export { registerUpdateDeal as n, handleUpdateDeal as t };
90
90
 
91
- //# sourceMappingURL=update-deal-DKC79skb.js.map
91
+ //# sourceMappingURL=update-deal-DSzr_Aau.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"update-deal-DKC79skb.js","names":[],"sources":["../src/mcp/tools/update-deal.ts"],"sourcesContent":["import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { upsertDeal } from \"../../fs/pipeline-writer.js\";\nimport type { PipelineDeal } from \"../../schemas/pipeline.js\";\nimport { writeAuditEntry, getActor } from \"../../fs/audit-log.js\";\nimport { enforceRbac } from \"../../core/rbac.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleUpdateDeal(\n input: {\n slug: string;\n dealName: string;\n stage?: string;\n value?: number;\n probability?: number;\n closeDate?: string;\n notes?: string;\n },\n dataDir: string = DATA_DIR\n): Promise<{\n content: Array<{ type: \"text\"; text: string }>;\n}> {\n const today = new Date().toISOString().split(\"T\")[0] as string;\n\n const deal: PipelineDeal = {\n name: input.dealName,\n stage: (input.stage as PipelineDeal[\"stage\"]) ?? \"lead\",\n currency: \"EUR\",\n updated: today,\n ...(input.value !== undefined ? { value: input.value } : {}),\n ...(input.probability !== undefined ? { probability: input.probability } : {}),\n ...(input.closeDate !== undefined ? { close_date: input.closeDate } : {}),\n ...(input.notes !== undefined ? { notes: input.notes } : {}),\n };\n\n try {\n enforceRbac(dataDir, \"update_deal\");\n\n await upsertDeal(dataDir, input.slug, deal);\n\n writeAuditEntry(dataDir, {\n timestamp: new Date().toISOString(),\n actor: getActor(),\n tool: \"update_deal\",\n slug: input.slug,\n summary: input.dealName,\n });\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n success: true,\n deal,\n },\n null,\n 2\n ),\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n success: false,\n error: (err as Error).message,\n },\n null,\n 2\n ),\n },\n ],\n };\n }\n}\n\nexport function registerUpdateDeal(server: McpServer): void {\n server.registerTool(\n \"update_deal\",\n {\n title: \"Update Deal\",\n description: `Update or create a deal in the customer's pipeline. Upserts by deal name.\nUse after pipeline discussions or when deal status changes.\n\nArgs:\n slug: Customer ID\n dealName: Deal name (used as unique key for upsert)\n stage: Deal stage (\"lead\" | \"qualified\" | \"proposal\" | \"negotiation\" | \"won\" | \"lost\")\n value: Deal value in euros\n probability: Win probability percentage (0-100)\n closeDate: Expected close date (YYYY-MM-DD)\n notes: Free-text notes about the deal\n\nReturns: { success: boolean, deal: object }`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer slug (e.g. 'acme-corp')\"),\n dealName: z.string().describe(\"Deal name (unique identifier for upsert)\"),\n stage: z\n .enum([\"lead\", \"qualified\", \"proposal\", \"negotiation\", \"won\", \"lost\"])\n .optional()\n .describe(\"Deal stage\"),\n value: z.number().optional().describe(\"Deal value in euros\"),\n probability: z.number().min(0).max(100).optional().describe(\"Win probability (0-100)\"),\n closeDate: z\n .string()\n .regex(/^\\d{4}-\\d{2}-\\d{2}$/)\n .optional()\n .describe(\"Expected close date (YYYY-MM-DD)\"),\n notes: z.string().optional().describe(\"Free-text notes about the deal\"),\n }),\n },\n async ({ slug, dealName, stage, value, probability, closeDate, notes }) =>\n handleUpdateDeal({\n slug,\n dealName,\n ...(stage !== undefined ? { stage } : {}),\n ...(value !== undefined ? { value } : {}),\n ...(probability !== undefined ? { probability } : {}),\n ...(closeDate !== undefined ? { closeDate } : {}),\n ...(notes !== undefined ? { notes } : {}),\n })\n );\n}\n"],"mappings":";;;;;AAOA,MAAM,WAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,iBACpB,OASA,UAAkB,UAGjB;CACD,MAAM,yBAAQ,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;CAElD,MAAM,OAAqB;EACzB,MAAM,MAAM;EACZ,OAAQ,MAAM,SAAmC;EACjD,UAAU;EACV,SAAS;EACT,GAAI,MAAM,UAAU,KAAA,IAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;EAC1D,GAAI,MAAM,gBAAgB,KAAA,IAAY,EAAE,aAAa,MAAM,YAAY,IAAI,CAAC;EAC5E,GAAI,MAAM,cAAc,KAAA,IAAY,EAAE,YAAY,MAAM,UAAU,IAAI,CAAC;EACvE,GAAI,MAAM,UAAU,KAAA,IAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;CAC5D;CAEA,IAAI;EACF,YAAY,SAAS,aAAa;EAElC,MAAM,WAAW,SAAS,MAAM,MAAM,IAAI;EAE1C,gBAAgB,SAAS;GACvB,4BAAW,IAAI,KAAK,GAAE,YAAY;GAClC,OAAO,SAAS;GAChB,MAAM;GACN,MAAM,MAAM;GACZ,SAAS,MAAM;EACjB,CAAC;EAED,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IACE,SAAS;IACT;GACF,GACA,MACA,CACF;EACF,CACF,EACF;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IACE,SAAS;IACT,OAAQ,IAAc;GACxB,GACA,MACA,CACF;EACF,CACF,EACF;CACF;AACF;AAEA,SAAgB,mBAAmB,QAAyB;CAC1D,OAAO,aACL,eACA;EACE,OAAO;EACP,aAAa;;;;;;;;;;;;;EAab,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,kCAAkC;GAC5D,UAAU,EAAE,OAAO,EAAE,SAAS,0CAA0C;GACxE,OAAO,EACJ,KAAK;IAAC;IAAQ;IAAa;IAAY;IAAe;IAAO;GAAM,CAAC,EACpE,SAAS,EACT,SAAS,YAAY;GACxB,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qBAAqB;GAC3D,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,yBAAyB;GACrF,WAAW,EACR,OAAO,EACP,MAAM,qBAAqB,EAC3B,SAAS,EACT,SAAS,kCAAkC;GAC9C,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,gCAAgC;EACxE,CAAC;CACH,GACA,OAAO,EAAE,MAAM,UAAU,OAAO,OAAO,aAAa,WAAW,YAC7D,iBAAiB;EACf;EACA;EACA,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;EACvC,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;EACvC,GAAI,gBAAgB,KAAA,IAAY,EAAE,YAAY,IAAI,CAAC;EACnD,GAAI,cAAc,KAAA,IAAY,EAAE,UAAU,IAAI,CAAC;EAC/C,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;CACzC,CAAC,CACL;AACF"}
1
+ {"version":3,"file":"update-deal-DSzr_Aau.js","names":[],"sources":["../src/mcp/tools/update-deal.ts"],"sourcesContent":["import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { upsertDeal } from \"../../fs/pipeline-writer.js\";\nimport type { PipelineDeal } from \"../../schemas/pipeline.js\";\nimport { writeAuditEntry, getActor } from \"../../fs/audit-log.js\";\nimport { enforceRbac } from \"../../core/rbac.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleUpdateDeal(\n input: {\n slug: string;\n dealName: string;\n stage?: string;\n value?: number;\n probability?: number;\n closeDate?: string;\n notes?: string;\n },\n dataDir: string = DATA_DIR\n): Promise<{\n content: Array<{ type: \"text\"; text: string }>;\n}> {\n const today = new Date().toISOString().split(\"T\")[0] as string;\n\n const deal: PipelineDeal = {\n name: input.dealName,\n stage: (input.stage as PipelineDeal[\"stage\"]) ?? \"lead\",\n currency: \"EUR\",\n updated: today,\n ...(input.value !== undefined ? { value: input.value } : {}),\n ...(input.probability !== undefined ? { probability: input.probability } : {}),\n ...(input.closeDate !== undefined ? { close_date: input.closeDate } : {}),\n ...(input.notes !== undefined ? { notes: input.notes } : {}),\n };\n\n try {\n enforceRbac(dataDir, \"update_deal\");\n\n await upsertDeal(dataDir, input.slug, deal);\n\n writeAuditEntry(dataDir, {\n timestamp: new Date().toISOString(),\n actor: getActor(),\n tool: \"update_deal\",\n slug: input.slug,\n summary: input.dealName,\n });\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n success: true,\n deal,\n },\n null,\n 2\n ),\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n success: false,\n error: (err as Error).message,\n },\n null,\n 2\n ),\n },\n ],\n };\n }\n}\n\nexport function registerUpdateDeal(server: McpServer): void {\n server.registerTool(\n \"update_deal\",\n {\n title: \"Update Deal\",\n description: `Update or create a deal in the customer's pipeline. Upserts by deal name.\nUse after pipeline discussions or when deal status changes.\n\nArgs:\n slug: Customer ID\n dealName: Deal name (used as unique key for upsert)\n stage: Deal stage (\"lead\" | \"qualified\" | \"proposal\" | \"negotiation\" | \"won\" | \"lost\")\n value: Deal value in euros\n probability: Win probability percentage (0-100)\n closeDate: Expected close date (YYYY-MM-DD)\n notes: Free-text notes about the deal\n\nReturns: { success: boolean, deal: object }`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer slug (e.g. 'acme-corp')\"),\n dealName: z.string().describe(\"Deal name (unique identifier for upsert)\"),\n stage: z\n .enum([\"lead\", \"qualified\", \"proposal\", \"negotiation\", \"won\", \"lost\"])\n .optional()\n .describe(\"Deal stage\"),\n value: z.number().optional().describe(\"Deal value in euros\"),\n probability: z.number().min(0).max(100).optional().describe(\"Win probability (0-100)\"),\n closeDate: z\n .string()\n .regex(/^\\d{4}-\\d{2}-\\d{2}$/)\n .optional()\n .describe(\"Expected close date (YYYY-MM-DD)\"),\n notes: z.string().optional().describe(\"Free-text notes about the deal\"),\n }),\n },\n async ({ slug, dealName, stage, value, probability, closeDate, notes }) =>\n handleUpdateDeal({\n slug,\n dealName,\n ...(stage !== undefined ? { stage } : {}),\n ...(value !== undefined ? { value } : {}),\n ...(probability !== undefined ? { probability } : {}),\n ...(closeDate !== undefined ? { closeDate } : {}),\n ...(notes !== undefined ? { notes } : {}),\n })\n );\n}\n"],"mappings":";;;;;AAOA,MAAM,WAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,iBACpB,OASA,UAAkB,UAGjB;CACD,MAAM,yBAAQ,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;CAElD,MAAM,OAAqB;EACzB,MAAM,MAAM;EACZ,OAAQ,MAAM,SAAmC;EACjD,UAAU;EACV,SAAS;EACT,GAAI,MAAM,UAAU,KAAA,IAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;EAC1D,GAAI,MAAM,gBAAgB,KAAA,IAAY,EAAE,aAAa,MAAM,YAAY,IAAI,CAAC;EAC5E,GAAI,MAAM,cAAc,KAAA,IAAY,EAAE,YAAY,MAAM,UAAU,IAAI,CAAC;EACvE,GAAI,MAAM,UAAU,KAAA,IAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;CAC5D;CAEA,IAAI;EACF,YAAY,SAAS,aAAa;EAElC,MAAM,WAAW,SAAS,MAAM,MAAM,IAAI;EAE1C,gBAAgB,SAAS;GACvB,4BAAW,IAAI,KAAK,GAAE,YAAY;GAClC,OAAO,SAAS;GAChB,MAAM;GACN,MAAM,MAAM;GACZ,SAAS,MAAM;EACjB,CAAC;EAED,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IACE,SAAS;IACT;GACF,GACA,MACA,CACF;EACF,CACF,EACF;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IACE,SAAS;IACT,OAAQ,IAAc;GACxB,GACA,MACA,CACF;EACF,CACF,EACF;CACF;AACF;AAEA,SAAgB,mBAAmB,QAAyB;CAC1D,OAAO,aACL,eACA;EACE,OAAO;EACP,aAAa;;;;;;;;;;;;;EAab,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,kCAAkC;GAC5D,UAAU,EAAE,OAAO,EAAE,SAAS,0CAA0C;GACxE,OAAO,EACJ,KAAK;IAAC;IAAQ;IAAa;IAAY;IAAe;IAAO;GAAM,CAAC,EACpE,SAAS,EACT,SAAS,YAAY;GACxB,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qBAAqB;GAC3D,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,yBAAyB;GACrF,WAAW,EACR,OAAO,EACP,MAAM,qBAAqB,EAC3B,SAAS,EACT,SAAS,kCAAkC;GAC9C,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,gCAAgC;EACxE,CAAC;CACH,GACA,OAAO,EAAE,MAAM,UAAU,OAAO,OAAO,aAAa,WAAW,YAC7D,iBAAiB;EACf;EACA;EACA,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;EACvC,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;EACvC,GAAI,gBAAgB,KAAA,IAAY,EAAE,YAAY,IAAI,CAAC;EACnD,GAAI,cAAc,KAAA,IAAY,EAAE,UAAU,IAAI,CAAC;EAC/C,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;CACzC,CAAC,CACL;AACF"}
@@ -51,11 +51,13 @@ function recordUsage(dataDir, u) {
51
51
  function loadUsage(dataDir) {
52
52
  const p = ledgerPath(dataDir);
53
53
  if (!fs.existsSync(p)) return [];
54
- try {
55
- return fs.readFileSync(p, "utf-8").split("\n").filter(Boolean).map((line) => JSON.parse(line));
56
- } catch {
57
- return [];
58
- }
54
+ return fs.readFileSync(p, "utf-8").split("\n").filter(Boolean).flatMap((line) => {
55
+ try {
56
+ return [JSON.parse(line)];
57
+ } catch {
58
+ return [];
59
+ }
60
+ });
59
61
  }
60
62
  function aggregateUsage(dataDir, opts = {}) {
61
63
  const agg = {
@@ -90,4 +92,4 @@ function aggregateUsage(dataDir, opts = {}) {
90
92
  //#endregion
91
93
  export { aggregateUsage, recordUsage };
92
94
 
93
- //# sourceMappingURL=usage-D0-TYJkw.js.map
95
+ //# sourceMappingURL=usage-BVlFlKW_.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage-BVlFlKW_.js","names":[],"sources":["../src/core/usage.ts"],"sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\n\n/**\n * LLM token-cost observability (domino D3 / F7). Every LLM call can record its\n * token usage + computed cost, attributed per customer/tool, into an append-only\n * NDJSON ledger. Basis for cost transparency and outcome/consumption pricing.\n */\nexport interface UsageEntry {\n timestamp: string;\n slug?: string;\n tool?: string;\n model: string;\n inputTokens: number;\n outputTokens: number;\n costUsd: number;\n}\n\nexport interface PricePerMillion {\n input: number;\n output: number;\n}\n\n// USD per 1M tokens. Override via .agentic/llm-pricing.json. Defaults are\n// conservative Haiku-class estimates — verify against current provider pricing.\nconst DEFAULT_PRICING: Record<string, PricePerMillion> = {\n \"claude-haiku-4-5\": { input: 1.0, output: 5.0 },\n default: { input: 1.0, output: 5.0 },\n};\n\nfunction ledgerPath(dataDir: string): string {\n return path.join(dataDir, \".agentic\", \"usage.ndjson\");\n}\n\nfunction loadPricing(dataDir: string): Record<string, PricePerMillion> {\n const p = path.join(dataDir, \".agentic\", \"llm-pricing.json\");\n if (!fs.existsSync(p)) return DEFAULT_PRICING;\n try {\n const custom = JSON.parse(fs.readFileSync(p, \"utf-8\") as string) as Record<\n string,\n PricePerMillion\n >;\n return { ...DEFAULT_PRICING, ...custom };\n } catch {\n return DEFAULT_PRICING;\n }\n}\n\nexport function computeCost(\n pricing: Record<string, PricePerMillion>,\n model: string,\n inputTokens: number,\n outputTokens: number\n): number {\n const price = pricing[model] ?? pricing[\"default\"]!;\n const cost = (inputTokens / 1_000_000) * price.input + (outputTokens / 1_000_000) * price.output;\n return Math.round(cost * 1_000_000) / 1_000_000;\n}\n\nexport function recordUsage(\n dataDir: string,\n u: { slug?: string; tool?: string; model: string; inputTokens: number; outputTokens: number }\n): void {\n const entry: UsageEntry = {\n timestamp: new Date().toISOString(),\n ...(u.slug ? { slug: u.slug } : {}),\n ...(u.tool ? { tool: u.tool } : {}),\n model: u.model,\n inputTokens: u.inputTokens,\n outputTokens: u.outputTokens,\n costUsd: computeCost(loadPricing(dataDir), u.model, u.inputTokens, u.outputTokens),\n };\n const p = ledgerPath(dataDir);\n try {\n fs.mkdirSync(path.dirname(p), { recursive: true });\n fs.appendFileSync(p, JSON.stringify(entry) + \"\\n\", \"utf-8\");\n } catch {\n /* non-fatal: usage logging must never break an LLM call */\n }\n}\n\nexport function loadUsage(dataDir: string): UsageEntry[] {\n const p = ledgerPath(dataDir);\n if (!fs.existsSync(p)) return [];\n // Parse line-by-line and skip any malformed line (e.g. a torn final append\n // from a crash) rather than discarding the entire ledger.\n return (fs.readFileSync(p, \"utf-8\") as string)\n .split(\"\\n\")\n .filter(Boolean)\n .flatMap((line) => {\n try {\n return [JSON.parse(line) as UsageEntry];\n } catch {\n return [];\n }\n });\n}\n\nexport interface UsageAggregate {\n totalInputTokens: number;\n totalOutputTokens: number;\n totalCostUsd: number;\n calls: number;\n bySlug: Record<\n string,\n { inputTokens: number; outputTokens: number; costUsd: number; calls: number }\n >;\n}\n\nexport function aggregateUsage(dataDir: string, opts: { slug?: string } = {}): UsageAggregate {\n const agg: UsageAggregate = {\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCostUsd: 0,\n calls: 0,\n bySlug: {},\n };\n for (const e of loadUsage(dataDir)) {\n if (opts.slug && e.slug !== opts.slug) continue;\n agg.totalInputTokens += e.inputTokens;\n agg.totalOutputTokens += e.outputTokens;\n agg.totalCostUsd += e.costUsd;\n agg.calls++;\n const key = e.slug ?? \"(unattributed)\";\n const b = agg.bySlug[key] ?? { inputTokens: 0, outputTokens: 0, costUsd: 0, calls: 0 };\n b.inputTokens += e.inputTokens;\n b.outputTokens += e.outputTokens;\n b.costUsd += e.costUsd;\n b.calls++;\n agg.bySlug[key] = b;\n }\n agg.totalCostUsd = Math.round(agg.totalCostUsd * 1_000_000) / 1_000_000;\n return agg;\n}\n"],"mappings":";;;AAyBA,MAAM,kBAAmD;CACvD,oBAAoB;EAAE,OAAO;EAAK,QAAQ;CAAI;CAC9C,SAAS;EAAE,OAAO;EAAK,QAAQ;CAAI;AACrC;AAEA,SAAS,WAAW,SAAyB;CAC3C,OAAO,KAAK,KAAK,SAAS,YAAY,cAAc;AACtD;AAEA,SAAS,YAAY,SAAkD;CACrE,MAAM,IAAI,KAAK,KAAK,SAAS,YAAY,kBAAkB;CAC3D,IAAI,CAAC,GAAG,WAAW,CAAC,GAAG,OAAO;CAC9B,IAAI;EACF,MAAM,SAAS,KAAK,MAAM,GAAG,aAAa,GAAG,OAAO,CAAW;EAI/D,OAAO;GAAE,GAAG;GAAiB,GAAG;EAAO;CACzC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAgB,YACd,SACA,OACA,aACA,cACQ;CACR,MAAM,QAAQ,QAAQ,UAAU,QAAQ;CACxC,MAAM,OAAQ,cAAc,MAAa,MAAM,QAAS,eAAe,MAAa,MAAM;CAC1F,OAAO,KAAK,MAAM,OAAO,GAAS,IAAI;AACxC;AAEA,SAAgB,YACd,SACA,GACM;CACN,MAAM,QAAoB;EACxB,4BAAW,IAAI,KAAK,GAAE,YAAY;EAClC,GAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;EACjC,GAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;EACjC,OAAO,EAAE;EACT,aAAa,EAAE;EACf,cAAc,EAAE;EAChB,SAAS,YAAY,YAAY,OAAO,GAAG,EAAE,OAAO,EAAE,aAAa,EAAE,YAAY;CACnF;CACA,MAAM,IAAI,WAAW,OAAO;CAC5B,IAAI;EACF,GAAG,UAAU,KAAK,QAAQ,CAAC,GAAG,EAAE,WAAW,KAAK,CAAC;EACjD,GAAG,eAAe,GAAG,KAAK,UAAU,KAAK,IAAI,MAAM,OAAO;CAC5D,QAAQ,CAER;AACF;AAEA,SAAgB,UAAU,SAA+B;CACvD,MAAM,IAAI,WAAW,OAAO;CAC5B,IAAI,CAAC,GAAG,WAAW,CAAC,GAAG,OAAO,CAAC;CAG/B,OAAQ,GAAG,aAAa,GAAG,OAAO,EAC/B,MAAM,IAAI,EACV,OAAO,OAAO,EACd,SAAS,SAAS;EACjB,IAAI;GACF,OAAO,CAAC,KAAK,MAAM,IAAI,CAAe;EACxC,QAAQ;GACN,OAAO,CAAC;EACV;CACF,CAAC;AACL;AAaA,SAAgB,eAAe,SAAiB,OAA0B,CAAC,GAAmB;CAC5F,MAAM,MAAsB;EAC1B,kBAAkB;EAClB,mBAAmB;EACnB,cAAc;EACd,OAAO;EACP,QAAQ,CAAC;CACX;CACA,KAAK,MAAM,KAAK,UAAU,OAAO,GAAG;EAClC,IAAI,KAAK,QAAQ,EAAE,SAAS,KAAK,MAAM;EACvC,IAAI,oBAAoB,EAAE;EAC1B,IAAI,qBAAqB,EAAE;EAC3B,IAAI,gBAAgB,EAAE;EACtB,IAAI;EACJ,MAAM,MAAM,EAAE,QAAQ;EACtB,MAAM,IAAI,IAAI,OAAO,QAAQ;GAAE,aAAa;GAAG,cAAc;GAAG,SAAS;GAAG,OAAO;EAAE;EACrF,EAAE,eAAe,EAAE;EACnB,EAAE,gBAAgB,EAAE;EACpB,EAAE,WAAW,EAAE;EACf,EAAE;EACF,IAAI,OAAO,OAAO;CACpB;CACA,IAAI,eAAe,KAAK,MAAM,IAAI,eAAe,GAAS,IAAI;CAC9D,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"usage-CClTf5e6.cjs","names":[],"sources":["../src/core/usage.ts"],"sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\n\n/**\n * LLM token-cost observability (domino D3 / F7). Every LLM call can record its\n * token usage + computed cost, attributed per customer/tool, into an append-only\n * NDJSON ledger. Basis for cost transparency and outcome/consumption pricing.\n */\nexport interface UsageEntry {\n timestamp: string;\n slug?: string;\n tool?: string;\n model: string;\n inputTokens: number;\n outputTokens: number;\n costUsd: number;\n}\n\nexport interface PricePerMillion {\n input: number;\n output: number;\n}\n\n// USD per 1M tokens. Override via .agentic/llm-pricing.json. Defaults are\n// conservative Haiku-class estimates — verify against current provider pricing.\nconst DEFAULT_PRICING: Record<string, PricePerMillion> = {\n \"claude-haiku-4-5\": { input: 1.0, output: 5.0 },\n default: { input: 1.0, output: 5.0 },\n};\n\nfunction ledgerPath(dataDir: string): string {\n return path.join(dataDir, \".agentic\", \"usage.ndjson\");\n}\n\nfunction loadPricing(dataDir: string): Record<string, PricePerMillion> {\n const p = path.join(dataDir, \".agentic\", \"llm-pricing.json\");\n if (!fs.existsSync(p)) return DEFAULT_PRICING;\n try {\n const custom = JSON.parse(fs.readFileSync(p, \"utf-8\") as string) as Record<\n string,\n PricePerMillion\n >;\n return { ...DEFAULT_PRICING, ...custom };\n } catch {\n return DEFAULT_PRICING;\n }\n}\n\nexport function computeCost(\n pricing: Record<string, PricePerMillion>,\n model: string,\n inputTokens: number,\n outputTokens: number\n): number {\n const price = pricing[model] ?? pricing[\"default\"]!;\n const cost = (inputTokens / 1_000_000) * price.input + (outputTokens / 1_000_000) * price.output;\n return Math.round(cost * 1_000_000) / 1_000_000;\n}\n\nexport function recordUsage(\n dataDir: string,\n u: { slug?: string; tool?: string; model: string; inputTokens: number; outputTokens: number }\n): void {\n const entry: UsageEntry = {\n timestamp: new Date().toISOString(),\n ...(u.slug ? { slug: u.slug } : {}),\n ...(u.tool ? { tool: u.tool } : {}),\n model: u.model,\n inputTokens: u.inputTokens,\n outputTokens: u.outputTokens,\n costUsd: computeCost(loadPricing(dataDir), u.model, u.inputTokens, u.outputTokens),\n };\n const p = ledgerPath(dataDir);\n try {\n fs.mkdirSync(path.dirname(p), { recursive: true });\n fs.appendFileSync(p, JSON.stringify(entry) + \"\\n\", \"utf-8\");\n } catch {\n /* non-fatal: usage logging must never break an LLM call */\n }\n}\n\nexport function loadUsage(dataDir: string): UsageEntry[] {\n const p = ledgerPath(dataDir);\n if (!fs.existsSync(p)) return [];\n try {\n return (fs.readFileSync(p, \"utf-8\") as string)\n .split(\"\\n\")\n .filter(Boolean)\n .map((line) => JSON.parse(line) as UsageEntry);\n } catch {\n return [];\n }\n}\n\nexport interface UsageAggregate {\n totalInputTokens: number;\n totalOutputTokens: number;\n totalCostUsd: number;\n calls: number;\n bySlug: Record<\n string,\n { inputTokens: number; outputTokens: number; costUsd: number; calls: number }\n >;\n}\n\nexport function aggregateUsage(dataDir: string, opts: { slug?: string } = {}): UsageAggregate {\n const agg: UsageAggregate = {\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCostUsd: 0,\n calls: 0,\n bySlug: {},\n };\n for (const e of loadUsage(dataDir)) {\n if (opts.slug && e.slug !== opts.slug) continue;\n agg.totalInputTokens += e.inputTokens;\n agg.totalOutputTokens += e.outputTokens;\n agg.totalCostUsd += e.costUsd;\n agg.calls++;\n const key = e.slug ?? \"(unattributed)\";\n const b = agg.bySlug[key] ?? { inputTokens: 0, outputTokens: 0, costUsd: 0, calls: 0 };\n b.inputTokens += e.inputTokens;\n b.outputTokens += e.outputTokens;\n b.costUsd += e.costUsd;\n b.calls++;\n agg.bySlug[key] = b;\n }\n agg.totalCostUsd = Math.round(agg.totalCostUsd * 1_000_000) / 1_000_000;\n return agg;\n}\n"],"mappings":";;;;;;AAyBA,MAAM,kBAAmD;CACvD,oBAAoB;EAAE,OAAO;EAAK,QAAQ;CAAI;CAC9C,SAAS;EAAE,OAAO;EAAK,QAAQ;CAAI;AACrC;AAEA,SAAS,WAAW,SAAyB;CAC3C,OAAO,KAAA,QAAK,KAAK,SAAS,YAAY,cAAc;AACtD;AAEA,SAAS,YAAY,SAAkD;CACrE,MAAM,IAAI,KAAA,QAAK,KAAK,SAAS,YAAY,kBAAkB;CAC3D,IAAI,CAAC,GAAA,QAAG,WAAW,CAAC,GAAG,OAAO;CAC9B,IAAI;EACF,MAAM,SAAS,KAAK,MAAM,GAAA,QAAG,aAAa,GAAG,OAAO,CAAW;EAI/D,OAAO;GAAE,GAAG;GAAiB,GAAG;EAAO;CACzC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAgB,YACd,SACA,OACA,aACA,cACQ;CACR,MAAM,QAAQ,QAAQ,UAAU,QAAQ;CACxC,MAAM,OAAQ,cAAc,MAAa,MAAM,QAAS,eAAe,MAAa,MAAM;CAC1F,OAAO,KAAK,MAAM,OAAO,GAAS,IAAI;AACxC;AAEA,SAAgB,YACd,SACA,GACM;CACN,MAAM,QAAoB;EACxB,4BAAW,IAAI,KAAK,GAAE,YAAY;EAClC,GAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;EACjC,GAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;EACjC,OAAO,EAAE;EACT,aAAa,EAAE;EACf,cAAc,EAAE;EAChB,SAAS,YAAY,YAAY,OAAO,GAAG,EAAE,OAAO,EAAE,aAAa,EAAE,YAAY;CACnF;CACA,MAAM,IAAI,WAAW,OAAO;CAC5B,IAAI;EACF,GAAA,QAAG,UAAU,KAAA,QAAK,QAAQ,CAAC,GAAG,EAAE,WAAW,KAAK,CAAC;EACjD,GAAA,QAAG,eAAe,GAAG,KAAK,UAAU,KAAK,IAAI,MAAM,OAAO;CAC5D,QAAQ,CAER;AACF"}
1
+ {"version":3,"file":"usage-CClTf5e6.cjs","names":[],"sources":["../src/core/usage.ts"],"sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\n\n/**\n * LLM token-cost observability (domino D3 / F7). Every LLM call can record its\n * token usage + computed cost, attributed per customer/tool, into an append-only\n * NDJSON ledger. Basis for cost transparency and outcome/consumption pricing.\n */\nexport interface UsageEntry {\n timestamp: string;\n slug?: string;\n tool?: string;\n model: string;\n inputTokens: number;\n outputTokens: number;\n costUsd: number;\n}\n\nexport interface PricePerMillion {\n input: number;\n output: number;\n}\n\n// USD per 1M tokens. Override via .agentic/llm-pricing.json. Defaults are\n// conservative Haiku-class estimates — verify against current provider pricing.\nconst DEFAULT_PRICING: Record<string, PricePerMillion> = {\n \"claude-haiku-4-5\": { input: 1.0, output: 5.0 },\n default: { input: 1.0, output: 5.0 },\n};\n\nfunction ledgerPath(dataDir: string): string {\n return path.join(dataDir, \".agentic\", \"usage.ndjson\");\n}\n\nfunction loadPricing(dataDir: string): Record<string, PricePerMillion> {\n const p = path.join(dataDir, \".agentic\", \"llm-pricing.json\");\n if (!fs.existsSync(p)) return DEFAULT_PRICING;\n try {\n const custom = JSON.parse(fs.readFileSync(p, \"utf-8\") as string) as Record<\n string,\n PricePerMillion\n >;\n return { ...DEFAULT_PRICING, ...custom };\n } catch {\n return DEFAULT_PRICING;\n }\n}\n\nexport function computeCost(\n pricing: Record<string, PricePerMillion>,\n model: string,\n inputTokens: number,\n outputTokens: number\n): number {\n const price = pricing[model] ?? pricing[\"default\"]!;\n const cost = (inputTokens / 1_000_000) * price.input + (outputTokens / 1_000_000) * price.output;\n return Math.round(cost * 1_000_000) / 1_000_000;\n}\n\nexport function recordUsage(\n dataDir: string,\n u: { slug?: string; tool?: string; model: string; inputTokens: number; outputTokens: number }\n): void {\n const entry: UsageEntry = {\n timestamp: new Date().toISOString(),\n ...(u.slug ? { slug: u.slug } : {}),\n ...(u.tool ? { tool: u.tool } : {}),\n model: u.model,\n inputTokens: u.inputTokens,\n outputTokens: u.outputTokens,\n costUsd: computeCost(loadPricing(dataDir), u.model, u.inputTokens, u.outputTokens),\n };\n const p = ledgerPath(dataDir);\n try {\n fs.mkdirSync(path.dirname(p), { recursive: true });\n fs.appendFileSync(p, JSON.stringify(entry) + \"\\n\", \"utf-8\");\n } catch {\n /* non-fatal: usage logging must never break an LLM call */\n }\n}\n\nexport function loadUsage(dataDir: string): UsageEntry[] {\n const p = ledgerPath(dataDir);\n if (!fs.existsSync(p)) return [];\n // Parse line-by-line and skip any malformed line (e.g. a torn final append\n // from a crash) rather than discarding the entire ledger.\n return (fs.readFileSync(p, \"utf-8\") as string)\n .split(\"\\n\")\n .filter(Boolean)\n .flatMap((line) => {\n try {\n return [JSON.parse(line) as UsageEntry];\n } catch {\n return [];\n }\n });\n}\n\nexport interface UsageAggregate {\n totalInputTokens: number;\n totalOutputTokens: number;\n totalCostUsd: number;\n calls: number;\n bySlug: Record<\n string,\n { inputTokens: number; outputTokens: number; costUsd: number; calls: number }\n >;\n}\n\nexport function aggregateUsage(dataDir: string, opts: { slug?: string } = {}): UsageAggregate {\n const agg: UsageAggregate = {\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCostUsd: 0,\n calls: 0,\n bySlug: {},\n };\n for (const e of loadUsage(dataDir)) {\n if (opts.slug && e.slug !== opts.slug) continue;\n agg.totalInputTokens += e.inputTokens;\n agg.totalOutputTokens += e.outputTokens;\n agg.totalCostUsd += e.costUsd;\n agg.calls++;\n const key = e.slug ?? \"(unattributed)\";\n const b = agg.bySlug[key] ?? { inputTokens: 0, outputTokens: 0, costUsd: 0, calls: 0 };\n b.inputTokens += e.inputTokens;\n b.outputTokens += e.outputTokens;\n b.costUsd += e.costUsd;\n b.calls++;\n agg.bySlug[key] = b;\n }\n agg.totalCostUsd = Math.round(agg.totalCostUsd * 1_000_000) / 1_000_000;\n return agg;\n}\n"],"mappings":";;;;;;AAyBA,MAAM,kBAAmD;CACvD,oBAAoB;EAAE,OAAO;EAAK,QAAQ;CAAI;CAC9C,SAAS;EAAE,OAAO;EAAK,QAAQ;CAAI;AACrC;AAEA,SAAS,WAAW,SAAyB;CAC3C,OAAO,KAAA,QAAK,KAAK,SAAS,YAAY,cAAc;AACtD;AAEA,SAAS,YAAY,SAAkD;CACrE,MAAM,IAAI,KAAA,QAAK,KAAK,SAAS,YAAY,kBAAkB;CAC3D,IAAI,CAAC,GAAA,QAAG,WAAW,CAAC,GAAG,OAAO;CAC9B,IAAI;EACF,MAAM,SAAS,KAAK,MAAM,GAAA,QAAG,aAAa,GAAG,OAAO,CAAW;EAI/D,OAAO;GAAE,GAAG;GAAiB,GAAG;EAAO;CACzC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAgB,YACd,SACA,OACA,aACA,cACQ;CACR,MAAM,QAAQ,QAAQ,UAAU,QAAQ;CACxC,MAAM,OAAQ,cAAc,MAAa,MAAM,QAAS,eAAe,MAAa,MAAM;CAC1F,OAAO,KAAK,MAAM,OAAO,GAAS,IAAI;AACxC;AAEA,SAAgB,YACd,SACA,GACM;CACN,MAAM,QAAoB;EACxB,4BAAW,IAAI,KAAK,GAAE,YAAY;EAClC,GAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;EACjC,GAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;EACjC,OAAO,EAAE;EACT,aAAa,EAAE;EACf,cAAc,EAAE;EAChB,SAAS,YAAY,YAAY,OAAO,GAAG,EAAE,OAAO,EAAE,aAAa,EAAE,YAAY;CACnF;CACA,MAAM,IAAI,WAAW,OAAO;CAC5B,IAAI;EACF,GAAA,QAAG,UAAU,KAAA,QAAK,QAAQ,CAAC,GAAG,EAAE,WAAW,KAAK,CAAC;EACjD,GAAA,QAAG,eAAe,GAAG,KAAK,UAAU,KAAK,IAAI,MAAM,OAAO;CAC5D,QAAQ,CAER;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"usage-D0u9a-lV.js","names":[],"sources":["../src/core/usage.ts"],"sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\n\n/**\n * LLM token-cost observability (domino D3 / F7). Every LLM call can record its\n * token usage + computed cost, attributed per customer/tool, into an append-only\n * NDJSON ledger. Basis for cost transparency and outcome/consumption pricing.\n */\nexport interface UsageEntry {\n timestamp: string;\n slug?: string;\n tool?: string;\n model: string;\n inputTokens: number;\n outputTokens: number;\n costUsd: number;\n}\n\nexport interface PricePerMillion {\n input: number;\n output: number;\n}\n\n// USD per 1M tokens. Override via .agentic/llm-pricing.json. Defaults are\n// conservative Haiku-class estimates — verify against current provider pricing.\nconst DEFAULT_PRICING: Record<string, PricePerMillion> = {\n \"claude-haiku-4-5\": { input: 1.0, output: 5.0 },\n default: { input: 1.0, output: 5.0 },\n};\n\nfunction ledgerPath(dataDir: string): string {\n return path.join(dataDir, \".agentic\", \"usage.ndjson\");\n}\n\nfunction loadPricing(dataDir: string): Record<string, PricePerMillion> {\n const p = path.join(dataDir, \".agentic\", \"llm-pricing.json\");\n if (!fs.existsSync(p)) return DEFAULT_PRICING;\n try {\n const custom = JSON.parse(fs.readFileSync(p, \"utf-8\") as string) as Record<\n string,\n PricePerMillion\n >;\n return { ...DEFAULT_PRICING, ...custom };\n } catch {\n return DEFAULT_PRICING;\n }\n}\n\nexport function computeCost(\n pricing: Record<string, PricePerMillion>,\n model: string,\n inputTokens: number,\n outputTokens: number\n): number {\n const price = pricing[model] ?? pricing[\"default\"]!;\n const cost = (inputTokens / 1_000_000) * price.input + (outputTokens / 1_000_000) * price.output;\n return Math.round(cost * 1_000_000) / 1_000_000;\n}\n\nexport function recordUsage(\n dataDir: string,\n u: { slug?: string; tool?: string; model: string; inputTokens: number; outputTokens: number }\n): void {\n const entry: UsageEntry = {\n timestamp: new Date().toISOString(),\n ...(u.slug ? { slug: u.slug } : {}),\n ...(u.tool ? { tool: u.tool } : {}),\n model: u.model,\n inputTokens: u.inputTokens,\n outputTokens: u.outputTokens,\n costUsd: computeCost(loadPricing(dataDir), u.model, u.inputTokens, u.outputTokens),\n };\n const p = ledgerPath(dataDir);\n try {\n fs.mkdirSync(path.dirname(p), { recursive: true });\n fs.appendFileSync(p, JSON.stringify(entry) + \"\\n\", \"utf-8\");\n } catch {\n /* non-fatal: usage logging must never break an LLM call */\n }\n}\n\nexport function loadUsage(dataDir: string): UsageEntry[] {\n const p = ledgerPath(dataDir);\n if (!fs.existsSync(p)) return [];\n try {\n return (fs.readFileSync(p, \"utf-8\") as string)\n .split(\"\\n\")\n .filter(Boolean)\n .map((line) => JSON.parse(line) as UsageEntry);\n } catch {\n return [];\n }\n}\n\nexport interface UsageAggregate {\n totalInputTokens: number;\n totalOutputTokens: number;\n totalCostUsd: number;\n calls: number;\n bySlug: Record<\n string,\n { inputTokens: number; outputTokens: number; costUsd: number; calls: number }\n >;\n}\n\nexport function aggregateUsage(dataDir: string, opts: { slug?: string } = {}): UsageAggregate {\n const agg: UsageAggregate = {\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCostUsd: 0,\n calls: 0,\n bySlug: {},\n };\n for (const e of loadUsage(dataDir)) {\n if (opts.slug && e.slug !== opts.slug) continue;\n agg.totalInputTokens += e.inputTokens;\n agg.totalOutputTokens += e.outputTokens;\n agg.totalCostUsd += e.costUsd;\n agg.calls++;\n const key = e.slug ?? \"(unattributed)\";\n const b = agg.bySlug[key] ?? { inputTokens: 0, outputTokens: 0, costUsd: 0, calls: 0 };\n b.inputTokens += e.inputTokens;\n b.outputTokens += e.outputTokens;\n b.costUsd += e.costUsd;\n b.calls++;\n agg.bySlug[key] = b;\n }\n agg.totalCostUsd = Math.round(agg.totalCostUsd * 1_000_000) / 1_000_000;\n return agg;\n}\n"],"mappings":";;;AAyBA,MAAM,kBAAmD;CACvD,oBAAoB;EAAE,OAAO;EAAK,QAAQ;CAAI;CAC9C,SAAS;EAAE,OAAO;EAAK,QAAQ;CAAI;AACrC;AAEA,SAAS,WAAW,SAAyB;CAC3C,OAAO,KAAK,KAAK,SAAS,YAAY,cAAc;AACtD;AAEA,SAAS,YAAY,SAAkD;CACrE,MAAM,IAAI,KAAK,KAAK,SAAS,YAAY,kBAAkB;CAC3D,IAAI,CAAC,GAAG,WAAW,CAAC,GAAG,OAAO;CAC9B,IAAI;EACF,MAAM,SAAS,KAAK,MAAM,GAAG,aAAa,GAAG,OAAO,CAAW;EAI/D,OAAO;GAAE,GAAG;GAAiB,GAAG;EAAO;CACzC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAgB,YACd,SACA,OACA,aACA,cACQ;CACR,MAAM,QAAQ,QAAQ,UAAU,QAAQ;CACxC,MAAM,OAAQ,cAAc,MAAa,MAAM,QAAS,eAAe,MAAa,MAAM;CAC1F,OAAO,KAAK,MAAM,OAAO,GAAS,IAAI;AACxC;AAEA,SAAgB,YACd,SACA,GACM;CACN,MAAM,QAAoB;EACxB,4BAAW,IAAI,KAAK,GAAE,YAAY;EAClC,GAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;EACjC,GAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;EACjC,OAAO,EAAE;EACT,aAAa,EAAE;EACf,cAAc,EAAE;EAChB,SAAS,YAAY,YAAY,OAAO,GAAG,EAAE,OAAO,EAAE,aAAa,EAAE,YAAY;CACnF;CACA,MAAM,IAAI,WAAW,OAAO;CAC5B,IAAI;EACF,GAAG,UAAU,KAAK,QAAQ,CAAC,GAAG,EAAE,WAAW,KAAK,CAAC;EACjD,GAAG,eAAe,GAAG,KAAK,UAAU,KAAK,IAAI,MAAM,OAAO;CAC5D,QAAQ,CAER;AACF"}
1
+ {"version":3,"file":"usage-D0u9a-lV.js","names":[],"sources":["../src/core/usage.ts"],"sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\n\n/**\n * LLM token-cost observability (domino D3 / F7). Every LLM call can record its\n * token usage + computed cost, attributed per customer/tool, into an append-only\n * NDJSON ledger. Basis for cost transparency and outcome/consumption pricing.\n */\nexport interface UsageEntry {\n timestamp: string;\n slug?: string;\n tool?: string;\n model: string;\n inputTokens: number;\n outputTokens: number;\n costUsd: number;\n}\n\nexport interface PricePerMillion {\n input: number;\n output: number;\n}\n\n// USD per 1M tokens. Override via .agentic/llm-pricing.json. Defaults are\n// conservative Haiku-class estimates — verify against current provider pricing.\nconst DEFAULT_PRICING: Record<string, PricePerMillion> = {\n \"claude-haiku-4-5\": { input: 1.0, output: 5.0 },\n default: { input: 1.0, output: 5.0 },\n};\n\nfunction ledgerPath(dataDir: string): string {\n return path.join(dataDir, \".agentic\", \"usage.ndjson\");\n}\n\nfunction loadPricing(dataDir: string): Record<string, PricePerMillion> {\n const p = path.join(dataDir, \".agentic\", \"llm-pricing.json\");\n if (!fs.existsSync(p)) return DEFAULT_PRICING;\n try {\n const custom = JSON.parse(fs.readFileSync(p, \"utf-8\") as string) as Record<\n string,\n PricePerMillion\n >;\n return { ...DEFAULT_PRICING, ...custom };\n } catch {\n return DEFAULT_PRICING;\n }\n}\n\nexport function computeCost(\n pricing: Record<string, PricePerMillion>,\n model: string,\n inputTokens: number,\n outputTokens: number\n): number {\n const price = pricing[model] ?? pricing[\"default\"]!;\n const cost = (inputTokens / 1_000_000) * price.input + (outputTokens / 1_000_000) * price.output;\n return Math.round(cost * 1_000_000) / 1_000_000;\n}\n\nexport function recordUsage(\n dataDir: string,\n u: { slug?: string; tool?: string; model: string; inputTokens: number; outputTokens: number }\n): void {\n const entry: UsageEntry = {\n timestamp: new Date().toISOString(),\n ...(u.slug ? { slug: u.slug } : {}),\n ...(u.tool ? { tool: u.tool } : {}),\n model: u.model,\n inputTokens: u.inputTokens,\n outputTokens: u.outputTokens,\n costUsd: computeCost(loadPricing(dataDir), u.model, u.inputTokens, u.outputTokens),\n };\n const p = ledgerPath(dataDir);\n try {\n fs.mkdirSync(path.dirname(p), { recursive: true });\n fs.appendFileSync(p, JSON.stringify(entry) + \"\\n\", \"utf-8\");\n } catch {\n /* non-fatal: usage logging must never break an LLM call */\n }\n}\n\nexport function loadUsage(dataDir: string): UsageEntry[] {\n const p = ledgerPath(dataDir);\n if (!fs.existsSync(p)) return [];\n // Parse line-by-line and skip any malformed line (e.g. a torn final append\n // from a crash) rather than discarding the entire ledger.\n return (fs.readFileSync(p, \"utf-8\") as string)\n .split(\"\\n\")\n .filter(Boolean)\n .flatMap((line) => {\n try {\n return [JSON.parse(line) as UsageEntry];\n } catch {\n return [];\n }\n });\n}\n\nexport interface UsageAggregate {\n totalInputTokens: number;\n totalOutputTokens: number;\n totalCostUsd: number;\n calls: number;\n bySlug: Record<\n string,\n { inputTokens: number; outputTokens: number; costUsd: number; calls: number }\n >;\n}\n\nexport function aggregateUsage(dataDir: string, opts: { slug?: string } = {}): UsageAggregate {\n const agg: UsageAggregate = {\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCostUsd: 0,\n calls: 0,\n bySlug: {},\n };\n for (const e of loadUsage(dataDir)) {\n if (opts.slug && e.slug !== opts.slug) continue;\n agg.totalInputTokens += e.inputTokens;\n agg.totalOutputTokens += e.outputTokens;\n agg.totalCostUsd += e.costUsd;\n agg.calls++;\n const key = e.slug ?? \"(unattributed)\";\n const b = agg.bySlug[key] ?? { inputTokens: 0, outputTokens: 0, costUsd: 0, calls: 0 };\n b.inputTokens += e.inputTokens;\n b.outputTokens += e.outputTokens;\n b.costUsd += e.costUsd;\n b.calls++;\n agg.bySlug[key] = b;\n }\n agg.totalCostUsd = Math.round(agg.totalCostUsd * 1_000_000) / 1_000_000;\n return agg;\n}\n"],"mappings":";;;AAyBA,MAAM,kBAAmD;CACvD,oBAAoB;EAAE,OAAO;EAAK,QAAQ;CAAI;CAC9C,SAAS;EAAE,OAAO;EAAK,QAAQ;CAAI;AACrC;AAEA,SAAS,WAAW,SAAyB;CAC3C,OAAO,KAAK,KAAK,SAAS,YAAY,cAAc;AACtD;AAEA,SAAS,YAAY,SAAkD;CACrE,MAAM,IAAI,KAAK,KAAK,SAAS,YAAY,kBAAkB;CAC3D,IAAI,CAAC,GAAG,WAAW,CAAC,GAAG,OAAO;CAC9B,IAAI;EACF,MAAM,SAAS,KAAK,MAAM,GAAG,aAAa,GAAG,OAAO,CAAW;EAI/D,OAAO;GAAE,GAAG;GAAiB,GAAG;EAAO;CACzC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAgB,YACd,SACA,OACA,aACA,cACQ;CACR,MAAM,QAAQ,QAAQ,UAAU,QAAQ;CACxC,MAAM,OAAQ,cAAc,MAAa,MAAM,QAAS,eAAe,MAAa,MAAM;CAC1F,OAAO,KAAK,MAAM,OAAO,GAAS,IAAI;AACxC;AAEA,SAAgB,YACd,SACA,GACM;CACN,MAAM,QAAoB;EACxB,4BAAW,IAAI,KAAK,GAAE,YAAY;EAClC,GAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;EACjC,GAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;EACjC,OAAO,EAAE;EACT,aAAa,EAAE;EACf,cAAc,EAAE;EAChB,SAAS,YAAY,YAAY,OAAO,GAAG,EAAE,OAAO,EAAE,aAAa,EAAE,YAAY;CACnF;CACA,MAAM,IAAI,WAAW,OAAO;CAC5B,IAAI;EACF,GAAG,UAAU,KAAK,QAAQ,CAAC,GAAG,EAAE,WAAW,KAAK,CAAC;EACjD,GAAG,eAAe,GAAG,KAAK,UAAU,KAAK,IAAI,MAAM,OAAO;CAC5D,QAAQ,CAER;AACF"}
@@ -1,3 +1,4 @@
1
+ import { t as writeFileAtomic } from "./atomic-write-8yjqqLtS.js";
1
2
  import path from "path";
2
3
  import fs from "fs";
3
4
  import crypto from "crypto";
@@ -54,9 +55,7 @@ function loadVault(dataDir, key) {
54
55
  }
55
56
  /** Encrypt + write the vault atomically (overwrites the single blob). */
56
57
  function saveVault(dataDir, key, data) {
57
- const p = vaultPath(dataDir);
58
- fs.mkdirSync(path.dirname(p), { recursive: true });
59
- fs.writeFileSync(p, encryptFieldStr(JSON.stringify(data), key), "utf-8");
58
+ writeFileAtomic(vaultPath(dataDir), encryptFieldStr(JSON.stringify(data), key));
60
59
  }
61
60
  /** Store (or overwrite) a secret under `name`. */
62
61
  function setSecret(dataDir, key, name, value) {
@@ -83,4 +82,4 @@ function removeSecret(dataDir, key, name) {
83
82
  //#endregion
84
83
  export { saveVault as a, removeSecret as i, listSecretKeys as n, setSecret as o, loadVault as r, getSecret as t };
85
84
 
86
- //# sourceMappingURL=vault-DXCg29W-.js.map
85
+ //# sourceMappingURL=vault-CfwZdNzC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault-CfwZdNzC.js","names":[],"sources":["../src/core/encryption.ts","../src/core/vault.ts"],"sourcesContent":["import crypto from \"crypto\";\n\nconst ALGORITHM = \"aes-256-gcm\";\nconst KEY_LEN = 32;\nconst IV_LEN = 12;\n\nexport function deriveKey(secret: string): Buffer {\n return crypto.scryptSync(secret, \"dxcrm-salt-v1\", KEY_LEN);\n}\n\nexport interface EncryptedField {\n iv: string;\n ciphertext: string;\n authTag: string;\n}\n\nexport function encryptField(plaintext: string, key: Buffer): EncryptedField {\n const iv = crypto.randomBytes(IV_LEN);\n const cipher = crypto.createCipheriv(ALGORITHM, key, iv);\n const ciphertext = Buffer.concat([cipher.update(plaintext, \"utf8\"), cipher.final()]);\n const authTag = cipher.getAuthTag();\n return {\n iv: iv.toString(\"hex\"),\n ciphertext: ciphertext.toString(\"hex\"),\n authTag: authTag.toString(\"hex\"),\n };\n}\n\nexport function decryptField(encrypted: EncryptedField, key: Buffer): string {\n const iv = Buffer.from(encrypted.iv, \"hex\");\n const ciphertext = Buffer.from(encrypted.ciphertext, \"hex\");\n const authTag = Buffer.from(encrypted.authTag, \"hex\");\n const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);\n decipher.setAuthTag(authTag);\n return Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString(\"utf8\");\n}\n\nexport function encryptFieldStr(plaintext: string, secret: string): string {\n return JSON.stringify(encryptField(plaintext, deriveKey(secret)));\n}\n\nexport function decryptFieldStr(encryptedJson: string, secret: string): string {\n return decryptField(JSON.parse(encryptedJson) as EncryptedField, deriveKey(secret));\n}\n","import fs from \"fs\";\nimport path from \"path\";\nimport { encryptFieldStr, decryptFieldStr } from \"./encryption.js\";\nimport { writeFileAtomic } from \"../fs/atomic-write.js\";\n\n/**\n * Local credential vault (domino D12 / F6): a dependency-free, AES-256-GCM\n * encrypted store for secrets the agent must hold (portal passwords, API keys)\n * but the customer markdown must never contain in plaintext. The whole vault is\n * a single encrypted blob at `.agentic/vault.enc`; the master key lives only in\n * the operator's environment (DXCRM_VAULT_KEY) — never on disk, never committed.\n * A GUI is a documented follow-up; this is the headless, scriptable core.\n */\ntype VaultData = Record<string, string>;\n\nfunction vaultPath(dataDir: string): string {\n return path.join(dataDir, \".agentic\", \"vault.enc\");\n}\n\n/** Read + decrypt the vault. Empty vault when the file does not exist yet. */\nexport function loadVault(dataDir: string, key: string): VaultData {\n const p = vaultPath(dataDir);\n if (!fs.existsSync(p)) return {};\n const encrypted = fs.readFileSync(p, \"utf-8\") as string;\n let decrypted: string;\n try {\n decrypted = decryptFieldStr(encrypted, key);\n } catch {\n // AES-GCM auth-tag failure → wrong master key (or a corrupted/tampered file).\n throw new Error(\"Unable to decrypt vault: wrong master key or corrupted vault file.\");\n }\n const data = JSON.parse(decrypted) as VaultData;\n return data && typeof data === \"object\" ? data : {};\n}\n\n/** Encrypt + write the vault atomically (overwrites the single blob). */\nexport function saveVault(dataDir: string, key: string, data: VaultData): void {\n writeFileAtomic(vaultPath(dataDir), encryptFieldStr(JSON.stringify(data), key));\n}\n\n/** Store (or overwrite) a secret under `name`. */\nexport function setSecret(dataDir: string, key: string, name: string, value: string): void {\n const data = loadVault(dataDir, key);\n data[name] = value;\n saveVault(dataDir, key, data);\n}\n\n/** Retrieve a secret; returns undefined when absent. Throws on wrong master key. */\nexport function getSecret(dataDir: string, key: string, name: string): string | undefined {\n return loadVault(dataDir, key)[name];\n}\n\n/** List the names of all stored secrets (values stay encrypted). */\nexport function listSecretKeys(dataDir: string, key: string): string[] {\n return Object.keys(loadVault(dataDir, key));\n}\n\n/** Remove a secret; returns true when something was deleted. */\nexport function removeSecret(dataDir: string, key: string, name: string): boolean {\n const data = loadVault(dataDir, key);\n if (!(name in data)) return false;\n delete data[name];\n saveVault(dataDir, key, data);\n return true;\n}\n"],"mappings":";;;;;AAEA,MAAM,YAAY;AAClB,MAAM,UAAU;AAChB,MAAM,SAAS;AAEf,SAAgB,UAAU,QAAwB;CAChD,OAAO,OAAO,WAAW,QAAQ,iBAAiB,OAAO;AAC3D;AAQA,SAAgB,aAAa,WAAmB,KAA6B;CAC3E,MAAM,KAAK,OAAO,YAAY,MAAM;CACpC,MAAM,SAAS,OAAO,eAAe,WAAW,KAAK,EAAE;CACvD,MAAM,aAAa,OAAO,OAAO,CAAC,OAAO,OAAO,WAAW,MAAM,GAAG,OAAO,MAAM,CAAC,CAAC;CACnF,MAAM,UAAU,OAAO,WAAW;CAClC,OAAO;EACL,IAAI,GAAG,SAAS,KAAK;EACrB,YAAY,WAAW,SAAS,KAAK;EACrC,SAAS,QAAQ,SAAS,KAAK;CACjC;AACF;AAEA,SAAgB,aAAa,WAA2B,KAAqB;CAC3E,MAAM,KAAK,OAAO,KAAK,UAAU,IAAI,KAAK;CAC1C,MAAM,aAAa,OAAO,KAAK,UAAU,YAAY,KAAK;CAC1D,MAAM,UAAU,OAAO,KAAK,UAAU,SAAS,KAAK;CACpD,MAAM,WAAW,OAAO,iBAAiB,WAAW,KAAK,EAAE;CAC3D,SAAS,WAAW,OAAO;CAC3B,OAAO,OAAO,OAAO,CAAC,SAAS,OAAO,UAAU,GAAG,SAAS,MAAM,CAAC,CAAC,EAAE,SAAS,MAAM;AACvF;AAEA,SAAgB,gBAAgB,WAAmB,QAAwB;CACzE,OAAO,KAAK,UAAU,aAAa,WAAW,UAAU,MAAM,CAAC,CAAC;AAClE;AAEA,SAAgB,gBAAgB,eAAuB,QAAwB;CAC7E,OAAO,aAAa,KAAK,MAAM,aAAa,GAAqB,UAAU,MAAM,CAAC;AACpF;;;AC5BA,SAAS,UAAU,SAAyB;CAC1C,OAAO,KAAK,KAAK,SAAS,YAAY,WAAW;AACnD;;AAGA,SAAgB,UAAU,SAAiB,KAAwB;CACjE,MAAM,IAAI,UAAU,OAAO;CAC3B,IAAI,CAAC,GAAG,WAAW,CAAC,GAAG,OAAO,CAAC;CAC/B,MAAM,YAAY,GAAG,aAAa,GAAG,OAAO;CAC5C,IAAI;CACJ,IAAI;EACF,YAAY,gBAAgB,WAAW,GAAG;CAC5C,QAAQ;EAEN,MAAM,IAAI,MAAM,oEAAoE;CACtF;CACA,MAAM,OAAO,KAAK,MAAM,SAAS;CACjC,OAAO,QAAQ,OAAO,SAAS,WAAW,OAAO,CAAC;AACpD;;AAGA,SAAgB,UAAU,SAAiB,KAAa,MAAuB;CAC7E,gBAAgB,UAAU,OAAO,GAAG,gBAAgB,KAAK,UAAU,IAAI,GAAG,GAAG,CAAC;AAChF;;AAGA,SAAgB,UAAU,SAAiB,KAAa,MAAc,OAAqB;CACzF,MAAM,OAAO,UAAU,SAAS,GAAG;CACnC,KAAK,QAAQ;CACb,UAAU,SAAS,KAAK,IAAI;AAC9B;;AAGA,SAAgB,UAAU,SAAiB,KAAa,MAAkC;CACxF,OAAO,UAAU,SAAS,GAAG,EAAE;AACjC;;AAGA,SAAgB,eAAe,SAAiB,KAAuB;CACrE,OAAO,OAAO,KAAK,UAAU,SAAS,GAAG,CAAC;AAC5C;;AAGA,SAAgB,aAAa,SAAiB,KAAa,MAAuB;CAChF,MAAM,OAAO,UAAU,SAAS,GAAG;CACnC,IAAI,EAAE,QAAQ,OAAO,OAAO;CAC5B,OAAO,KAAK;CACZ,UAAU,SAAS,KAAK,IAAI;CAC5B,OAAO;AACT"}
@@ -1,2 +1,2 @@
1
- import { i as removeSecret, n as listSecretKeys, o as setSecret, t as getSecret } from "./vault-DXCg29W-.js";
1
+ import { i as removeSecret, n as listSecretKeys, o as setSecret, t as getSecret } from "./vault-CfwZdNzC.js";
2
2
  export { getSecret, listSecretKeys, removeSecret, setSecret };
@@ -1,8 +1,7 @@
1
1
  const require_chunk = require("./chunk-DakpK96I.cjs");
2
+ const require_session_store = require("./session-store-yfwnj0OC.cjs");
2
3
  let path = require("path");
3
4
  path = require_chunk.__toESM(path, 1);
4
- let fs = require("fs");
5
- fs = require_chunk.__toESM(fs, 1);
6
5
  let crypto = require("crypto");
7
6
  //#region src/core/webhooks.ts
8
7
  function subsPath(dataDir) {
@@ -11,21 +10,8 @@ function subsPath(dataDir) {
11
10
  function failuresPath(dataDir) {
12
11
  return path.default.join(dataDir, ".agentic", "webhook-failures.json");
13
12
  }
14
- function readJson(p, key) {
15
- if (!fs.default.existsSync(p)) return [];
16
- try {
17
- const data = JSON.parse(fs.default.readFileSync(p, "utf-8"));
18
- return Array.isArray(data[key]) ? data[key] : [];
19
- } catch {
20
- return [];
21
- }
22
- }
23
- function writeJson(p, key, items) {
24
- fs.default.mkdirSync(path.default.dirname(p), { recursive: true });
25
- fs.default.writeFileSync(p, JSON.stringify({ [key]: items }, null, 2), "utf-8");
26
- }
27
13
  function loadWebhooks(dataDir) {
28
- return readJson(subsPath(dataDir), "subscriptions");
14
+ return require_session_store.readJsonArray(subsPath(dataDir), "subscriptions");
29
15
  }
30
16
  /** A subscription matches an event by exact name, "*", or a "prefix.*" pattern. */
31
17
  function matchSubscriptions(subs, event) {
@@ -39,7 +25,7 @@ function signPayload(secret, body) {
39
25
  return (0, crypto.createHmac)("sha256", secret).update(body).digest("hex");
40
26
  }
41
27
  function loadFailures(dataDir) {
42
- return readJson(failuresPath(dataDir), "failures");
28
+ return require_session_store.readJsonArray(failuresPath(dataDir), "failures");
43
29
  }
44
30
  async function deliver(sub, event, payload) {
45
31
  const body = JSON.stringify({
@@ -89,9 +75,9 @@ async function emitEvent(dataDir, event, payload) {
89
75
  queuedAt: (/* @__PURE__ */ new Date()).toISOString()
90
76
  });
91
77
  }
92
- if (failures.length > 0) writeJson(failuresPath(dataDir), "failures", failures);
78
+ if (failures.length > 0) require_session_store.writeJsonArray(failuresPath(dataDir), "failures", failures);
93
79
  }
94
80
  //#endregion
95
81
  exports.emitEvent = emitEvent;
96
82
 
97
- //# sourceMappingURL=webhooks-Xn6zO6kd.cjs.map
83
+ //# sourceMappingURL=webhooks-CwW-3kvG.cjs.map