@langwatch/mcp-server 2.1.0 → 3.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 (428) hide show
  1. package/.gitignore +7 -0
  2. package/.npmignore +41 -0
  3. package/CHANGELOG.md +218 -201
  4. package/CONTRIBUTING.md +10 -0
  5. package/README.md +70 -68
  6. package/dist/add-dashboard-widget-55UI6H22.js +44 -0
  7. package/dist/add-dashboard-widget-MJHIC3CC.js +45 -0
  8. package/dist/{archive-project-W3IKI7UL.js → archive-project-K5UD7A6X.js} +4 -4
  9. package/dist/archive-project-L4PAKT34.js +19 -0
  10. package/dist/{archive-run-plan-474OKHHU.js → archive-run-plan-5HSQG2HX.js} +4 -4
  11. package/dist/archive-run-plan-AOKNYQIO.js +15 -0
  12. package/dist/archive-scenario-2CWJW2VD.js +19 -0
  13. package/dist/{archive-scenario-V5UNYK26.js → archive-scenario-5IJQESHH.js} +4 -4
  14. package/dist/{archive-test-suite-O7FLDMXK.js → archive-test-suite-OPB7NFI7.js} +4 -4
  15. package/dist/archive-test-suite-ZC3TN6VH.js +15 -0
  16. package/dist/assign-prompt-tag-6DDE6ZZ5.js +23 -0
  17. package/dist/{assign-prompt-tag-Q46WRB6P.js → assign-prompt-tag-D7O23MJM.js} +8 -4
  18. package/dist/chunk-3YLN3ATJ.js +241 -0
  19. package/dist/{chunk-EYXMLE5X.js → chunk-4RX3G62A.js} +56 -47
  20. package/dist/{chunk-UF6XIGYR.js → chunk-6YZUOD34.js} +2 -5
  21. package/dist/{chunk-WVI5CJ6S.js → chunk-7AQLPVFL.js} +2 -2
  22. package/dist/chunk-7CZQDZ2K.js +319 -0
  23. package/dist/{chunk-RVAE2MEA.js → chunk-7GETGE6B.js} +7 -7
  24. package/dist/{chunk-OJLYYJWI.js → chunk-AASW2TO2.js} +7 -10
  25. package/dist/{chunk-QAMP3CGR.js → chunk-B4RFWIUP.js} +4 -4
  26. package/dist/{chunk-ZXKLPC2E.js → chunk-BIIKE3EI.js} +1 -1
  27. package/dist/{chunk-G4ZAZTZW.js → chunk-D2HS73VI.js} +7 -10
  28. package/dist/{chunk-37SMPMQS.js → chunk-DMM3JQ42.js} +7 -2
  29. package/dist/{chunk-WT4PO4A3.js → chunk-DULFP3MK.js} +10 -7
  30. package/dist/chunk-EYPJBL7P.js +516 -0
  31. package/dist/{chunk-NUFPTHKU.js → chunk-FOKVY3BK.js} +1 -1
  32. package/dist/chunk-GA5JUSPT.js +64 -0
  33. package/dist/{chunk-UJPXFA26.js → chunk-HHMNZAPD.js} +101 -74
  34. package/dist/chunk-HLQJXUR6.js +67 -0
  35. package/dist/{chunk-JTQJRNFJ.js → chunk-KILVK3FS.js} +4 -4
  36. package/dist/chunk-MOCU5XWF.js +79 -0
  37. package/dist/chunk-O2WGVCED.js +41 -0
  38. package/dist/{chunk-HV4DWKBI.js → chunk-O7EMWEVJ.js} +2 -4
  39. package/dist/{chunk-UFOYFYI7.js → chunk-QXLMHLRC.js} +6 -9
  40. package/dist/{chunk-QRO35SOM.js → chunk-R5YJIYPF.js} +981 -747
  41. package/dist/{chunk-JR6DJZOU.js → chunk-RABYBFX5.js} +4 -10
  42. package/dist/{chunk-SR6QPRIE.js → chunk-RFC2SBEX.js} +7 -13
  43. package/dist/chunk-SHSVN3SE.js +21 -0
  44. package/dist/{chunk-CKNAH5TG.js → chunk-U24EACC4.js} +3 -10
  45. package/dist/{chunk-56OGTS24.js → chunk-VOUGDY2O.js} +4 -11
  46. package/dist/chunk-WCKZDOGF.js +31 -0
  47. package/dist/chunk-XQYH52SI.js +129 -0
  48. package/dist/{chunk-7E4FZIYJ.js → chunk-XUIJYNRJ.js} +1 -1
  49. package/dist/{chunk-6DJDEXET.js → chunk-YCIUEZVK.js} +6 -12
  50. package/dist/config-2WQGMAEN.js +16 -0
  51. package/dist/config.cjs +109 -0
  52. package/dist/config.js +5 -4
  53. package/dist/{create-agent-JFJ2K6X3.js → create-agent-6JNLMYQD.js} +4 -4
  54. package/dist/create-agent-IRZOU4R5.js +23 -0
  55. package/dist/create-analytics-report-N4L4V5QL.js +19 -0
  56. package/dist/create-analytics-report-QEHXG7FU.js +18 -0
  57. package/dist/{create-annotation-EUXXQ6NS.js → create-annotation-CCEGIZ67.js} +10 -5
  58. package/dist/create-annotation-DTHCMWHB.js +29 -0
  59. package/dist/{create-api-key-BGBB76JX.js → create-api-key-JKM2DSZO.js} +5 -7
  60. package/dist/create-api-key-JPEUIXGM.js +24 -0
  61. package/dist/create-dataset-DJNXYJ5B.js +22 -0
  62. package/dist/{create-dataset-FD5VAXU4.js → create-dataset-WON4SOTC.js} +6 -6
  63. package/dist/create-dataset-records-TMEOTLTO.js +20 -0
  64. package/dist/{create-dataset-records-WQUXXOHI.js → create-dataset-records-UJBW3C7C.js} +5 -7
  65. package/dist/create-evaluator-N5AEHI4K.js +27 -0
  66. package/dist/{create-evaluator-6NV33Z52.js → create-evaluator-XYNY2YFY.js} +4 -4
  67. package/dist/create-mcp-server.cjs +9712 -0
  68. package/dist/create-mcp-server.js +2757 -10
  69. package/dist/{create-project-ZQ7TFIO2.js → create-project-EY4XZ7TH.js} +4 -4
  70. package/dist/create-project-YL345T5L.js +44 -0
  71. package/dist/{create-prompt-BS6QRCUU.js → create-prompt-JZQNQ7I3.js} +5 -7
  72. package/dist/create-prompt-ZUMQHHX7.js +37 -0
  73. package/dist/create-prompt-tag-CJ5FZ436.js +17 -0
  74. package/dist/{create-prompt-tag-FCQ5ELSQ.js → create-prompt-tag-JFP2Q3PO.js} +3 -3
  75. package/dist/create-scenario-CQU2SSFB.js +33 -0
  76. package/dist/{create-scenario-DRPTPXU3.js → create-scenario-S6OWWKJO.js} +5 -5
  77. package/dist/create-test-suite-OLGCAGJA.js +36 -0
  78. package/dist/{create-test-suite-ZIZCCFJ4.js → create-test-suite-Y7P2RI4L.js} +6 -6
  79. package/dist/create-trigger-4CNBTISJ.js +48 -0
  80. package/dist/create-trigger-RQ653WYF.js +49 -0
  81. package/dist/dashboards-BA7M6CMO.js +90 -0
  82. package/dist/dashboards-U663GUIB.js +91 -0
  83. package/dist/{delete-agent-SA4JMUZF.js → delete-agent-J2Q4DRZ2.js} +4 -4
  84. package/dist/delete-agent-ZAU4LTXB.js +18 -0
  85. package/dist/delete-analytics-report-QK6X7P4S.js +19 -0
  86. package/dist/delete-analytics-report-YUYLDHLL.js +18 -0
  87. package/dist/delete-annotation-7X4NYXXM.js +17 -0
  88. package/dist/{delete-annotation-X3KKK7QY.js → delete-annotation-KJOCDLV3.js} +4 -4
  89. package/dist/{delete-dataset-W6EZ44HY.js → delete-dataset-NXP7ZPPV.js} +5 -7
  90. package/dist/delete-dataset-RUTZBBVD.js +18 -0
  91. package/dist/{delete-dataset-records-7CNOTALB.js → delete-dataset-records-4Z7DZCDW.js} +5 -7
  92. package/dist/delete-dataset-records-75UAR5IS.js +19 -0
  93. package/dist/delete-evaluator-E3CUNGTQ.js +16 -0
  94. package/dist/delete-evaluator-RI4GALGX.js +15 -0
  95. package/dist/delete-prompt-tag-LE3WJPKS.js +17 -0
  96. package/dist/{delete-prompt-tag-QB3OCZUV.js → delete-prompt-tag-S4KBZTNG.js} +3 -3
  97. package/dist/delete-workflow-4CZFIQCQ.js +17 -0
  98. package/dist/{delete-workflow-NG2VXYYM.js → delete-workflow-PWQPDW6H.js} +4 -4
  99. package/dist/discover-evaluator-schema-UHWA5HVL.js +120 -0
  100. package/dist/discover-evaluator-schema-XKCLLCB3.js +118 -0
  101. package/dist/discover-scenario-schema-NOJY6S7E.js +137 -0
  102. package/dist/{discover-scenario-schema-W7KBXA4J.js → discover-scenario-schema-OOFIQKOG.js} +37 -17
  103. package/dist/discover-schema-7WHIIATI.js +442 -0
  104. package/dist/{discover-schema-L6QDPON3.js → discover-schema-J2ANOBKO.js} +181 -186
  105. package/dist/get-agent-5T3CXQOR.js +69 -0
  106. package/dist/{get-agent-7THF7HCU.js → get-agent-ZKYQJUQ7.js} +15 -11
  107. package/dist/get-analytics-4MPEK4KV.js +79 -0
  108. package/dist/get-analytics-ZLI3A4F5.js +80 -0
  109. package/dist/get-analytics-report-JCKYMA2S.js +29 -0
  110. package/dist/get-analytics-report-SKIP2JWH.js +30 -0
  111. package/dist/get-dataset-APGZBYMH.js +64 -0
  112. package/dist/get-dataset-LWXDVMVE.js +63 -0
  113. package/dist/get-evaluator-3A7BJBAB.js +47 -0
  114. package/dist/{get-evaluator-RZ44UIN6.js → get-evaluator-IWNJINRY.js} +4 -4
  115. package/dist/get-project-EQVB4LEL.js +26 -0
  116. package/dist/{get-project-QSQEAB33.js → get-project-RK6AJTEP.js} +4 -4
  117. package/dist/{get-prompt-GVKXF5NL.js → get-prompt-TLG2T2DS.js} +53 -58
  118. package/dist/get-prompt-ZER557X3.js +94 -0
  119. package/dist/get-run-plan-5X7DDJRN.js +58 -0
  120. package/dist/{get-run-plan-NY7J5GRE.js → get-run-plan-PEHRO5M3.js} +7 -9
  121. package/dist/{get-scenario-Q3LLQE4T.js → get-scenario-375W5D6I.js} +5 -5
  122. package/dist/get-scenario-UQX45ZZO.js +37 -0
  123. package/dist/{get-simulation-run-WINEYDMK.js → get-simulation-run-2NBXJADG.js} +26 -22
  124. package/dist/get-simulation-run-QZTLGL7W.js +69 -0
  125. package/dist/{get-test-suite-4HKA7OKS.js → get-test-suite-GVIBDG7K.js} +5 -5
  126. package/dist/get-test-suite-OODIR3RI.js +48 -0
  127. package/dist/{get-trace-RCUV7N4O.js → get-trace-AGCHVPJK.js} +11 -13
  128. package/dist/get-trace-KJLYAZRC.js +45 -0
  129. package/dist/get-workflow-3TV2YYC5.js +25 -0
  130. package/dist/{get-workflow-EEOC7Y45.js → get-workflow-7LZSVPP2.js} +4 -4
  131. package/dist/{http-security-EU3CHTY7.js → http-security-DNLBNQZL.js} +2 -2
  132. package/dist/{http-server-WCDUARTH.js → http-server-7CCN3EHJ.js} +4249 -325
  133. package/dist/index.js +59595 -38027
  134. package/dist/langwatch-api-analytics-reports-6CF6KUET.js +17 -0
  135. package/dist/langwatch-api-analytics-reports-RPFB5AO5.js +18 -0
  136. package/dist/{langwatch-api-annotations-6DHVZWUK.js → langwatch-api-annotations-H4AI4TKG.js} +4 -4
  137. package/dist/langwatch-api-annotations-QSJNUQQS.js +17 -0
  138. package/dist/langwatch-api-monitors-ENHLOL3S.js +47 -0
  139. package/dist/{langwatch-api-monitors-6ISFJ7WX.js → langwatch-api-monitors-OHSGADTH.js} +11 -16
  140. package/dist/langwatch-api-secrets-AGW6UUMD.js +55 -0
  141. package/dist/langwatch-api-secrets-CLTS766Q.js +56 -0
  142. package/dist/langwatch-api-triggers-G5UWFNN2.js +22 -0
  143. package/dist/langwatch-api-triggers-QMR7KEXW.js +23 -0
  144. package/dist/langwatch-api-workflows-HKTBIKKY.js +15 -0
  145. package/dist/{langwatch-api-workflows-6UJL5U4Z.js → langwatch-api-workflows-OMROZH2O.js} +4 -4
  146. package/dist/{list-agents-AMVDQPQL.js → list-agents-BYWDNAHT.js} +4 -4
  147. package/dist/list-agents-MG24MHZE.js +42 -0
  148. package/dist/list-analytics-reports-G3EPWGSQ.js +32 -0
  149. package/dist/list-analytics-reports-PPWIFRES.js +33 -0
  150. package/dist/list-annotations-QCLGEK5A.js +38 -0
  151. package/dist/{list-annotations-6PR5NLIC.js → list-annotations-Y4EUBJHG.js} +10 -5
  152. package/dist/list-api-keys-DAVOBPFK.js +42 -0
  153. package/dist/{list-api-keys-GVPNBIHQ.js → list-api-keys-JMW5WRXX.js} +10 -5
  154. package/dist/list-dashboards-2P3VJFRS.js +29 -0
  155. package/dist/list-dashboards-MW5O3MKH.js +30 -0
  156. package/dist/list-dataset-records-KEHT7G6Q.js +43 -0
  157. package/dist/{list-dataset-records-O67HZ35Y.js → list-dataset-records-KMLLMZAZ.js} +14 -10
  158. package/dist/{list-datasets-WXZL6UMP.js → list-datasets-P3JK2ZHS.js} +9 -13
  159. package/dist/list-datasets-Z7OOE4KI.js +56 -0
  160. package/dist/{list-evaluators-PAX72WCN.js → list-evaluators-7RRESBOU.js} +5 -7
  161. package/dist/list-evaluators-VATJVOHR.js +32 -0
  162. package/dist/{list-model-providers-VVLZMLCX.js → list-model-providers-OXDRPUCJ.js} +4 -4
  163. package/dist/list-model-providers-VXQJWDXU.js +35 -0
  164. package/dist/{list-projects-AQVI6SUK.js → list-projects-HUVK7L3W.js} +5 -7
  165. package/dist/list-projects-X72ZXVY5.js +40 -0
  166. package/dist/{list-prompt-tags-WZFBJOHG.js → list-prompt-tags-3I3LWFIR.js} +3 -3
  167. package/dist/list-prompt-tags-DRHUH2ND.js +23 -0
  168. package/dist/list-prompts-6DX3QECJ.js +30 -0
  169. package/dist/{list-prompts-BQOHRHYT.js → list-prompts-PS423RU3.js} +4 -6
  170. package/dist/list-run-plans-5SXPOV3X.js +45 -0
  171. package/dist/{list-run-plans-UBAU2DGH.js → list-run-plans-6VNHINPY.js} +5 -5
  172. package/dist/list-scenarios-EQWCW7Q4.js +45 -0
  173. package/dist/{list-scenarios-MS4IUIVM.js → list-scenarios-GKNH3YND.js} +13 -11
  174. package/dist/{list-simulation-runs-D6YF4ZOU.js → list-simulation-runs-KHY7KALI.js} +12 -8
  175. package/dist/list-simulation-runs-PUDK32C2.js +53 -0
  176. package/dist/list-test-suites-7H2DRILK.js +34 -0
  177. package/dist/{list-test-suites-L7R2O6DR.js → list-test-suites-GY56LGLY.js} +4 -4
  178. package/dist/list-trigger-fires-7RZUP54Y.js +19 -0
  179. package/dist/list-trigger-fires-OZUF65LI.js +20 -0
  180. package/dist/list-triggers-BGUCUXTJ.js +45 -0
  181. package/dist/list-triggers-XC5KMX4C.js +46 -0
  182. package/dist/list-workflows-55NYC3PC.js +33 -0
  183. package/dist/{list-workflows-6MV4XJHF.js → list-workflows-HV7FUWZA.js} +5 -7
  184. package/dist/{rename-prompt-tag-K5LQ4CY6.js → rename-prompt-tag-2I7Z5FCY.js} +3 -3
  185. package/dist/rename-prompt-tag-SZYTOWDX.js +18 -0
  186. package/dist/{rename-test-suite-NTYHAO5X.js → rename-test-suite-27AYY33K.js} +4 -4
  187. package/dist/rename-test-suite-CLIEPZDO.js +20 -0
  188. package/dist/report-issue-5HSL7CNB.js +924 -0
  189. package/dist/{report-issue-RHZZ33IS.js → report-issue-N7ND5TM6.js} +107 -67
  190. package/dist/{rerun-run-plan-MUDWJBE4.js → rerun-run-plan-O3VUZ6CG.js} +5 -5
  191. package/dist/rerun-run-plan-OJTVVGJI.js +21 -0
  192. package/dist/{revoke-api-key-6LAZ3QZZ.js → revoke-api-key-BU6BKGCG.js} +4 -4
  193. package/dist/revoke-api-key-NZNCFOIR.js +15 -0
  194. package/dist/run-agent-244O4Y5M.js +75 -0
  195. package/dist/run-agent-HPCGZGYW.js +74 -0
  196. package/dist/run-plan-2ZPGGZ4H.js +38 -0
  197. package/dist/{run-plan-T4ZYOZGA.js → run-plan-KSXUYQT3.js} +7 -7
  198. package/dist/run-query-4LMOQ5UW.js +47 -0
  199. package/dist/run-query-BQUHIUC2.js +46 -0
  200. package/dist/{run-test-suite-L4MZ7G4D.js → run-test-suite-P3WLVPXC.js} +6 -6
  201. package/dist/run-test-suite-UEOMCON6.js +25 -0
  202. package/dist/run-workflow-EFZ6HG5B.js +36 -0
  203. package/dist/{run-workflow-DFIS23AP.js → run-workflow-I4IHEN54.js} +4 -4
  204. package/dist/search-traces-6IR7PR4L.js +170 -0
  205. package/dist/search-traces-BYML2NQ4.js +171 -0
  206. package/dist/set-model-provider-RBNGWFVI.js +33 -0
  207. package/dist/{set-model-provider-XRNMFOVR.js → set-model-provider-SHEVKWRC.js} +4 -4
  208. package/dist/{update-agent-DUWNYBNA.js → update-agent-PTKTM2B5.js} +4 -4
  209. package/dist/update-agent-ZPXWRMS2.js +20 -0
  210. package/dist/update-dashboard-widget-HKCBXH7X.js +62 -0
  211. package/dist/update-dashboard-widget-IP2TTQ5G.js +63 -0
  212. package/dist/update-dataset-GHIN6JR3.js +22 -0
  213. package/dist/{update-dataset-YSOMDCOB.js → update-dataset-IRVMY5PF.js} +6 -6
  214. package/dist/update-dataset-record-6VI7K2CL.js +19 -0
  215. package/dist/{update-dataset-record-DEA2ITYR.js → update-dataset-record-Z3L7ACNF.js} +4 -4
  216. package/dist/update-evaluator-5NLNE6VY.js +24 -0
  217. package/dist/{update-evaluator-NH7Q5GWV.js → update-evaluator-FEH7H6NS.js} +4 -4
  218. package/dist/update-project-75H3LDQT.js +24 -0
  219. package/dist/{update-project-Q26FBSYH.js → update-project-QPR3QX55.js} +4 -4
  220. package/dist/update-prompt-BCDFTNLK.js +140 -0
  221. package/dist/{update-prompt-ZQQ2C3KU.js → update-prompt-NPRXYSWA.js} +27 -29
  222. package/dist/update-scenario-BNOMDCMV.js +34 -0
  223. package/dist/{update-scenario-WUX34JAR.js → update-scenario-EM5XGMB7.js} +5 -5
  224. package/package.json +35 -39
  225. package/pyproject.toml +23 -8
  226. package/src/config.d.ts +6 -0
  227. package/src/config.ts +22 -29
  228. package/src/create-mcp-server.ts +887 -634
  229. package/src/documentation-fetch.ts +21 -20
  230. package/src/http-security.ts +166 -135
  231. package/src/http-server.ts +189 -224
  232. package/src/index.ts +14 -16
  233. package/src/langwatch-api-agents.ts +18 -21
  234. package/src/langwatch-api-analytics-reports.ts +62 -0
  235. package/src/langwatch-api-annotations.ts +11 -12
  236. package/src/langwatch-api-api-keys.ts +8 -9
  237. package/src/langwatch-api-dashboard-widgets.ts +47 -0
  238. package/src/langwatch-api-dashboards.ts +109 -24
  239. package/src/langwatch-api-datasets.ts +98 -32
  240. package/src/langwatch-api-evaluators.ts +13 -19
  241. package/src/langwatch-api-model-providers.ts +4 -4
  242. package/src/langwatch-api-monitors.ts +14 -18
  243. package/src/langwatch-api-projects.ts +10 -9
  244. package/src/langwatch-api-query.ts +114 -0
  245. package/src/langwatch-api-run-plans.ts +12 -29
  246. package/src/langwatch-api-scenarios.ts +9 -11
  247. package/src/langwatch-api-secrets.ts +31 -24
  248. package/src/langwatch-api-simulation-runs.ts +6 -8
  249. package/src/langwatch-api-test-suites.ts +14 -33
  250. package/src/langwatch-api-triggers.ts +96 -34
  251. package/src/langwatch-api-workflows.ts +9 -9
  252. package/src/langwatch-api.ts +118 -124
  253. package/src/public-http-request.ts +21 -12
  254. package/src/schemas/analytics-metrics.ts +3 -15
  255. package/src/schemas/create-dataset.ts +3 -4
  256. package/src/schemas/run-plan.ts +13 -29
  257. package/src/schemas/suite-fields.ts +6 -23
  258. package/src/schemas/triggers.ts +365 -0
  259. package/src/schemas/widget-sources.ts +33 -0
  260. package/src/tools/add-dashboard-widget.ts +51 -0
  261. package/src/tools/archive-project.ts +2 -4
  262. package/src/tools/archive-run-plan.ts +2 -4
  263. package/src/tools/archive-scenario.ts +2 -4
  264. package/src/tools/archive-test-suite.ts +2 -4
  265. package/src/tools/assign-prompt-tag.ts +6 -2
  266. package/src/tools/create-agent.ts +1 -1
  267. package/src/tools/create-analytics-report.ts +7 -0
  268. package/src/tools/create-annotation.ts +7 -2
  269. package/src/tools/create-api-key.ts +4 -6
  270. package/src/tools/create-dataset-records.ts +4 -8
  271. package/src/tools/create-dataset.ts +5 -7
  272. package/src/tools/create-evaluator.ts +3 -5
  273. package/src/tools/create-project.ts +2 -2
  274. package/src/tools/create-prompt-tag.ts +2 -4
  275. package/src/tools/create-prompt.ts +9 -18
  276. package/src/tools/create-scenario.ts +5 -7
  277. package/src/tools/create-test-suite.ts +4 -9
  278. package/src/tools/create-trigger.ts +55 -0
  279. package/src/tools/dashboard-widget-queries.ts +45 -0
  280. package/src/tools/dashboards.ts +104 -0
  281. package/src/tools/delete-agent.ts +1 -1
  282. package/src/tools/delete-analytics-report.ts +7 -0
  283. package/src/tools/delete-annotation.ts +1 -1
  284. package/src/tools/delete-dataset-records.ts +4 -8
  285. package/src/tools/delete-dataset.ts +3 -7
  286. package/src/tools/delete-evaluator.ts +4 -6
  287. package/src/tools/delete-prompt-tag.ts +2 -4
  288. package/src/tools/delete-workflow.ts +1 -1
  289. package/src/tools/discover-evaluator-schema.ts +34 -25
  290. package/src/tools/discover-scenario-schema.ts +41 -21
  291. package/src/tools/discover-schema.ts +149 -27
  292. package/src/tools/experiment-run-status.ts +2 -8
  293. package/src/tools/format-dataset-mutation.ts +5 -10
  294. package/src/tools/format-run-plan.ts +7 -21
  295. package/src/tools/format-scenario.ts +2 -4
  296. package/src/tools/format-suite-details.ts +6 -12
  297. package/src/tools/get-agent.ts +15 -6
  298. package/src/tools/get-analytics-report.ts +23 -0
  299. package/src/tools/get-analytics.ts +52 -46
  300. package/src/tools/get-dataset.ts +34 -16
  301. package/src/tools/get-evaluator.ts +4 -11
  302. package/src/tools/get-experiment-results.ts +219 -186
  303. package/src/tools/get-project.ts +2 -4
  304. package/src/tools/get-prompt.ts +63 -84
  305. package/src/tools/get-run-plan.ts +4 -6
  306. package/src/tools/get-scenario.ts +4 -6
  307. package/src/tools/get-simulation-run.ts +27 -24
  308. package/src/tools/get-test-suite.ts +2 -5
  309. package/src/tools/get-trace.ts +16 -17
  310. package/src/tools/get-workflow.ts +1 -1
  311. package/src/tools/list-agents.ts +1 -1
  312. package/src/tools/list-analytics-reports.ts +27 -0
  313. package/src/tools/list-annotations.ts +8 -5
  314. package/src/tools/list-api-keys.ts +7 -2
  315. package/src/tools/list-dashboards.ts +20 -21
  316. package/src/tools/list-dataset-records.ts +8 -6
  317. package/src/tools/list-datasets.ts +12 -23
  318. package/src/tools/list-evaluators.ts +4 -8
  319. package/src/tools/list-experiment-runs.ts +5 -9
  320. package/src/tools/list-experiments.ts +5 -11
  321. package/src/tools/list-model-providers.ts +3 -5
  322. package/src/tools/list-projects.ts +2 -4
  323. package/src/tools/list-prompt-tags.ts +3 -3
  324. package/src/tools/list-prompts.ts +4 -8
  325. package/src/tools/list-run-plans.ts +2 -2
  326. package/src/tools/list-scenarios.ts +14 -15
  327. package/src/tools/list-simulation-runs.ts +8 -4
  328. package/src/tools/list-test-suites.ts +1 -1
  329. package/src/tools/list-trigger-fires.ts +17 -0
  330. package/src/tools/list-triggers.ts +39 -0
  331. package/src/tools/list-workflows.ts +2 -4
  332. package/src/tools/rename-prompt-tag.ts +1 -1
  333. package/src/tools/rename-test-suite.ts +2 -5
  334. package/src/tools/report-issue.ts +7 -9
  335. package/src/tools/rerun-run-plan.ts +2 -5
  336. package/src/tools/revoke-api-key.ts +2 -4
  337. package/src/tools/run-agent.ts +29 -26
  338. package/src/tools/run-experiment.ts +37 -34
  339. package/src/tools/run-plan.ts +4 -7
  340. package/src/tools/run-query.ts +47 -0
  341. package/src/tools/run-test-suite.ts +4 -7
  342. package/src/tools/run-workflow.ts +2 -5
  343. package/src/tools/search-traces.ts +161 -47
  344. package/src/tools/set-model-provider.ts +4 -6
  345. package/src/tools/test-agent.ts +2 -2
  346. package/src/tools/update-agent.ts +1 -1
  347. package/src/tools/update-dashboard-widget.ts +86 -0
  348. package/src/tools/update-dataset-record.ts +1 -1
  349. package/src/tools/update-dataset.ts +5 -7
  350. package/src/tools/update-evaluator.ts +3 -5
  351. package/src/tools/update-project.ts +1 -1
  352. package/src/tools/update-prompt.ts +44 -59
  353. package/src/tools/update-scenario.ts +5 -7
  354. package/src/tools/update-test-suite.ts +6 -11
  355. package/src/utils/date-parsing.ts +1 -1
  356. package/src/utils/escape-markdown.ts +3 -8
  357. package/src/utils/format-evaluations.ts +6 -6
  358. package/src/utils/markdown-table.ts +58 -0
  359. package/src/utils/trace-id-shape.ts +20 -0
  360. package/tsconfig.app.json +24 -0
  361. package/tsconfig.json +14 -12
  362. package/uv.lock +667 -341
  363. package/vitest.integration.config.js +10 -0
  364. package/vitest.scenario.config.js +9 -0
  365. package/.eslintrc.cjs +0 -36
  366. package/dist/chunk-AN4OUA4D.js +0 -86
  367. package/dist/chunk-GELJ2MQR.js +0 -226
  368. package/dist/chunk-K37ZNPXK.js +0 -24
  369. package/dist/chunk-S4GVX36W.js +0 -39
  370. package/dist/config.d.ts +0 -17
  371. package/dist/create-dashboard-Z76AIPLS.js +0 -19
  372. package/dist/create-mcp-server.d.ts +0 -10
  373. package/dist/delete-dashboard-LYMRPF27.js +0 -19
  374. package/dist/delete-evaluator-RKYC4TNB.js +0 -16
  375. package/dist/discover-evaluator-schema-ESSHQGPY.js +0 -1912
  376. package/dist/get-analytics-R6AZD3AW.js +0 -73
  377. package/dist/get-dashboard-P4WWVHFU.js +0 -30
  378. package/dist/get-dataset-AKTYSQDI.js +0 -49
  379. package/dist/index.d.ts +0 -2
  380. package/dist/langwatch-api-dashboards-2KJL2M42.js +0 -18
  381. package/dist/langwatch-api-secrets-OEBD6GBU.js +0 -41
  382. package/dist/langwatch-api-triggers-5E6DDGX6.js +0 -31
  383. package/dist/list-dashboards-Z3BZKDGF.js +0 -33
  384. package/dist/run-agent-CAGWGTYT.js +0 -72
  385. package/dist/search-traces-4XTJYXIK.js +0 -79
  386. package/src/__tests__/agent-tools.unit.test.ts +0 -257
  387. package/src/__tests__/all-tools.integration.test.ts +0 -1872
  388. package/src/__tests__/config.unit.test.ts +0 -202
  389. package/src/__tests__/datasets.integration.test.ts +0 -620
  390. package/src/__tests__/datasets.unit.test.ts +0 -244
  391. package/src/__tests__/date-parsing.unit.test.ts +0 -78
  392. package/src/__tests__/discover-evaluator-schema.unit.test.ts +0 -89
  393. package/src/__tests__/discover-schema.unit.test.ts +0 -118
  394. package/src/__tests__/docker.integration.test.ts +0 -318
  395. package/src/__tests__/documentation-fetch-security.integration.test.ts +0 -182
  396. package/src/__tests__/evaluator-tools.unit.test.ts +0 -262
  397. package/src/__tests__/experiment-list-tools.unit.test.ts +0 -157
  398. package/src/__tests__/experiment-status.unit.test.ts +0 -194
  399. package/src/__tests__/feature-map-tool-drift.unit.test.ts +0 -93
  400. package/src/__tests__/get-experiment-results.unit.test.ts +0 -313
  401. package/src/__tests__/http-security-origin.unit.test.ts +0 -97
  402. package/src/__tests__/http-security-sessions.unit.test.ts +0 -209
  403. package/src/__tests__/http-security-verifier.unit.test.ts +0 -248
  404. package/src/__tests__/http-server-allocation.integration.test.ts +0 -279
  405. package/src/__tests__/http-server-origin.integration.test.ts +0 -169
  406. package/src/__tests__/http-server-session-auth.integration.test.ts +0 -341
  407. package/src/__tests__/http-transport.integration.test.ts +0 -395
  408. package/src/__tests__/integration.integration.test.ts +0 -284
  409. package/src/__tests__/langwatch-api.unit.test.ts +0 -661
  410. package/src/__tests__/model-provider-tools.unit.test.ts +0 -190
  411. package/src/__tests__/project-api-key-tools.unit.test.ts +0 -451
  412. package/src/__tests__/prompt-response-types.unit.test.ts +0 -51
  413. package/src/__tests__/prompts.integration.test.ts +0 -736
  414. package/src/__tests__/public-http-request-security.integration.test.ts +0 -118
  415. package/src/__tests__/report-issue.integration.test.ts +0 -147
  416. package/src/__tests__/run-plan-tools.unit.test.ts +0 -565
  417. package/src/__tests__/scenario-tools.integration.test.ts +0 -286
  418. package/src/__tests__/scenario-tools.unit.test.ts +0 -207
  419. package/src/__tests__/schemas.unit.test.ts +0 -85
  420. package/src/__tests__/simulation-run-tools.unit.test.ts +0 -116
  421. package/src/__tests__/support/http-server-harness.ts +0 -138
  422. package/src/__tests__/test-suite-tools.unit.test.ts +0 -615
  423. package/src/__tests__/tools.integration.test.ts +0 -896
  424. package/src/schemas/filter-fields.ts +0 -119
  425. package/src/schemas/index.ts +0 -9
  426. package/src/tools/create-dashboard.ts +0 -7
  427. package/src/tools/delete-dashboard.ts +0 -7
  428. package/src/tools/get-dashboard.ts +0 -22
@@ -0,0 +1,924 @@
1
+ import {
2
+ LANGWATCH_API_VERSION
3
+ } from "./chunk-7CZQDZ2K.js";
4
+ import {
5
+ getConfig
6
+ } from "./chunk-DULFP3MK.js";
7
+
8
+ // ../../packages/redaction/src/piiEntities.ts
9
+ var ESSENTIAL_PII_ENTITIES = [
10
+ "EMAIL_ADDRESS",
11
+ "IP_ADDRESS",
12
+ "CREDIT_CARD",
13
+ "IBAN_CODE",
14
+ "CRYPTO",
15
+ "PHONE_NUMBER",
16
+ "US_SSN",
17
+ "US_ITIN",
18
+ "US_PASSPORT",
19
+ "US_BANK_NUMBER",
20
+ "US_DRIVER_LICENSE",
21
+ "MEDICAL_LICENSE",
22
+ "UK_NHS",
23
+ "SG_NRIC_FIN",
24
+ "AU_ABN",
25
+ "AU_TFN",
26
+ "IN_PAN",
27
+ "IN_AADHAAR",
28
+ "BR_CPF"
29
+ ];
30
+ var PRESIDIO_STRICT_ENTITIES = [
31
+ "CREDIT_CARD",
32
+ "CRYPTO",
33
+ "EMAIL_ADDRESS",
34
+ "IBAN_CODE",
35
+ "IP_ADDRESS",
36
+ "LOCATION",
37
+ "PERSON",
38
+ "PHONE_NUMBER",
39
+ "MEDICAL_LICENSE",
40
+ "US_BANK_NUMBER",
41
+ "US_DRIVER_LICENSE",
42
+ "US_ITIN",
43
+ "US_PASSPORT",
44
+ "US_SSN",
45
+ "UK_NHS",
46
+ "SG_NRIC_FIN",
47
+ "AU_ABN",
48
+ "AU_ACN",
49
+ "AU_TFN",
50
+ "AU_MEDICARE",
51
+ "IN_PAN",
52
+ "IN_AADHAAR",
53
+ "IN_VEHICLE_REGISTRATION",
54
+ "IN_VOTER",
55
+ "IN_PASSPORT"
56
+ ];
57
+ var STRICT_ONLY_PII_ENTITIES = PRESIDIO_STRICT_ENTITIES.filter(
58
+ (entity) => !new Set(ESSENTIAL_PII_ENTITIES).has(entity)
59
+ );
60
+
61
+ // ../../packages/redaction/src/markers.ts
62
+ var SECRET_MARKER = "[SECRET]";
63
+ function formatPiiMarker(entity) {
64
+ return `[${entity}]`;
65
+ }
66
+
67
+ // ../../packages/redaction/src/secrets.ts
68
+ var SECRETS_REDACTION_MARKER = SECRET_MARKER;
69
+ var REPLACEMENT = SECRETS_REDACTION_MARKER;
70
+ var MAX_SCAN_LENGTH = 25e4;
71
+ var ENTROPY_SAMPLE_LENGTH = 256;
72
+ function shannonEntropyBits(value) {
73
+ const sample = value.length > ENTROPY_SAMPLE_LENGTH ? value.slice(0, ENTROPY_SAMPLE_LENGTH) : value;
74
+ const counts = /* @__PURE__ */ new Map();
75
+ for (const char of sample) {
76
+ counts.set(char, (counts.get(char) ?? 0) + 1);
77
+ }
78
+ let entropy = 0;
79
+ for (const count of counts.values()) {
80
+ const probability = count / sample.length;
81
+ entropy -= probability * Math.log2(probability);
82
+ }
83
+ return entropy;
84
+ }
85
+ function countCharClasses(value) {
86
+ let lower = 0;
87
+ let upper = 0;
88
+ let digit = 0;
89
+ for (let index = 0; index < value.length; index++) {
90
+ const code = value.charCodeAt(index);
91
+ if (code >= 97 && code <= 122) lower++;
92
+ else if (code >= 65 && code <= 90) upper++;
93
+ else if (code >= 48 && code <= 57) digit++;
94
+ }
95
+ return { lower, upper, digit };
96
+ }
97
+ var TOKEN_START = String.raw`(?<![A-Za-z0-9_-])`;
98
+ var TOKEN_END = String.raw`(?![A-Za-z0-9_-])`;
99
+ var VENDOR_KEY_PATTERNS = [
100
+ // LangWatch's own token prefixes, minted by modules/api-key/contract/src/api-key.tokens.ts.
101
+ // The 3-body-char floor keeps a bare prefix (printed alone in docs/errors) from matching as a
102
+ // key. Duplicated here rather than imported so this package stays dependency-free; a test pins
103
+ // them to the constants so the two cannot drift.
104
+ String.raw`(?:sk|ik|pat|vk)-lw-[A-Za-z0-9_-]{3,}`,
105
+ // GitLab personal, project, deploy, runner and agent tokens.
106
+ String.raw`gl(?:pat|rt|dt|soat|ptt|cbt|imt|agent|ffct)-[A-Za-z0-9_-]{20,}`,
107
+ String.raw`npm_[A-Za-z0-9]{36}`,
108
+ // Google OAuth client secret.
109
+ String.raw`GOCSPX-[A-Za-z0-9_-]{20,}`,
110
+ String.raw`mb_[A-Za-z0-9+/=]{40,}`,
111
+ String.raw`dckr_pat_[A-Za-z0-9_-]{20,}`,
112
+ // Shopify admin, storefront, custom and private app tokens.
113
+ String.raw`shp(?:at|ss|ca|pa)_[0-9a-fA-F]{32}`,
114
+ String.raw`SG\.[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}`,
115
+ String.raw`hf_[A-Za-z0-9]{30,}`,
116
+ String.raw`gsk_[A-Za-z0-9]{40,}`,
117
+ String.raw`pplx-[A-Za-z0-9]{30,}`,
118
+ String.raw`nvapi-[A-Za-z0-9_-]{40,}`,
119
+ String.raw`r8_[A-Za-z0-9]{30,}`,
120
+ String.raw`xai-[A-Za-z0-9]{40,}`,
121
+ // Notion integration tokens, current and legacy.
122
+ String.raw`ntn_[A-Za-z0-9]{30,}`,
123
+ String.raw`secret_[A-Za-z0-9]{40,}`,
124
+ String.raw`dop_v1_[0-9a-f]{64}`,
125
+ String.raw`figd_[A-Za-z0-9_-]{30,}`,
126
+ String.raw`ATATT[A-Za-z0-9_=-]{100,}`,
127
+ String.raw`sq0(?:atp|csp)-[A-Za-z0-9_-]{20,}`,
128
+ String.raw`EAAG[A-Za-z0-9]{60,}`,
129
+ String.raw`key-[0-9a-f]{32}`,
130
+ String.raw`re_[A-Za-z0-9_-]{20,}`,
131
+ String.raw`phx_[A-Za-z0-9]{30,}`,
132
+ String.raw`lin_api_[A-Za-z0-9]{30,}`,
133
+ String.raw`sl\.[A-Za-z0-9_-]{60,}`,
134
+ String.raw`ya29\.[A-Za-z0-9_-]{20,}`,
135
+ String.raw`sbp_[0-9a-f]{40,}`,
136
+ String.raw`sntry(?:s|u)_[A-Za-z0-9_.-]{30,}`,
137
+ String.raw`fw_[A-Za-z0-9]{20,}`,
138
+ String.raw`gl(?:c|sa)_[A-Za-z0-9]{30,}`,
139
+ String.raw`NRAK-[A-Za-z0-9]{20,}`,
140
+ String.raw`PMAK-[A-Za-z0-9]{20,}-[A-Za-z0-9]{20,}`,
141
+ String.raw`dp\.(?:pt|st|ct|sa)\.[A-Za-z0-9_-]{20,}`,
142
+ // Airtable personal access token: patXXXXXXXXXXXXXX.<64 hex>.
143
+ String.raw`pat[A-Za-z0-9]{14}\.[0-9a-f]{64}`,
144
+ // Telegram bot token: <numeric bot id>:AA<35-char body>.
145
+ String.raw`[0-9]{8,10}:AA[A-Za-z0-9_-]{33}`
146
+ ];
147
+ var VENDOR_KEY_REGEX = new RegExp(
148
+ `${TOKEN_START}(?:${VENDOR_KEY_PATTERNS.join("|")})${TOKEN_END}`,
149
+ "g"
150
+ );
151
+ var SHAPED_TOKEN_MIN_BODY = 26;
152
+ var SHAPED_TOKEN_MAX_BODY = 120;
153
+ var SHAPED_TOKEN_MIN_ENTROPY = 3.9;
154
+ function isKeyShapedBody(body) {
155
+ if (body.length < SHAPED_TOKEN_MIN_BODY || body.length > SHAPED_TOKEN_MAX_BODY) {
156
+ return false;
157
+ }
158
+ const { lower, upper, digit } = countCharClasses(body);
159
+ if (lower < 2 || upper < 2 || digit < 2) return false;
160
+ if (isWordSlug(body)) return false;
161
+ return shannonEntropyBits(body) >= SHAPED_TOKEN_MIN_ENTROPY;
162
+ }
163
+ var SLUG_MIN_SEGMENTS = 4;
164
+ var SLUG_LETTERS_SEGMENT = /^[A-Za-z]{1,12}$/;
165
+ var SLUG_TAG_SEGMENT = /^[A-Za-z0-9]{1,6}$/;
166
+ var SLUG_WORD_SEGMENT = /^(?:[a-z]{4,}|[A-Z]{4,}|[A-Z][a-z]{3,})$/;
167
+ var SLUG_RANDOM_SEGMENT = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])/;
168
+ var SLUG_MAX_RANDOM_SEGMENTS = 1;
169
+ var SLUG_MIN_WORDS = 2;
170
+ function isWordSlug(body) {
171
+ const segments = body.split(/[-_]/);
172
+ if (segments.length < SLUG_MIN_SEGMENTS) return false;
173
+ let words = 0;
174
+ let randomLooking = 0;
175
+ for (const segment of segments) {
176
+ if (!SLUG_LETTERS_SEGMENT.test(segment) && !SLUG_TAG_SEGMENT.test(segment)) {
177
+ return false;
178
+ }
179
+ if (SLUG_WORD_SEGMENT.test(segment)) words += 1;
180
+ if (SLUG_RANDOM_SEGMENT.test(segment)) randomLooking += 1;
181
+ }
182
+ return words >= SLUG_MIN_WORDS && randomLooking <= SLUG_MAX_RANDOM_SEGMENTS;
183
+ }
184
+ var DIGEST_PREFIXES = /* @__PURE__ */ new Set([
185
+ "sha1",
186
+ "sha224",
187
+ "sha256",
188
+ "sha384",
189
+ "sha512",
190
+ "sha3",
191
+ "md4",
192
+ "md5",
193
+ "blake2b",
194
+ "blake2s",
195
+ "blake3",
196
+ "crc32",
197
+ "xxh3",
198
+ "xxh64",
199
+ "base32",
200
+ "base58",
201
+ "base64",
202
+ "hex",
203
+ "uuid",
204
+ "urn",
205
+ "cid",
206
+ "etag",
207
+ "hash",
208
+ "digest",
209
+ "checksum",
210
+ "integrity"
211
+ ]);
212
+ var HEX_BODY_CREDENTIAL_SEGMENTS = [
213
+ "live",
214
+ "test",
215
+ "prod",
216
+ "sk",
217
+ "pk",
218
+ "key",
219
+ "secret",
220
+ "token"
221
+ ];
222
+ var IDENTIFIER_PREFIXES = /* @__PURE__ */ new Set([
223
+ "commit",
224
+ "sha",
225
+ "sha1",
226
+ "sha256",
227
+ "md5",
228
+ "hash",
229
+ "digest",
230
+ "trace",
231
+ "span",
232
+ "id",
233
+ "uuid",
234
+ "rev",
235
+ "blob",
236
+ "tree",
237
+ "etag",
238
+ "checksum"
239
+ ]);
240
+ var RECORD_ID_PREFIXES = /* @__PURE__ */ new Set([
241
+ "project",
242
+ "provider",
243
+ "card",
244
+ "eval",
245
+ "monitor",
246
+ "scenario",
247
+ "ses",
248
+ "sess",
249
+ "session",
250
+ "thread",
251
+ "conv",
252
+ "langyconv",
253
+ "span",
254
+ "trace",
255
+ "run",
256
+ "msg",
257
+ "task",
258
+ "job",
259
+ "step",
260
+ "node",
261
+ "team",
262
+ "org",
263
+ "user",
264
+ "call",
265
+ "req",
266
+ "resp",
267
+ "chatcmpl",
268
+ "toolu",
269
+ "asst",
270
+ "file",
271
+ "batch",
272
+ "evt",
273
+ "acct",
274
+ "cus",
275
+ "sub"
276
+ ]);
277
+ var PUBLIC_KEY_PREFIXES = /* @__PURE__ */ new Set(["phc"]);
278
+ function isNonCredentialPrefix(prefix) {
279
+ const lower = prefix.toLowerCase();
280
+ return DIGEST_PREFIXES.has(lower) || IDENTIFIER_PREFIXES.has(lower) || RECORD_ID_PREFIXES.has(lower) || PUBLIC_KEY_PREFIXES.has(lower);
281
+ }
282
+ var HEX_BODY_MIN = 24;
283
+ var HEX_BODY_MAX = 128;
284
+ var PLACEHOLDER_VALUE_REGEX = /^(?:x+|\*+|\.+|-+|_+|0+|(?:your|my|our|insert|replace|example|sample|dummy|fake|placeholder|changeme|redacted|removed|hidden|none|null|nil|undefined|todo|tbd|fixme)[a-z0-9_\- ]*)$/i;
285
+ var ENV_REFERENCE_REGEX = /^(?:\$[A-Za-z_][A-Za-z0-9_]*|[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+)$/;
286
+ var CODE_EXPRESSION_REGEX = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)+$/;
287
+ var PATH_LIKE_REGEX = /^[~.]{0,2}\/|\/[^/\s]*\.[a-z]{1,5}$/;
288
+ var CONTEXT_VALUE_MIN_LENGTH = 16;
289
+ var CONTEXT_VALUE_MIN_ENTROPY = 2.9;
290
+ function isCredentialValue(value) {
291
+ if (value.length < CONTEXT_VALUE_MIN_LENGTH) return false;
292
+ if (PLACEHOLDER_VALUE_REGEX.test(value)) return false;
293
+ if (ENV_REFERENCE_REGEX.test(value)) return false;
294
+ if (CODE_EXPRESSION_REGEX.test(value)) return false;
295
+ if (PATH_LIKE_REGEX.test(value)) return false;
296
+ if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value)) return false;
297
+ if (value.includes(SECRETS_REDACTION_MARKER)) return false;
298
+ return shannonEntropyBits(value) >= CONTEXT_VALUE_MIN_ENTROPY;
299
+ }
300
+ var VERSION_STRING_REGEX = /^v?\d+(?:[._-]\d+)+/;
301
+ var LOOSE_VALUE_MIN_LENGTH = 20;
302
+ var LOOSE_VALUE_MIN_ENTROPY = 3.4;
303
+ function isKeyMaterial(value) {
304
+ if (value.length < LOOSE_VALUE_MIN_LENGTH) return false;
305
+ if (!isCredentialValue(value)) return false;
306
+ if (VERSION_STRING_REGEX.test(value)) return false;
307
+ if (shannonEntropyBits(value) < LOOSE_VALUE_MIN_ENTROPY) return false;
308
+ if (/^[0-9a-f]{32,}$/i.test(value)) return true;
309
+ if (/^[A-Z2-7]{32,}={0,6}$/.test(value)) return true;
310
+ const { lower, upper, digit } = countCharClasses(value);
311
+ return digit >= 2 && (lower >= 2 || upper >= 2);
312
+ }
313
+ var CREDENTIAL_QUALIFIERS = /* @__PURE__ */ new Set([
314
+ "master",
315
+ "encryption",
316
+ "signing",
317
+ "private",
318
+ "access",
319
+ "api",
320
+ "auth",
321
+ "secret",
322
+ "refresh",
323
+ "session",
324
+ "bearer",
325
+ "verification",
326
+ "webhook",
327
+ "client",
328
+ "service",
329
+ "personal",
330
+ "root",
331
+ "admin"
332
+ ]);
333
+ var QUALIFIER_ALTERNATION = [...CREDENTIAL_QUALIFIERS].join("|");
334
+ var CREDENTIAL_KEYWORD = String.raw`(?:x[_.\- ]?)?(?:` + String.raw`(?:${QUALIFIER_ALTERNATION})[_.\- ]?(?:api[_.\- ]?)?key` + String.raw`|(?:${QUALIFIER_ALTERNATION})?[_.\- ]?(?:api[_.\- ]?)?` + String.raw`(?:token|secret|password|passwd|pwd|credentials?|authorization|cookie)` + String.raw`)`;
335
+ function isBasicAuthPayload(value) {
336
+ if (value.endsWith("=")) return true;
337
+ const { lower, upper, digit } = countCharClasses(value);
338
+ return digit > 0 || lower > 0 && upper > 0;
339
+ }
340
+ var VALUE_RULES = [
341
+ {
342
+ id: "pem_private_key",
343
+ description: "PEM private key block",
344
+ regex: /-----BEGIN (?:RSA |EC |DSA |OPENSSH |PGP |ENCRYPTED )?PRIVATE KEY(?: BLOCK)?-----[\s\S]*?-----END (?:RSA |EC |DSA |OPENSSH |PGP |ENCRYPTED )?PRIVATE KEY(?: BLOCK)?-----/g
345
+ },
346
+ {
347
+ // PuTTY's own private-key format, which carries no PEM armour. The body
348
+ // runs to the end of the file, so it is clamped at the next blank line
349
+ // rather than allowed to swallow the rest of the payload.
350
+ id: "putty_private_key",
351
+ description: "PuTTY private key file",
352
+ regex: /PuTTY-User-Key-File-\d+:[\s\S]*?(?:\n\s*\n|$)/g
353
+ },
354
+ {
355
+ // A kubeconfig embeds the client certificate and its key as base64. The
356
+ // key is the credential; the certificate is redacted with it because
357
+ // together they are a working login.
358
+ id: "kubeconfig_client_credentials",
359
+ description: "Embedded kubeconfig client key or certificate",
360
+ regex: /\b(client-(?:key|certificate)-data:\s*)[A-Za-z0-9+/=]{40,}/g,
361
+ render: (_m, prefix) => `${prefix}${REPLACEMENT}`
362
+ },
363
+ {
364
+ id: "aws_access_key_id",
365
+ description: "AWS access key id",
366
+ regex: /\b(?:AKIA|ASIA|AGPA|AIDA|AROA|ANPA|ANVA)[0-9A-Z]{16}\b/g
367
+ },
368
+ {
369
+ id: "github_token",
370
+ description: "GitHub token",
371
+ regex: /\b(?:gh[posru]_[A-Za-z0-9]{36,}|github_pat_[A-Za-z0-9_]{60,})\b/g
372
+ },
373
+ {
374
+ // Provider secret keys share the `sk-` namespace: OpenAI (`sk-proj-...`,
375
+ // legacy `sk-...`), Anthropic (`sk-ant-...`), LangWatch (`sk-lw-...`), and
376
+ // others. The body is base64url, so it includes `_` and `-` and has no inner
377
+ // word boundary; matching the whole token and stopping at the next non-key
378
+ // char catches modern keys a `[A-Za-z0-9]+\b` rule misses.
379
+ id: "provider_api_key",
380
+ description: "Provider API key (sk-...)",
381
+ regex: /\bsk-[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g
382
+ },
383
+ {
384
+ id: "stripe_secret_key",
385
+ description: "Stripe secret key",
386
+ regex: /\b[rs]k_(?:live|test)_[A-Za-z0-9]{16,}\b/g
387
+ },
388
+ {
389
+ id: "slack_token",
390
+ description: "Slack token",
391
+ regex: /\bxox[abposr]-[A-Za-z0-9-]{10,}\b/g
392
+ },
393
+ {
394
+ id: "google_api_key",
395
+ description: "Google API key",
396
+ regex: /\bAIza[0-9A-Za-z_-]{35}\b/g
397
+ },
398
+ {
399
+ id: "vendor_api_key",
400
+ description: "Developer-service API key (GitLab, npm, Docker Hub, Shopify, SendGrid, Hugging Face, Groq, Notion, Atlassian and others)",
401
+ regex: VENDOR_KEY_REGEX
402
+ },
403
+ {
404
+ id: "jwt",
405
+ description: "JSON Web Token",
406
+ regex: /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g
407
+ },
408
+ {
409
+ id: "url_credentials",
410
+ description: "Password embedded in a connection URL",
411
+ // scheme://user:password@host -> keep everything but the password. The scheme sits in a
412
+ // lookbehind so the engine anchors on the literal `:` instead of scanning from every
413
+ // lowercase letter: unanchored this cost 6.2ms on a 200KB payload (more than every other
414
+ // rule combined); anchored, 0.09ms. The scheme stays outside the match and untouched.
415
+ regex: /(?<=[a-z][a-z0-9+.-]{0,30})(:\/\/[^\s:@/]+:)([^\s:@/]+)(@)/gi,
416
+ // The same scheme the lookbehind reads, so a reported match still spans the
417
+ // whole URL rather than starting at the colon.
418
+ precededBy: /[a-z][a-z0-9+.-]{0,30}$/i,
419
+ render: (...[, prefix = "", , at = ""]) => `${prefix}${REPLACEMENT}${at}`
420
+ },
421
+ {
422
+ id: "bearer_token",
423
+ description: "Bearer authorization token",
424
+ regex: /\b(Bearer\s+)[A-Za-z0-9._~+/-]{10,}=*/gi,
425
+ render: (_m, prefix) => `${prefix}${REPLACEMENT}`
426
+ },
427
+ {
428
+ // The other Authorization schemes. Unlike `Bearer` these are ordinary
429
+ // words (`Token`, `OAuth`, `Splunk`), so they are only a credential cue
430
+ // inside an actual Authorization header: a bare "token acme_live_abcd1234"
431
+ // in prose is a sentence, not a header, and matching it redacted one.
432
+ id: "authorization_scheme_token",
433
+ description: "Non-Bearer authorization scheme token",
434
+ regex: /\b(Authorization:\s*(?:Token|SSWS|GenieKey|Splunk|OAuth)\s+)[A-Za-z0-9._~+/-]{10,}=*/gi,
435
+ render: (_m, prefix) => `${prefix}${REPLACEMENT}`
436
+ },
437
+ {
438
+ id: "basic_auth_credentials",
439
+ description: "Basic authorization credentials",
440
+ regex: /\b(Basic\s+)([A-Za-z0-9+/]{16,}={0,2})(?![A-Za-z0-9+/=])/g,
441
+ accept: (groups) => isBasicAuthPayload(groups[2] ?? ""),
442
+ render: (_m, prefix) => `${prefix}${REPLACEMENT}`
443
+ },
444
+ {
445
+ // The all-hex sibling of the shape rule below, which cannot accept a hex
446
+ // body without also accepting every digest and trace id in the transcript.
447
+ // A credential segment in the middle of the token is what makes the
448
+ // difference, so this rule requires one and refuses identifier prefixes on
449
+ // top of it.
450
+ id: "prefixed_hex_api_key",
451
+ description: "API key with a vendor prefix and an all-hex body",
452
+ regex: new RegExp(
453
+ `${TOKEN_START}([A-Za-z][A-Za-z0-9]{1,11})_(?:${HEX_BODY_CREDENTIAL_SEGMENTS.join("|")})_([0-9a-f]{${HEX_BODY_MIN},${HEX_BODY_MAX}})${TOKEN_END}`,
454
+ "gi"
455
+ ),
456
+ accept: (groups) => !IDENTIFIER_PREFIXES.has((groups[1] ?? "").toLowerCase()),
457
+ precondition: (text) => text.includes("_")
458
+ },
459
+ {
460
+ // The layer that catches a vendor nobody has heard of: a short prefix, a separator and a
461
+ // high-entropy body, needing no vendor knowledge. The prefix may be upper, lower or mixed
462
+ // case since plenty of vendors mint `LW_…` or `Xy_…`; that also makes it the shape of a
463
+ // screaming-snake env var NAME, but the length floor and character-mix gate turn those away.
464
+ // A declined match consumes the text it spanned, so in principle an outer match could hide
465
+ // secret material further inside the same token. It cannot in practice: a body containing
466
+ // key material inherits that material's entropy and mix, so the outer match is accepted and
467
+ // the secret is redacted along with its prefix.
468
+ id: "shaped_api_key",
469
+ description: "High-entropy API key with a vendor-style prefix",
470
+ regex: new RegExp(
471
+ `${TOKEN_START}([A-Za-z][A-Za-z0-9]{1,11})[_-]([A-Za-z0-9_+/-]{${SHAPED_TOKEN_MIN_BODY},})${TOKEN_END}`,
472
+ "g"
473
+ ),
474
+ accept: (groups) => !isNonCredentialPrefix(groups[1] ?? "") && isKeyShapedBody(groups[2] ?? ""),
475
+ precondition: (text) => text.includes("_") || text.includes("-")
476
+ },
477
+ {
478
+ // The layer that needs no shape at all: the text says what the value is.
479
+ // Up to two filler words are tolerated between the keyword and the
480
+ // separator, because people write "key now:" and "token here =" as often as
481
+ // they write "key:".
482
+ id: "sensitive_assignment",
483
+ description: "Value assigned to a credential-named field",
484
+ // `key is <value>` was rejected as a strict separator: on real traces it caught zero
485
+ // credentials while being the sole source of prose false-positives. Whitespace is accepted
486
+ // instead on a higher bar — the value must look like key material (see `isKeyMaterial`) —
487
+ // which is what keeps `Authorization <token>` and `key <token>` while rejecting prose.
488
+ // The value class excludes backslash: span content arrives JSON-encoded, so a literal `\n`
489
+ // is two characters, and letting a value run through one carried it across logical lines and
490
+ // past the `$VAR`/code-expression guards — `api_key = $OPENAI_API_KEY` was kept with a real
491
+ // newline and redacted with an escaped one.
492
+ regex: new RegExp(
493
+ `((?:^|[\\W_])(?:${CREDENTIAL_KEYWORD})(?:\\s+[A-Za-z]{1,8}){0,2}["'\`]?(?:\\s*[:=]{1,2}\\s*|[ \\t?-]+)["'\`]?)([^\\s"'\`,;<>(){}\\[\\]\\\\]{${CONTEXT_VALUE_MIN_LENGTH},})`,
494
+ "gi"
495
+ ),
496
+ accept: (groups) => {
497
+ const introduction = groups[1] ?? "";
498
+ const value = groups[2] ?? "";
499
+ const strict = /[:=]\s*["'`]?$/.test(introduction);
500
+ return strict ? isCredentialValue(value) : isKeyMaterial(value);
501
+ },
502
+ render: (_m, introduction) => `${introduction}${REPLACEMENT}`
503
+ }
504
+ ];
505
+ var BUILTIN_SECRET_RULES = VALUE_RULES.map(({ id, description }) => ({ id, description }));
506
+ var SENSITIVE_KEY_REGEX = /(?:^|[._-])(?:password|passwd|pwd|secret|api[_-]?key|apikey|access[_-]?token|auth[_-]?token|authorization|auth|bearer|credentials?|private[_-]?key|client[_-]?secret|db[_-]?password|connection[_-]?string|session[_-]?token|refresh[_-]?token|set[_-]?cookie|cookie|x-api-key)(?:$|[._-])/i;
507
+ var CREDENTIAL_NOUNS = /* @__PURE__ */ new Set([
508
+ "password",
509
+ "passwd",
510
+ "pwd",
511
+ "secret",
512
+ "authorization",
513
+ "auth",
514
+ "bearer",
515
+ "credential",
516
+ "credentials",
517
+ "cookie"
518
+ ]);
519
+ function tokenizeAttributeName(name) {
520
+ return name.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").split(/[^A-Za-z0-9]+/).filter(Boolean).map((token) => token.toLowerCase());
521
+ }
522
+ function namesACredential(name) {
523
+ const tokens = tokenizeAttributeName(name);
524
+ return tokens.some((token, index) => {
525
+ if (CREDENTIAL_NOUNS.has(token)) return true;
526
+ if (token !== "key" && token !== "token") return false;
527
+ const previous = tokens[index - 1];
528
+ return previous !== void 0 && CREDENTIAL_QUALIFIERS.has(previous);
529
+ });
530
+ }
531
+ function isSensitiveAttributeKey(key) {
532
+ return SENSITIVE_KEY_REGEX.test(key) || namesACredential(key);
533
+ }
534
+ var VALUE_BOUNDARY = /["'`]/;
535
+ function keptLengthAtBoundary(match) {
536
+ const index = match.search(VALUE_BOUNDARY);
537
+ return index === -1 ? match.length : index;
538
+ }
539
+ var CUSTOM_VALUE_BOUNDARY = /[\s"'`<>]/;
540
+ function keptLengthForCustomPattern(match) {
541
+ const index = match.search(CUSTOM_VALUE_BOUNDARY);
542
+ return index === -1 ? match.length : index;
543
+ }
544
+ function replacementFor(rule, args) {
545
+ const full = args[0] ?? "";
546
+ if (rule.accept && !rule.accept(args)) return null;
547
+ if (rule.render) return rule.render(...args);
548
+ const kept = keptLengthAtBoundary(full);
549
+ if (kept === 0) return null;
550
+ return REPLACEMENT + full.slice(kept);
551
+ }
552
+ function sliceForScan(text) {
553
+ if (text.length <= MAX_SCAN_LENGTH) return [text];
554
+ const slices = [];
555
+ let start = 0;
556
+ while (start < text.length) {
557
+ const end = sliceEndAfter(text, start);
558
+ slices.push(text.slice(start, end));
559
+ start = end;
560
+ }
561
+ return slices;
562
+ }
563
+ function sliceEndAfter(text, start) {
564
+ const target = Math.min(start + MAX_SCAN_LENGTH, text.length);
565
+ if (target >= text.length) return text.length;
566
+ let end;
567
+ const lastSpace = text.slice(start, target).search(/\s(?=\S*$)/);
568
+ if (lastSpace > 0) {
569
+ end = start + lastSpace;
570
+ } else {
571
+ const lookahead = text.slice(target, target + SAFE_CUT_LOOKAHEAD);
572
+ const next = lookahead.search(/\s/);
573
+ end = next === -1 ? Math.min(target + SAFE_CUT_LOOKAHEAD, text.length) : target + next;
574
+ }
575
+ const begin = text.lastIndexOf(PEM_BEGIN, end);
576
+ const close = text.indexOf(PEM_END, begin);
577
+ if (begin >= start && close >= end) {
578
+ end = close + PEM_END.length;
579
+ }
580
+ return end;
581
+ }
582
+ var SAFE_CUT_LOOKAHEAD = 4096;
583
+ var PEM_BEGIN = "-----BEGIN";
584
+ var PEM_END = "-----END";
585
+ function redactSecretsInText({
586
+ text,
587
+ customPatterns = [],
588
+ skipRuleIds
589
+ }) {
590
+ if (typeof text !== "string" || text.length === 0) {
591
+ return { text, redactedCount: 0 };
592
+ }
593
+ const skipped = toSkipSet(skipRuleIds);
594
+ if (text.length > MAX_SCAN_LENGTH) {
595
+ let total = 0;
596
+ const pieces = sliceForScan(text).map((slice) => {
597
+ const scanned = redactOneSlice(slice, customPatterns, skipped);
598
+ total += scanned.redactedCount;
599
+ return scanned.text;
600
+ });
601
+ return { text: pieces.join(""), redactedCount: total };
602
+ }
603
+ return redactOneSlice(text, customPatterns, skipped);
604
+ }
605
+ function toSkipSet(skipRuleIds) {
606
+ if (!skipRuleIds || skipRuleIds.length === 0) return null;
607
+ return new Set(skipRuleIds);
608
+ }
609
+ function redactOneSlice(text, customPatterns, skipped) {
610
+ let redactedCount = 0;
611
+ let result = text;
612
+ for (const rule of VALUE_RULES) {
613
+ if (skipped?.has(rule.id)) continue;
614
+ if (rule.precondition && !rule.precondition(result)) continue;
615
+ result = result.replace(rule.regex, (...args) => {
616
+ const replacement = replacementFor(rule, args);
617
+ if (replacement === null) return args[0] ?? "";
618
+ redactedCount++;
619
+ return replacement;
620
+ });
621
+ }
622
+ for (const pattern of customPatterns) {
623
+ result = result.replace(pattern, (...args) => {
624
+ const full = args[0] ?? "";
625
+ const kept = keptLengthForCustomPattern(full);
626
+ if (kept === 0) return full;
627
+ redactedCount++;
628
+ return REPLACEMENT + full.slice(kept);
629
+ });
630
+ }
631
+ return { text: result, redactedCount };
632
+ }
633
+
634
+ // ../../packages/redaction/src/sessionReport.ts
635
+ var EMAIL_MARKER = formatPiiMarker("EMAIL_ADDRESS");
636
+ var PHONE_MARKER = formatPiiMarker("PHONE_NUMBER");
637
+ var CARD_MARKER = formatPiiMarker("CREDIT_CARD");
638
+ var IP_MARKER = formatPiiMarker("IP_ADDRESS");
639
+ var ENV_SECRET_NAME_REGEX = /(?:^|[._-])(?:key|token|secret|password|passwd|pwd|credentials?|auth)(?:$|[._-])/i;
640
+ var MIN_ENV_SECRET_LENGTH = 8;
641
+ function collectSensitiveEnvValues(env) {
642
+ const values = /* @__PURE__ */ new Set();
643
+ for (const [name, value] of Object.entries(env)) {
644
+ if (!value) continue;
645
+ const trimmed = value.trim();
646
+ if (trimmed.length < MIN_ENV_SECRET_LENGTH) continue;
647
+ if (!ENV_SECRET_NAME_REGEX.test(name)) continue;
648
+ values.add(trimmed);
649
+ }
650
+ return [...values].toSorted((a, b) => b.length - a.length);
651
+ }
652
+ var EMAIL_REGEX = /[A-Za-z0-9._%+-]{1,64}@[A-Za-z0-9.-]{1,253}\.[A-Za-z]{2,24}/g;
653
+ var INTL_PHONE_REGEX = /(?<![\w.+-])\+[1-9]\d{0,2}(?:[\s.-]?(?:\(\d{1,4}\)[\s.-]?)?\d{1,4}){1,5}(?!\d)/g;
654
+ var NATIONAL_PHONE_REGEX = /(?<!\d)(?:\(\d{3}\)[\s.-]?|\d{3}[.-])\d{3}[.-]\d{4}(?!\d)/g;
655
+ var CARD_REGEX = /(?<![\d.-])\d(?:[ -]?\d){12,18}(?![\d.-])/g;
656
+ var IPV4_REGEX = /\b(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\b/g;
657
+ var countDigits = (value) => value.replace(/\D/g, "").length;
658
+ function passesLuhn(digits) {
659
+ let sum = 0;
660
+ let double = false;
661
+ for (let i = digits.length - 1; i >= 0; i--) {
662
+ let d = digits.charCodeAt(i) - 48;
663
+ if (double) {
664
+ d *= 2;
665
+ if (d > 9) d -= 9;
666
+ }
667
+ sum += d;
668
+ double = !double;
669
+ }
670
+ return sum % 10 === 0;
671
+ }
672
+ function isCardNumber(candidate) {
673
+ const digits = candidate.replace(/[ -]/g, "");
674
+ if (!/^\d+$/.test(digits)) return false;
675
+ const separated = /[ -]/.test(candidate);
676
+ if (!separated && (digits.length < 14 || digits.length > 16)) return false;
677
+ if (digits.length < 13 || digits.length > 19) return false;
678
+ return passesLuhn(digits);
679
+ }
680
+ function isPrivateOrLocalIp(ip) {
681
+ const parts = ip.split(".").map(Number);
682
+ const [a = 0, b = 0] = parts;
683
+ if (a === 0 || a === 10 || a === 127) return true;
684
+ if (a === 192 && b === 168) return true;
685
+ if (a === 172 && b >= 16 && b <= 31) return true;
686
+ if (a === 169 && b === 254) return true;
687
+ if (a === 100 && b >= 64 && b <= 127) return true;
688
+ if (a >= 224) return true;
689
+ return false;
690
+ }
691
+ var SLICE_TARGET = 2e5;
692
+ function sliceLongText(text) {
693
+ if (text.length <= SLICE_TARGET) return [text];
694
+ const slices = [];
695
+ let start = 0;
696
+ while (start < text.length) {
697
+ let end = Math.min(start + SLICE_TARGET, text.length);
698
+ if (end < text.length) {
699
+ const newline = text.lastIndexOf("\n", end);
700
+ if (newline > start + SLICE_TARGET / 2) end = newline;
701
+ }
702
+ slices.push(text.slice(start, end));
703
+ start = end;
704
+ }
705
+ return slices;
706
+ }
707
+ function redactPiiPatterns(text) {
708
+ let redactedCount = 0;
709
+ let result = text.replace(EMAIL_REGEX, () => {
710
+ redactedCount++;
711
+ return EMAIL_MARKER;
712
+ });
713
+ result = result.replace(CARD_REGEX, (match) => {
714
+ if (!isCardNumber(match)) return match;
715
+ redactedCount++;
716
+ return CARD_MARKER;
717
+ });
718
+ result = result.replace(INTL_PHONE_REGEX, (match) => {
719
+ const digits = countDigits(match);
720
+ if (digits < 7 || digits > 15) return match;
721
+ redactedCount++;
722
+ return PHONE_MARKER;
723
+ });
724
+ result = result.replace(NATIONAL_PHONE_REGEX, () => {
725
+ redactedCount++;
726
+ return PHONE_MARKER;
727
+ });
728
+ result = result.replace(IPV4_REGEX, (match) => {
729
+ if (isPrivateOrLocalIp(match)) return match;
730
+ redactedCount++;
731
+ return IP_MARKER;
732
+ });
733
+ return { text: result, redactedCount };
734
+ }
735
+ function scrubEnvLiterals(text, envValues) {
736
+ let result = text;
737
+ let redactedCount = 0;
738
+ for (const value of envValues) {
739
+ if (!result.includes(value)) continue;
740
+ const parts = result.split(value);
741
+ redactedCount += parts.length - 1;
742
+ result = parts.join(SECRET_MARKER);
743
+ }
744
+ return { text: result, redactedCount };
745
+ }
746
+ function redactReportText({
747
+ text,
748
+ envValues = []
749
+ }) {
750
+ if (typeof text !== "string" || text.length === 0) {
751
+ return { text, redactedCount: 0 };
752
+ }
753
+ const envPass = scrubEnvLiterals(text, envValues);
754
+ let redactedCount = envPass.redactedCount;
755
+ const pieces = sliceLongText(envPass.text).map((slice) => {
756
+ const secrets = redactSecretsInText({ text: slice });
757
+ redactedCount += secrets.redactedCount;
758
+ const pii = redactPiiPatterns(secrets.text);
759
+ redactedCount += pii.redactedCount;
760
+ return pii.text;
761
+ });
762
+ return { text: pieces.join(""), redactedCount };
763
+ }
764
+ function redactJsonValue(value, envValues, count) {
765
+ if (typeof value === "string") {
766
+ const result = redactReportText({ text: value, envValues });
767
+ count.redacted += result.redactedCount;
768
+ return result.text;
769
+ }
770
+ if (Array.isArray(value)) {
771
+ return value.map((item) => redactJsonValue(item, envValues, count));
772
+ }
773
+ if (value && typeof value === "object") {
774
+ const out = {};
775
+ for (const [key, entry] of Object.entries(value)) {
776
+ if (isSensitiveAttributeKey(key) && entry !== null && entry !== void 0) {
777
+ out[key] = SECRET_MARKER;
778
+ count.redacted++;
779
+ continue;
780
+ }
781
+ out[key] = redactJsonValue(entry, envValues, count);
782
+ }
783
+ return out;
784
+ }
785
+ return value;
786
+ }
787
+ function redactSessionJsonl({
788
+ jsonl,
789
+ envValues = []
790
+ }) {
791
+ let redactedCount = 0;
792
+ const lines = jsonl.split("\n").map((line) => {
793
+ if (line.trim().length === 0) return line;
794
+ try {
795
+ const parsed = JSON.parse(line);
796
+ const count = { redacted: 0 };
797
+ const redacted = redactJsonValue(parsed, envValues, count);
798
+ redactedCount += count.redacted;
799
+ return JSON.stringify(redacted);
800
+ } catch {
801
+ const result = redactReportText({ text: line, envValues });
802
+ redactedCount += result.redactedCount;
803
+ return result.text;
804
+ }
805
+ });
806
+ return { text: lines.join("\n"), redactedCount };
807
+ }
808
+ function truncateJsonlToByteBudget({
809
+ jsonl,
810
+ maxBytes
811
+ }) {
812
+ const encoder = new TextEncoder();
813
+ if (encoder.encode(jsonl).length <= maxBytes) {
814
+ return { text: jsonl, truncated: false };
815
+ }
816
+ const lines = jsonl.split("\n");
817
+ const kept = [];
818
+ let used = 0;
819
+ for (let i = lines.length - 1; i >= 0; i--) {
820
+ const line = lines[i] ?? "";
821
+ const size = encoder.encode(line).length + 1;
822
+ if (used + size > maxBytes) break;
823
+ kept.unshift(line);
824
+ used += size;
825
+ }
826
+ return { text: kept.join("\n"), truncated: true };
827
+ }
828
+ var REDACTION_AUDIT_URL = "https://github.com/langwatch/langwatch/blob/main/packages/redaction/src/sessionReport.ts";
829
+
830
+ // src/tools/report-issue.ts
831
+ var MAX_SESSION_BYTES = 8 * 1024 * 1024;
832
+ var REQUEST_TIMEOUT_MS = 6e4;
833
+ function redactReport(params) {
834
+ const envValues = collectSensitiveEnvValues(process.env);
835
+ let redactedCount = 0;
836
+ const titleResult = redactReportText({ text: params.title, envValues });
837
+ redactedCount += titleResult.redactedCount;
838
+ let summary;
839
+ if (params.summary) {
840
+ const result = redactReportText({ text: params.summary, envValues });
841
+ summary = result.text;
842
+ redactedCount += result.redactedCount;
843
+ }
844
+ let sessionData;
845
+ let sessionTruncated = false;
846
+ if (params.session_content) {
847
+ const redacted = redactSessionJsonl({
848
+ jsonl: params.session_content,
849
+ envValues
850
+ });
851
+ redactedCount += redacted.redactedCount;
852
+ const truncated = truncateJsonlToByteBudget({
853
+ jsonl: redacted.text,
854
+ maxBytes: MAX_SESSION_BYTES
855
+ });
856
+ sessionData = truncated.text;
857
+ sessionTruncated = truncated.truncated;
858
+ }
859
+ return {
860
+ title: titleResult.text,
861
+ summary,
862
+ sessionData,
863
+ sessionTruncated,
864
+ redactedCount
865
+ };
866
+ }
867
+ async function deliverReport(report, params) {
868
+ const config = getConfig();
869
+ const endpoint = config.endpoint.replace(/\/+$/, "");
870
+ const response = await fetch(`${endpoint}/api/v1/bug-reports`, {
871
+ method: "POST",
872
+ headers: {
873
+ "content-type": "application/json",
874
+ "x-api-version": LANGWATCH_API_VERSION,
875
+ ...config.apiKey ? { authorization: `Bearer ${config.apiKey}` } : {}
876
+ },
877
+ body: JSON.stringify({
878
+ source: "mcp",
879
+ kind: report.sessionData ? "full_session" : "summary",
880
+ title: report.title,
881
+ ...report.summary ? { summary: report.summary } : {},
882
+ ...report.sessionData ? { sessionData: report.sessionData, sessionTruncated: report.sessionTruncated } : {},
883
+ ...params.agent ? { agent: params.agent } : {},
884
+ ...params.contact_email ? { contactEmail: params.contact_email } : {}
885
+ }),
886
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
887
+ }).catch(() => {
888
+ throw new Error(
889
+ `Could not reach ${endpoint} to deliver the report. Retry in a moment; if it keeps failing, email support@langwatch.ai with the same content.`
890
+ );
891
+ });
892
+ if (!response.ok) {
893
+ const body = (await response.text().catch(() => "")).slice(0, 300);
894
+ throw new Error(
895
+ `The reports endpoint answered HTTP ${response.status}: ${body}. Retry in a moment; if it keeps failing, email support@langwatch.ai.`
896
+ );
897
+ }
898
+ const { id } = await response.json();
899
+ return id;
900
+ }
901
+ async function handleReportIssue(params) {
902
+ if (!params.user_approved) {
903
+ throw new Error(
904
+ `This sends a report to the LangWatch team, so the user must approve it first. Ask the user: "Can I send this issue report to LangWatch to help them fix it?" If they agree, call again with user_approved=true. Secrets and personal data are redacted locally before sending; audit the rules at ${REDACTION_AUDIT_URL}`
905
+ );
906
+ }
907
+ if (!params.summary?.trim() && !params.session_content?.trim()) {
908
+ throw new Error(
909
+ "Nothing to report: pass a summary (what you tried, verbatim errors, what you had to figure out), session_content, or both."
910
+ );
911
+ }
912
+ const report = redactReport(params);
913
+ const id = await deliverReport(report, params);
914
+ return [
915
+ `Report sent to the LangWatch team (${id}). Thank you!`,
916
+ `Redacted ${report.redactedCount} sensitive value${report.redactedCount === 1 ? "" : "s"} locally before sending.`,
917
+ ...report.sessionTruncated ? ["The session content was truncated to the most recent activity to fit the upload limit."] : [],
918
+ "Reports like this directly shape what gets fixed next."
919
+ ].join(" ");
920
+ }
921
+ export {
922
+ handleReportIssue
923
+ };
924
+ //# sourceMappingURL=report-issue-5HSL7CNB.js.map