@langwatch/mcp-server 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/.release-please-shim +1 -0
  2. package/CHANGELOG.md +87 -0
  3. package/LICENSE +7 -0
  4. package/dist/archive-project-HZBRPR2S.js +19 -0
  5. package/dist/{archive-scenario-WJ2A7ETN.js → archive-scenario-P5RRITRM.js} +4 -4
  6. package/dist/{archive-suite-4JOM4SSL.js → archive-suite-NUUFD2EM.js} +4 -4
  7. package/dist/{assign-prompt-tag-GL7EAAF3.js → assign-prompt-tag-FKCCZPML.js} +3 -3
  8. package/dist/{chunk-2WPLXEKF.js → chunk-42ZHHHIJ.js} +20 -5
  9. package/dist/chunk-ADSJ2FDA.js +44 -0
  10. package/dist/{chunk-IE4M5OGE.js → chunk-BB7EOKHR.js} +2 -2
  11. package/dist/chunk-BBJ5WAJB.js +24 -0
  12. package/dist/{chunk-EGH5RPXM.js → chunk-BYWYM2RP.js} +2 -2
  13. package/dist/{chunk-2GT7IFWK.js → chunk-CCM4ZFGF.js} +2 -2
  14. package/dist/{chunk-LUMEZEHL.js → chunk-CHKCEZBP.js} +2 -2
  15. package/dist/{chunk-ZVS4UKN2.js → chunk-HKY3GW45.js} +2 -2
  16. package/dist/{chunk-EUQDVOSU.js → chunk-JHOSVOHT.js} +2 -2
  17. package/dist/{chunk-E5JYYU3J.js → chunk-JVLJKQJG.js} +669 -94
  18. package/dist/{chunk-BWWY5KEF.js → chunk-KOO5733S.js} +3 -2
  19. package/dist/{chunk-HYMIWO3U.js → chunk-R7C7OUVG.js} +2 -2
  20. package/dist/{chunk-WQG2DFHX.js → chunk-TROIWSEQ.js} +2 -2
  21. package/dist/{chunk-CCWCIJJ3.js → chunk-X2SEURT2.js} +2 -2
  22. package/dist/{chunk-4AUB2BIA.js → chunk-XC62KJIT.js} +3 -3
  23. package/dist/config.js +1 -1
  24. package/dist/{create-agent-MBOOT3XK.js → create-agent-K5Q7BFGZ.js} +4 -4
  25. package/dist/{create-annotation-XMV6A7ED.js → create-annotation-KN3GE3DK.js} +4 -4
  26. package/dist/create-api-key-OQI5PUNQ.js +26 -0
  27. package/dist/{create-dashboard-VRKLFVZJ.js → create-dashboard-G4QA5AXP.js} +4 -4
  28. package/dist/{create-dataset-7HQPZCRE.js → create-dataset-WQSC37N7.js} +4 -4
  29. package/dist/{create-dataset-records-2NIVFYTV.js → create-dataset-records-B4RL3FLC.js} +4 -4
  30. package/dist/{create-evaluator-WYFRFLRC.js → create-evaluator-YFFQIR7E.js} +4 -4
  31. package/dist/create-mcp-server.js +3 -2
  32. package/dist/create-project-CUVQ67VN.js +44 -0
  33. package/dist/{create-prompt-IEN7O6JT.js → create-prompt-NGXKSP4X.js} +3 -3
  34. package/dist/{create-prompt-tag-CAEZ45VO.js → create-prompt-tag-IUKYPVHH.js} +3 -3
  35. package/dist/{create-scenario-6YHSMGLP.js → create-scenario-FNBXALH3.js} +4 -4
  36. package/dist/{create-suite-H5XOFDE5.js → create-suite-DJEPD4ZB.js} +4 -4
  37. package/dist/{delete-agent-JKTNBWAA.js → delete-agent-TJI5XBBM.js} +4 -4
  38. package/dist/{delete-annotation-ACMDV6QO.js → delete-annotation-KRP53TUU.js} +4 -4
  39. package/dist/{delete-dashboard-VJSR7CRU.js → delete-dashboard-N5SZJIR3.js} +4 -4
  40. package/dist/{delete-dataset-RTTTWP4D.js → delete-dataset-KDUOHL2P.js} +4 -4
  41. package/dist/{delete-dataset-records-KNQTIPQK.js → delete-dataset-records-DM4W3PAW.js} +4 -4
  42. package/dist/{delete-evaluator-7FVC5WM4.js → delete-evaluator-7ZATLJOA.js} +4 -4
  43. package/dist/{delete-prompt-tag-ZMZUAGFW.js → delete-prompt-tag-I6HNMSVJ.js} +3 -3
  44. package/dist/{delete-workflow-EYQ3T4RQ.js → delete-workflow-QEO74JQR.js} +4 -4
  45. package/dist/{get-agent-E3QSTVKG.js → get-agent-3KDWCP5N.js} +4 -4
  46. package/dist/{get-analytics-2OHV763I.js → get-analytics-GPVJX7SF.js} +3 -3
  47. package/dist/{get-dashboard-PC7JDHH6.js → get-dashboard-YPTIE5YY.js} +4 -4
  48. package/dist/{get-dataset-H5IK5FVU.js → get-dataset-6DQFYITM.js} +4 -4
  49. package/dist/{get-evaluator-UWVUPYTM.js → get-evaluator-PCM6XQAU.js} +4 -4
  50. package/dist/get-project-JCMWXVLU.js +26 -0
  51. package/dist/{get-prompt-WZUOLLQC.js → get-prompt-5XAGWWBG.js} +3 -3
  52. package/dist/{get-scenario-Q6LCNUYN.js → get-scenario-7XBCDZWX.js} +4 -4
  53. package/dist/{get-simulation-run-Z2XKO256.js → get-simulation-run-AV24FJWI.js} +4 -4
  54. package/dist/{get-suite-BXK5TN7P.js → get-suite-4DBVHFEM.js} +4 -4
  55. package/dist/{get-trace-4EJAYVBG.js → get-trace-MRBDS3HJ.js} +3 -3
  56. package/dist/{get-workflow-O34QJLHD.js → get-workflow-UR4Y6UFX.js} +4 -4
  57. package/dist/{http-server-ISHF7NJX.js → http-server-DEGNV5EP.js} +4 -3
  58. package/dist/index.js +1453 -431
  59. package/dist/{langwatch-api-annotations-ERBG27RF.js → langwatch-api-annotations-ZJDRB4JH.js} +4 -4
  60. package/dist/{langwatch-api-dashboards-G6TR7VVO.js → langwatch-api-dashboards-WARLI6NF.js} +4 -4
  61. package/dist/{langwatch-api-monitors-WSXZLS2B.js → langwatch-api-monitors-4XKXHYCG.js} +3 -3
  62. package/dist/{langwatch-api-secrets-RR5DKG2X.js → langwatch-api-secrets-6SHK5G7Q.js} +3 -3
  63. package/dist/{langwatch-api-triggers-2RTNSWQY.js → langwatch-api-triggers-5SX6R2WU.js} +3 -3
  64. package/dist/langwatch-api-workflows-NLJENNXE.js +15 -0
  65. package/dist/{list-agents-AW3P6FJV.js → list-agents-NECO7MPI.js} +4 -4
  66. package/dist/{list-annotations-QNCGWPQ3.js → list-annotations-3OJEO774.js} +4 -4
  67. package/dist/list-api-keys-AWW7ROLB.js +37 -0
  68. package/dist/{list-dashboards-R7RK2IXL.js → list-dashboards-DVPVVVKW.js} +4 -4
  69. package/dist/{list-dataset-records-WVCSQP7P.js → list-dataset-records-I4BYORF5.js} +4 -4
  70. package/dist/{list-datasets-KEXRLDEU.js → list-datasets-WUAE5HGX.js} +4 -4
  71. package/dist/{list-evaluators-7R2LB4JH.js → list-evaluators-B6OSVAM2.js} +4 -4
  72. package/dist/{list-model-providers-OBYJCKBX.js → list-model-providers-NL6IP4UZ.js} +4 -4
  73. package/dist/list-projects-5FHMJ4PQ.js +42 -0
  74. package/dist/{list-prompt-tags-6LY3ZPYI.js → list-prompt-tags-Z2DD6FLQ.js} +3 -3
  75. package/dist/{list-prompts-VWEZ4CDE.js → list-prompts-VNXKHK7T.js} +3 -3
  76. package/dist/{list-scenarios-TXD4W2ZJ.js → list-scenarios-CFZHXL76.js} +4 -4
  77. package/dist/{list-simulation-runs-RHPOLMFI.js → list-simulation-runs-AM2BXLBW.js} +4 -4
  78. package/dist/{list-suites-FSGBX27Z.js → list-suites-ZDOHAAXF.js} +4 -4
  79. package/dist/{list-workflows-VRGEZ3EN.js → list-workflows-WBRBKLIT.js} +4 -4
  80. package/dist/{rename-prompt-tag-VOJJLX4M.js → rename-prompt-tag-A4RJUK7Z.js} +3 -3
  81. package/dist/revoke-api-key-ZSPSPF5G.js +15 -0
  82. package/dist/{run-agent-KTCC7TB7.js → run-agent-JFNDY7MR.js} +4 -4
  83. package/dist/{run-suite-BTMHGI2D.js → run-suite-TH7LO5TJ.js} +4 -4
  84. package/dist/{run-workflow-IGAYGKJL.js → run-workflow-CK3JP5U2.js} +4 -4
  85. package/dist/{search-traces-VYFUIMXH.js → search-traces-3BBVYPC3.js} +3 -3
  86. package/dist/{set-model-provider-W5IUI326.js → set-model-provider-WOC5FNMV.js} +4 -4
  87. package/dist/{update-agent-4BB7EYLR.js → update-agent-YMEV5MTL.js} +4 -4
  88. package/dist/{update-dataset-CXBKZ4W3.js → update-dataset-EYT5POFM.js} +4 -4
  89. package/dist/{update-dataset-record-HOHAMHXG.js → update-dataset-record-VFF5JTX4.js} +4 -4
  90. package/dist/{update-evaluator-IVOR6FTR.js → update-evaluator-6IJHFG2E.js} +4 -4
  91. package/dist/update-project-OIT4WPFI.js +24 -0
  92. package/dist/{update-prompt-OWQAKE7K.js → update-prompt-ZU2DD6KM.js} +3 -3
  93. package/dist/{update-scenario-GDFVILPN.js → update-scenario-3VUTPDRU.js} +4 -4
  94. package/dist/{update-suite-BXYUYSPT.js → update-suite-C6JFDQHL.js} +4 -4
  95. package/package.json +7 -7
  96. package/pnpm-workspace.yaml +2 -0
  97. package/pyproject.toml +3 -0
  98. package/src/__tests__/all-tools.integration.test.ts +9 -0
  99. package/src/__tests__/datasets.integration.test.ts +17 -0
  100. package/src/__tests__/datasets.unit.test.ts +4 -0
  101. package/src/__tests__/experiment-list-tools.unit.test.ts +157 -0
  102. package/src/__tests__/get-experiment-results.unit.test.ts +222 -0
  103. package/src/__tests__/project-api-key-tools.unit.test.ts +451 -0
  104. package/src/__tests__/scenario-tools.unit.test.ts +3 -0
  105. package/src/config.ts +2 -0
  106. package/src/create-mcp-server.ts +257 -13
  107. package/src/langwatch-api-api-keys.ts +54 -0
  108. package/src/langwatch-api-projects.ts +82 -0
  109. package/src/langwatch-api.ts +22 -4
  110. package/src/tools/archive-project.ts +14 -0
  111. package/src/tools/create-api-key.ts +29 -0
  112. package/src/tools/create-project.ts +45 -0
  113. package/src/tools/get-experiment-results.ts +273 -0
  114. package/src/tools/get-project.ts +20 -0
  115. package/src/tools/list-api-keys.ts +33 -0
  116. package/src/tools/list-experiment-runs.ts +142 -0
  117. package/src/tools/list-experiments.ts +95 -0
  118. package/src/tools/list-projects.ts +41 -0
  119. package/src/tools/revoke-api-key.ts +9 -0
  120. package/src/tools/{run-evaluation.ts → run-experiment.ts} +5 -5
  121. package/src/tools/update-project.ts +22 -0
  122. package/uv.lock +192 -530
  123. package/Dockerfile +0 -22
  124. package/build.js +0 -12
  125. package/dist/archive-scenario-WJ2A7ETN.js.map +0 -1
  126. package/dist/archive-suite-4JOM4SSL.js.map +0 -1
  127. package/dist/assign-prompt-tag-GL7EAAF3.js.map +0 -1
  128. package/dist/chunk-2GT7IFWK.js.map +0 -1
  129. package/dist/chunk-2WPLXEKF.js.map +0 -1
  130. package/dist/chunk-4AUB2BIA.js.map +0 -1
  131. package/dist/chunk-BWWY5KEF.js.map +0 -1
  132. package/dist/chunk-CCWCIJJ3.js.map +0 -1
  133. package/dist/chunk-E5JYYU3J.js.map +0 -1
  134. package/dist/chunk-EGH5RPXM.js.map +0 -1
  135. package/dist/chunk-EUQDVOSU.js.map +0 -1
  136. package/dist/chunk-HYMIWO3U.js.map +0 -1
  137. package/dist/chunk-IE4M5OGE.js.map +0 -1
  138. package/dist/chunk-LUMEZEHL.js.map +0 -1
  139. package/dist/chunk-NUFPTHKU.js.map +0 -1
  140. package/dist/chunk-WQG2DFHX.js.map +0 -1
  141. package/dist/chunk-WVI5CJ6S.js.map +0 -1
  142. package/dist/chunk-ZVS4UKN2.js.map +0 -1
  143. package/dist/chunk-ZXKLPC2E.js.map +0 -1
  144. package/dist/config.js.map +0 -1
  145. package/dist/create-agent-MBOOT3XK.js.map +0 -1
  146. package/dist/create-annotation-XMV6A7ED.js.map +0 -1
  147. package/dist/create-dashboard-VRKLFVZJ.js.map +0 -1
  148. package/dist/create-dataset-7HQPZCRE.js.map +0 -1
  149. package/dist/create-dataset-records-2NIVFYTV.js.map +0 -1
  150. package/dist/create-evaluator-WYFRFLRC.js.map +0 -1
  151. package/dist/create-mcp-server.js.map +0 -1
  152. package/dist/create-prompt-IEN7O6JT.js.map +0 -1
  153. package/dist/create-prompt-tag-CAEZ45VO.js.map +0 -1
  154. package/dist/create-scenario-6YHSMGLP.js.map +0 -1
  155. package/dist/create-suite-H5XOFDE5.js.map +0 -1
  156. package/dist/delete-agent-JKTNBWAA.js.map +0 -1
  157. package/dist/delete-annotation-ACMDV6QO.js.map +0 -1
  158. package/dist/delete-dashboard-VJSR7CRU.js.map +0 -1
  159. package/dist/delete-dataset-RTTTWP4D.js.map +0 -1
  160. package/dist/delete-dataset-records-KNQTIPQK.js.map +0 -1
  161. package/dist/delete-evaluator-7FVC5WM4.js.map +0 -1
  162. package/dist/delete-prompt-tag-ZMZUAGFW.js.map +0 -1
  163. package/dist/delete-workflow-EYQ3T4RQ.js.map +0 -1
  164. package/dist/discover-evaluator-schema-H23XCLNE.js.map +0 -1
  165. package/dist/discover-scenario-schema-MEEEVND7.js.map +0 -1
  166. package/dist/discover-schema-3T52ORPB.js.map +0 -1
  167. package/dist/get-agent-E3QSTVKG.js.map +0 -1
  168. package/dist/get-analytics-2OHV763I.js.map +0 -1
  169. package/dist/get-dashboard-PC7JDHH6.js.map +0 -1
  170. package/dist/get-dataset-H5IK5FVU.js.map +0 -1
  171. package/dist/get-evaluator-UWVUPYTM.js.map +0 -1
  172. package/dist/get-prompt-WZUOLLQC.js.map +0 -1
  173. package/dist/get-scenario-Q6LCNUYN.js.map +0 -1
  174. package/dist/get-simulation-run-Z2XKO256.js.map +0 -1
  175. package/dist/get-suite-BXK5TN7P.js.map +0 -1
  176. package/dist/get-trace-4EJAYVBG.js.map +0 -1
  177. package/dist/get-workflow-O34QJLHD.js.map +0 -1
  178. package/dist/http-server-ISHF7NJX.js.map +0 -1
  179. package/dist/index.js.map +0 -1
  180. package/dist/langwatch-api-annotations-ERBG27RF.js.map +0 -1
  181. package/dist/langwatch-api-dashboards-G6TR7VVO.js.map +0 -1
  182. package/dist/langwatch-api-monitors-WSXZLS2B.js.map +0 -1
  183. package/dist/langwatch-api-secrets-RR5DKG2X.js.map +0 -1
  184. package/dist/langwatch-api-triggers-2RTNSWQY.js.map +0 -1
  185. package/dist/langwatch-api-workflows-VJRIIDZ7.js +0 -15
  186. package/dist/langwatch-api-workflows-VJRIIDZ7.js.map +0 -1
  187. package/dist/list-agents-AW3P6FJV.js.map +0 -1
  188. package/dist/list-annotations-QNCGWPQ3.js.map +0 -1
  189. package/dist/list-dashboards-R7RK2IXL.js.map +0 -1
  190. package/dist/list-dataset-records-WVCSQP7P.js.map +0 -1
  191. package/dist/list-datasets-KEXRLDEU.js.map +0 -1
  192. package/dist/list-evaluators-7R2LB4JH.js.map +0 -1
  193. package/dist/list-model-providers-OBYJCKBX.js.map +0 -1
  194. package/dist/list-prompt-tags-6LY3ZPYI.js.map +0 -1
  195. package/dist/list-prompts-VWEZ4CDE.js.map +0 -1
  196. package/dist/list-scenarios-TXD4W2ZJ.js.map +0 -1
  197. package/dist/list-simulation-runs-RHPOLMFI.js.map +0 -1
  198. package/dist/list-suites-FSGBX27Z.js.map +0 -1
  199. package/dist/list-workflows-VRGEZ3EN.js.map +0 -1
  200. package/dist/rename-prompt-tag-VOJJLX4M.js.map +0 -1
  201. package/dist/run-agent-KTCC7TB7.js.map +0 -1
  202. package/dist/run-evaluation-2X3V3Q6L.js +0 -64
  203. package/dist/run-evaluation-2X3V3Q6L.js.map +0 -1
  204. package/dist/run-suite-BTMHGI2D.js.map +0 -1
  205. package/dist/run-workflow-IGAYGKJL.js.map +0 -1
  206. package/dist/search-traces-VYFUIMXH.js.map +0 -1
  207. package/dist/set-model-provider-W5IUI326.js.map +0 -1
  208. package/dist/update-agent-4BB7EYLR.js.map +0 -1
  209. package/dist/update-dataset-CXBKZ4W3.js.map +0 -1
  210. package/dist/update-dataset-record-HOHAMHXG.js.map +0 -1
  211. package/dist/update-evaluator-IVOR6FTR.js.map +0 -1
  212. package/dist/update-prompt-OWQAKE7K.js.map +0 -1
  213. package/dist/update-scenario-GDFVILPN.js.map +0 -1
  214. package/dist/update-suite-BXYUYSPT.js.map +0 -1
  215. package/tests/evaluations.ipynb +0 -649
  216. package/tests/fixtures/azure/azure_openai_stream_bot_expected.py +0 -102
  217. package/tests/fixtures/azure/azure_openai_stream_bot_input.py +0 -78
  218. package/tests/fixtures/dspy/dspy_bot_expected.py +0 -61
  219. package/tests/fixtures/dspy/dspy_bot_input.py +0 -53
  220. package/tests/fixtures/fastapi/fastapi_app_expected.py +0 -68
  221. package/tests/fixtures/fastapi/fastapi_app_input.py +0 -60
  222. package/tests/fixtures/fastapi/prompt_management_fastapi_expected.py +0 -114
  223. package/tests/fixtures/fastapi/prompt_management_fastapi_input.py +0 -88
  224. package/tests/fixtures/haystack/haystack_bot_expected.py +0 -141
  225. package/tests/fixtures/haystack/haystack_bot_input.py +0 -69
  226. package/tests/fixtures/langchain/langchain_bot_expected.py +0 -53
  227. package/tests/fixtures/langchain/langchain_bot_input.py +0 -45
  228. package/tests/fixtures/langchain/langchain_bot_with_memory_expected.py +0 -69
  229. package/tests/fixtures/langchain/langchain_bot_with_memory_input.py +0 -61
  230. package/tests/fixtures/langchain/langchain_rag_bot_expected.py +0 -97
  231. package/tests/fixtures/langchain/langchain_rag_bot_input.py +0 -77
  232. package/tests/fixtures/langchain/langchain_rag_bot_vertex_ai_expected.py +0 -116
  233. package/tests/fixtures/langchain/langchain_rag_bot_vertex_ai_input.py +0 -81
  234. package/tests/fixtures/langchain/langgraph_rag_bot_with_threads_expected.py +0 -331
  235. package/tests/fixtures/langchain/langgraph_rag_bot_with_threads_input.py +0 -106
  236. package/tests/fixtures/litellm/litellm_bot_expected.py +0 -40
  237. package/tests/fixtures/litellm/litellm_bot_input.py +0 -35
  238. package/tests/fixtures/openai/openai_bot_expected.py +0 -43
  239. package/tests/fixtures/openai/openai_bot_function_call_expected.py +0 -91
  240. package/tests/fixtures/openai/openai_bot_function_call_input.py +0 -82
  241. package/tests/fixtures/openai/openai_bot_input.py +0 -36
  242. package/tests/fixtures/openai/openai_bot_rag_expected.py +0 -73
  243. package/tests/fixtures/openai/openai_bot_rag_input.py +0 -51
  244. package/tests/fixtures/opentelemetry/openinference_dspy_bot_expected.py +0 -63
  245. package/tests/fixtures/opentelemetry/openinference_dspy_bot_input.py +0 -58
  246. package/tests/fixtures/opentelemetry/openinference_langchain_bot_expected.py +0 -53
  247. package/tests/fixtures/opentelemetry/openinference_langchain_bot_input.py +0 -52
  248. package/tests/fixtures/opentelemetry/openinference_openai_bot_expected.py +0 -49
  249. package/tests/fixtures/opentelemetry/openinference_openai_bot_input.py +0 -41
  250. package/tests/fixtures/opentelemetry/openllmetry_openai_bot_expected.py +0 -44
  251. package/tests/fixtures/opentelemetry/openllmetry_openai_bot_input.py +0 -40
  252. package/tests/fixtures/strands/strands_bot_expected.py +0 -84
  253. package/tests/fixtures/strands/strands_bot_input.py +0 -52
  254. package/tests/scenario-openai.test.ts +0 -160
  255. package/tsup.config.ts +0 -14
  256. package/vitest.config.js +0 -7
package/dist/index.js CHANGED
@@ -15919,7 +15919,8 @@ function initConfig(args) {
15919
15919
  const state = getGlobalState();
15920
15920
  state.globalConfig = {
15921
15921
  apiKey: args.apiKey || process.env.LANGWATCH_API_KEY,
15922
- endpoint: args.endpoint || process.env.LANGWATCH_ENDPOINT || "https://app.langwatch.ai"
15922
+ endpoint: args.endpoint || process.env.LANGWATCH_ENDPOINT || "https://app.langwatch.ai",
15923
+ projectId: process.env.LANGWATCH_PROJECT_ID
15923
15924
  };
15924
15925
  }
15925
15926
  function getConfig() {
@@ -25821,12 +25822,15 @@ var require_data = __commonJS({
25821
25822
  }
25822
25823
  });
25823
25824
 
25824
- // node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/lib/utils.js
25825
+ // node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/lib/utils.js
25825
25826
  var require_utils = __commonJS({
25826
- "node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/lib/utils.js"(exports, module) {
25827
+ "node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/lib/utils.js"(exports, module) {
25827
25828
  "use strict";
25828
25829
  var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
25829
25830
  var isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
25831
+ var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
25832
+ var isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
25833
+ var isPathCharacter = RegExp.prototype.test.bind(/^[\da-z\-._~!$&'()*+,;=:@/]$/iu);
25830
25834
  function stringArrayToHexStripped(input) {
25831
25835
  let acc = "";
25832
25836
  let code = 0;
@@ -26019,27 +26023,77 @@ var require_utils = __commonJS({
26019
26023
  }
26020
26024
  return output.join("");
26021
26025
  }
26022
- function normalizeComponentEncoding(component, esc2) {
26023
- const func = esc2 !== true ? escape : unescape;
26024
- if (component.scheme !== void 0) {
26025
- component.scheme = func(component.scheme);
26026
- }
26027
- if (component.userinfo !== void 0) {
26028
- component.userinfo = func(component.userinfo);
26029
- }
26030
- if (component.host !== void 0) {
26031
- component.host = func(component.host);
26026
+ var HOST_DELIMS = { "@": "%40", "/": "%2F", "?": "%3F", "#": "%23", ":": "%3A" };
26027
+ var HOST_DELIM_RE = /[@/?#:]/g;
26028
+ var HOST_DELIM_NO_COLON_RE = /[@/?#]/g;
26029
+ function reescapeHostDelimiters(host, isIP) {
26030
+ const re = isIP ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE;
26031
+ re.lastIndex = 0;
26032
+ return host.replace(re, (ch) => HOST_DELIMS[ch]);
26033
+ }
26034
+ function normalizePercentEncoding(input, decodeUnreserved = false) {
26035
+ if (input.indexOf("%") === -1) {
26036
+ return input;
26032
26037
  }
26033
- if (component.path !== void 0) {
26034
- component.path = func(component.path);
26038
+ let output = "";
26039
+ for (let i = 0; i < input.length; i++) {
26040
+ if (input[i] === "%" && i + 2 < input.length) {
26041
+ const hex3 = input.slice(i + 1, i + 3);
26042
+ if (isHexPair(hex3)) {
26043
+ const normalizedHex = hex3.toUpperCase();
26044
+ const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
26045
+ if (decodeUnreserved && isUnreserved(decoded)) {
26046
+ output += decoded;
26047
+ } else {
26048
+ output += "%" + normalizedHex;
26049
+ }
26050
+ i += 2;
26051
+ continue;
26052
+ }
26053
+ }
26054
+ output += input[i];
26035
26055
  }
26036
- if (component.query !== void 0) {
26037
- component.query = func(component.query);
26056
+ return output;
26057
+ }
26058
+ function normalizePathEncoding(input) {
26059
+ let output = "";
26060
+ for (let i = 0; i < input.length; i++) {
26061
+ if (input[i] === "%" && i + 2 < input.length) {
26062
+ const hex3 = input.slice(i + 1, i + 3);
26063
+ if (isHexPair(hex3)) {
26064
+ const normalizedHex = hex3.toUpperCase();
26065
+ const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
26066
+ if (decoded !== "." && isUnreserved(decoded)) {
26067
+ output += decoded;
26068
+ } else {
26069
+ output += "%" + normalizedHex;
26070
+ }
26071
+ i += 2;
26072
+ continue;
26073
+ }
26074
+ }
26075
+ if (isPathCharacter(input[i])) {
26076
+ output += input[i];
26077
+ } else {
26078
+ output += escape(input[i]);
26079
+ }
26038
26080
  }
26039
- if (component.fragment !== void 0) {
26040
- component.fragment = func(component.fragment);
26081
+ return output;
26082
+ }
26083
+ function escapePreservingEscapes(input) {
26084
+ let output = "";
26085
+ for (let i = 0; i < input.length; i++) {
26086
+ if (input[i] === "%" && i + 2 < input.length) {
26087
+ const hex3 = input.slice(i + 1, i + 3);
26088
+ if (isHexPair(hex3)) {
26089
+ output += "%" + hex3.toUpperCase();
26090
+ i += 2;
26091
+ continue;
26092
+ }
26093
+ }
26094
+ output += escape(input[i]);
26041
26095
  }
26042
- return component;
26096
+ return output;
26043
26097
  }
26044
26098
  function recomposeAuthority(component) {
26045
26099
  const uriTokens = [];
@@ -26054,7 +26108,7 @@ var require_utils = __commonJS({
26054
26108
  if (ipV6res.isIPV6 === true) {
26055
26109
  host = `[${ipV6res.escapedHost}]`;
26056
26110
  } else {
26057
- host = component.host;
26111
+ host = reescapeHostDelimiters(host, false);
26058
26112
  }
26059
26113
  }
26060
26114
  uriTokens.push(host);
@@ -26068,7 +26122,10 @@ var require_utils = __commonJS({
26068
26122
  module.exports = {
26069
26123
  nonSimpleDomain,
26070
26124
  recomposeAuthority,
26071
- normalizeComponentEncoding,
26125
+ reescapeHostDelimiters,
26126
+ normalizePercentEncoding,
26127
+ normalizePathEncoding,
26128
+ escapePreservingEscapes,
26072
26129
  removeDotSegments,
26073
26130
  isIPv4,
26074
26131
  isUUID,
@@ -26078,9 +26135,9 @@ var require_utils = __commonJS({
26078
26135
  }
26079
26136
  });
26080
26137
 
26081
- // node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/lib/schemes.js
26138
+ // node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/lib/schemes.js
26082
26139
  var require_schemes = __commonJS({
26083
- "node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/lib/schemes.js"(exports, module) {
26140
+ "node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/lib/schemes.js"(exports, module) {
26084
26141
  "use strict";
26085
26142
  var { isUUID } = require_utils();
26086
26143
  var URN_REG = /([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-.:;=@]|%[\da-f]{2})+)/iu;
@@ -26288,16 +26345,16 @@ var require_schemes = __commonJS({
26288
26345
  }
26289
26346
  });
26290
26347
 
26291
- // node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/index.js
26348
+ // node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/index.js
26292
26349
  var require_fast_uri = __commonJS({
26293
- "node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/index.js"(exports, module) {
26350
+ "node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/index.js"(exports, module) {
26294
26351
  "use strict";
26295
- var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizeComponentEncoding, isIPv4, nonSimpleDomain } = require_utils();
26352
+ var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, escapePreservingEscapes, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
26296
26353
  var { SCHEMES, getSchemeHandler } = require_schemes();
26297
26354
  function normalize2(uri, options) {
26298
26355
  if (typeof uri === "string") {
26299
26356
  uri = /** @type {T} */
26300
- serialize(parse3(uri, options), options);
26357
+ normalizeString(uri, options);
26301
26358
  } else if (typeof uri === "object") {
26302
26359
  uri = /** @type {T} */
26303
26360
  parse3(serialize(uri, options), options);
@@ -26364,19 +26421,9 @@ var require_fast_uri = __commonJS({
26364
26421
  return target;
26365
26422
  }
26366
26423
  function equal(uriA, uriB, options) {
26367
- if (typeof uriA === "string") {
26368
- uriA = unescape(uriA);
26369
- uriA = serialize(normalizeComponentEncoding(parse3(uriA, options), true), { ...options, skipEscape: true });
26370
- } else if (typeof uriA === "object") {
26371
- uriA = serialize(normalizeComponentEncoding(uriA, true), { ...options, skipEscape: true });
26372
- }
26373
- if (typeof uriB === "string") {
26374
- uriB = unescape(uriB);
26375
- uriB = serialize(normalizeComponentEncoding(parse3(uriB, options), true), { ...options, skipEscape: true });
26376
- } else if (typeof uriB === "object") {
26377
- uriB = serialize(normalizeComponentEncoding(uriB, true), { ...options, skipEscape: true });
26378
- }
26379
- return uriA.toLowerCase() === uriB.toLowerCase();
26424
+ const normalizedA = normalizeComparableURI(uriA, options);
26425
+ const normalizedB = normalizeComparableURI(uriB, options);
26426
+ return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA.toLowerCase() === normalizedB.toLowerCase();
26380
26427
  }
26381
26428
  function serialize(cmpts, opts) {
26382
26429
  const component = {
@@ -26401,12 +26448,12 @@ var require_fast_uri = __commonJS({
26401
26448
  if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(component, options);
26402
26449
  if (component.path !== void 0) {
26403
26450
  if (!options.skipEscape) {
26404
- component.path = escape(component.path);
26451
+ component.path = escapePreservingEscapes(component.path);
26405
26452
  if (component.scheme !== void 0) {
26406
26453
  component.path = component.path.split("%3A").join(":");
26407
26454
  }
26408
26455
  } else {
26409
- component.path = unescape(component.path);
26456
+ component.path = normalizePercentEncoding(component.path);
26410
26457
  }
26411
26458
  }
26412
26459
  if (options.reference !== "suffix" && component.scheme) {
@@ -26441,7 +26488,16 @@ var require_fast_uri = __commonJS({
26441
26488
  return uriTokens.join("");
26442
26489
  }
26443
26490
  var URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
26444
- function parse3(uri, opts) {
26491
+ function getParseError(parsed, matches) {
26492
+ if (matches[2] !== void 0 && parsed.path && parsed.path[0] !== "/") {
26493
+ return 'URI path must start with "/" when authority is present.';
26494
+ }
26495
+ if (typeof parsed.port === "number" && (parsed.port < 0 || parsed.port > 65535)) {
26496
+ return "URI port is malformed.";
26497
+ }
26498
+ return void 0;
26499
+ }
26500
+ function parseWithStatus(uri, opts) {
26445
26501
  const options = Object.assign({}, opts);
26446
26502
  const parsed = {
26447
26503
  scheme: void 0,
@@ -26452,6 +26508,7 @@ var require_fast_uri = __commonJS({
26452
26508
  query: void 0,
26453
26509
  fragment: void 0
26454
26510
  };
26511
+ let malformedAuthorityOrPort = false;
26455
26512
  let isIP = false;
26456
26513
  if (options.reference === "suffix") {
26457
26514
  if (options.scheme) {
@@ -26472,6 +26529,11 @@ var require_fast_uri = __commonJS({
26472
26529
  if (isNaN(parsed.port)) {
26473
26530
  parsed.port = matches[5];
26474
26531
  }
26532
+ const parseError = getParseError(parsed, matches);
26533
+ if (parseError !== void 0) {
26534
+ parsed.error = parsed.error || parseError;
26535
+ malformedAuthorityOrPort = true;
26536
+ }
26475
26537
  if (parsed.host) {
26476
26538
  const ipv4result = isIPv4(parsed.host);
26477
26539
  if (ipv4result === false) {
@@ -26510,14 +26572,18 @@ var require_fast_uri = __commonJS({
26510
26572
  parsed.scheme = unescape(parsed.scheme);
26511
26573
  }
26512
26574
  if (parsed.host !== void 0) {
26513
- parsed.host = unescape(parsed.host);
26575
+ parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP);
26514
26576
  }
26515
26577
  }
26516
26578
  if (parsed.path) {
26517
- parsed.path = escape(unescape(parsed.path));
26579
+ parsed.path = normalizePathEncoding(parsed.path);
26518
26580
  }
26519
26581
  if (parsed.fragment) {
26520
- parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
26582
+ try {
26583
+ parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
26584
+ } catch {
26585
+ parsed.error = parsed.error || "URI malformed";
26586
+ }
26521
26587
  }
26522
26588
  }
26523
26589
  if (schemeHandler && schemeHandler.parse) {
@@ -26526,7 +26592,29 @@ var require_fast_uri = __commonJS({
26526
26592
  } else {
26527
26593
  parsed.error = parsed.error || "URI can not be parsed.";
26528
26594
  }
26529
- return parsed;
26595
+ return { parsed, malformedAuthorityOrPort };
26596
+ }
26597
+ function parse3(uri, opts) {
26598
+ return parseWithStatus(uri, opts).parsed;
26599
+ }
26600
+ function normalizeString(uri, opts) {
26601
+ return normalizeStringWithStatus(uri, opts).normalized;
26602
+ }
26603
+ function normalizeStringWithStatus(uri, opts) {
26604
+ const { parsed, malformedAuthorityOrPort } = parseWithStatus(uri, opts);
26605
+ return {
26606
+ normalized: malformedAuthorityOrPort ? uri : serialize(parsed, opts),
26607
+ malformedAuthorityOrPort
26608
+ };
26609
+ }
26610
+ function normalizeComparableURI(uri, opts) {
26611
+ if (typeof uri === "string") {
26612
+ const { normalized, malformedAuthorityOrPort } = normalizeStringWithStatus(uri, opts);
26613
+ return malformedAuthorityOrPort ? void 0 : normalized;
26614
+ }
26615
+ if (typeof uri === "object") {
26616
+ return serialize(uri, opts);
26617
+ }
26530
26618
  }
26531
26619
  var fastUri = {
26532
26620
  SCHEMES,
@@ -31021,7 +31109,7 @@ var init_package = __esm({
31021
31109
  "package.json"() {
31022
31110
  package_default = {
31023
31111
  name: "@langwatch/mcp-server",
31024
- version: "0.7.0",
31112
+ version: "0.9.0",
31025
31113
  description: "An MCP server for Langwatch.",
31026
31114
  type: "module",
31027
31115
  main: "./dist/index.js",
@@ -31063,19 +31151,19 @@ var init_package = __esm({
31063
31151
  },
31064
31152
  devDependencies: {
31065
31153
  "@ai-sdk/anthropic": "^3.0.44",
31066
- "@anthropic-ai/claude-code": "^2.1.72",
31067
- "@eslint/js": "^9.4.0",
31154
+ "@anthropic-ai/claude-code": "^2.1.119",
31155
+ "@eslint/js": "^10.0.1",
31068
31156
  "@langwatch/scenario": "^0.4.6",
31069
31157
  "@types/debug": "^4.1.12",
31070
31158
  "@types/eslint__js": "^8.42.3",
31071
31159
  "@types/express": "^5.0.6",
31072
- "@types/node": "^16.0.0",
31160
+ "@types/node": "^25.6.0",
31073
31161
  "@types/yargs": "^17.0.33",
31074
31162
  "@typescript/native-preview": "7.0.0-dev.20250911.1",
31075
- ai: "^6.0.0",
31163
+ ai: "^6.0.161",
31076
31164
  dotenv: "^17.2.2",
31077
31165
  esbuild: "^0.25.0",
31078
- eslint: "^8.57.0",
31166
+ eslint: "^10.2.1",
31079
31167
  tsup: "^8.1.0",
31080
31168
  tsx: "^4.20.5",
31081
31169
  typescript: "^5.0.0",
@@ -31084,7 +31172,7 @@ var init_package = __esm({
31084
31172
  dependencies: {
31085
31173
  "@modelcontextprotocol/sdk": "^1.26.0",
31086
31174
  "@opentelemetry/context-async-hooks": "^2.1.0",
31087
- "@opentelemetry/sdk-node": "^0.204.0",
31175
+ "@opentelemetry/sdk-node": "^0.217.0",
31088
31176
  chalk: "^5.6.2",
31089
31177
  "date-fns": "^4.1.0",
31090
31178
  express: "^5.2.1",
@@ -31096,6 +31184,13 @@ var init_package = __esm({
31096
31184
  },
31097
31185
  bin: {
31098
31186
  "langwatch-mcp-server": "./dist/index.js"
31187
+ },
31188
+ pnpm: {
31189
+ overrides: {
31190
+ protobufjs: ">=7.5.6 <8.0.0 || >=8.0.2",
31191
+ "langsmith@<0.6.0": "0.6.0",
31192
+ "fast-uri@<3.1.2": "3.1.2"
31193
+ }
31099
31194
  }
31100
31195
  };
31101
31196
  }
@@ -31133,6 +31228,533 @@ var init_create_dataset = __esm({
31133
31228
  }
31134
31229
  });
31135
31230
 
31231
+ // src/langwatch-api.ts
31232
+ async function makeRequest(method, path, body) {
31233
+ const config2 = getConfig();
31234
+ const url2 = config2.endpoint + path;
31235
+ const headers = {
31236
+ "X-Auth-Token": requireApiKey()
31237
+ };
31238
+ if (config2.projectId) {
31239
+ headers["X-Project-Id"] = config2.projectId;
31240
+ }
31241
+ if (body !== void 0) {
31242
+ headers["Content-Type"] = "application/json";
31243
+ }
31244
+ const response = await fetch(url2, {
31245
+ method,
31246
+ headers,
31247
+ ...body !== void 0 ? { body: JSON.stringify(body) } : {}
31248
+ });
31249
+ if (!response.ok) {
31250
+ const responseBody = await response.text();
31251
+ throw new LangWatchApiError(
31252
+ `LangWatch API error ${response.status}: ${responseBody}`,
31253
+ response.status,
31254
+ responseBody
31255
+ );
31256
+ }
31257
+ if (response.status === 204 || response.headers?.get("content-length") === "0") {
31258
+ return null;
31259
+ }
31260
+ return response.json();
31261
+ }
31262
+ async function searchTraces(params) {
31263
+ const { format: format3 = "digest", ...rest } = params;
31264
+ return makeRequest("POST", "/api/traces/search", {
31265
+ ...rest,
31266
+ format: format3
31267
+ });
31268
+ }
31269
+ async function getTraceById(traceId, format3 = "digest") {
31270
+ return makeRequest(
31271
+ "GET",
31272
+ `/api/traces/${encodeURIComponent(traceId)}?format=${format3}`
31273
+ );
31274
+ }
31275
+ async function getAnalyticsTimeseries(params) {
31276
+ return makeRequest(
31277
+ "POST",
31278
+ "/api/analytics/timeseries",
31279
+ params
31280
+ );
31281
+ }
31282
+ async function listPrompts() {
31283
+ return makeRequest("GET", "/api/prompts");
31284
+ }
31285
+ async function getPrompt(idOrHandle, options) {
31286
+ const params = new URLSearchParams();
31287
+ if (options?.version != null) params.set("version", String(options.version));
31288
+ if (options?.tag) params.set("tag", options.tag);
31289
+ const query = params.toString() ? `?${params}` : "";
31290
+ return makeRequest(
31291
+ "GET",
31292
+ `/api/prompts/${encodeURIComponent(idOrHandle)}${query}`
31293
+ );
31294
+ }
31295
+ async function createPrompt(data) {
31296
+ return makeRequest(
31297
+ "POST",
31298
+ "/api/prompts",
31299
+ data
31300
+ );
31301
+ }
31302
+ async function updatePrompt(idOrHandle, data) {
31303
+ return makeRequest(
31304
+ "PUT",
31305
+ `/api/prompts/${encodeURIComponent(idOrHandle)}`,
31306
+ data
31307
+ );
31308
+ }
31309
+ async function assignPromptTag({
31310
+ idOrHandle,
31311
+ tag,
31312
+ versionId
31313
+ }) {
31314
+ return makeRequest(
31315
+ "PUT",
31316
+ `/api/prompts/${encodeURIComponent(idOrHandle)}/tags/${encodeURIComponent(tag)}`,
31317
+ { versionId }
31318
+ );
31319
+ }
31320
+ async function listPromptTags() {
31321
+ return makeRequest("GET", "/api/prompts/tags");
31322
+ }
31323
+ async function createPromptTag(name) {
31324
+ return makeRequest("POST", "/api/prompts/tags", { name });
31325
+ }
31326
+ async function renamePromptTag({
31327
+ tag,
31328
+ name
31329
+ }) {
31330
+ return makeRequest(
31331
+ "PUT",
31332
+ `/api/prompts/tags/${encodeURIComponent(tag)}`,
31333
+ { name }
31334
+ );
31335
+ }
31336
+ async function deletePromptTag(tag) {
31337
+ return makeRequest(
31338
+ "DELETE",
31339
+ `/api/prompts/tags/${encodeURIComponent(tag)}`
31340
+ );
31341
+ }
31342
+ var LangWatchApiError;
31343
+ var init_langwatch_api = __esm({
31344
+ "src/langwatch-api.ts"() {
31345
+ "use strict";
31346
+ init_config();
31347
+ LangWatchApiError = class extends Error {
31348
+ constructor(message, status, responseBody) {
31349
+ super(message);
31350
+ this.status = status;
31351
+ this.responseBody = responseBody;
31352
+ this.name = "LangWatchApiError";
31353
+ }
31354
+ };
31355
+ }
31356
+ });
31357
+
31358
+ // src/tools/get-experiment-results.ts
31359
+ async function handleExperimentResults(params) {
31360
+ const filter = params.filter ?? "all";
31361
+ const evaluatorFilter = params.evaluator?.trim();
31362
+ const limit = typeof params.limit === "number" && params.limit > 0 ? Math.min(params.limit, DEFAULT_ROW_CAP) : DEFAULT_ROW_CAP;
31363
+ const search = new URLSearchParams();
31364
+ if (params.experimentSlug) search.set("experimentSlug", params.experimentSlug);
31365
+ const qs = search.toString() ? `?${search.toString()}` : "";
31366
+ let results;
31367
+ try {
31368
+ results = await makeRequest(
31369
+ "GET",
31370
+ `/api/experiments/runs/${encodeURIComponent(params.runId)}/results${qs}`
31371
+ );
31372
+ } catch (error48) {
31373
+ const message = error48 instanceof Error ? error48.message : String(error48);
31374
+ const status = error48 instanceof LangWatchApiError ? error48.status : error48 && typeof error48 === "object" && "status" in error48 && typeof error48.status === "number" ? error48.status : void 0;
31375
+ if (status === 404 || status === void 0 && /404|not found/i.test(message)) {
31376
+ return [
31377
+ `# Evaluation Results: ${params.runId}`,
31378
+ "",
31379
+ "**Status**: not found",
31380
+ "",
31381
+ `Could not load results for run \`${params.runId}\`. The run may still be in progress, or the id may be incorrect.`,
31382
+ "",
31383
+ "> Try `platform_experiment_status` first to confirm the run id and that it is completed."
31384
+ ].join("\n");
31385
+ }
31386
+ throw error48;
31387
+ }
31388
+ if (!results || results.timestamps.finishedAt == null && results.timestamps.stoppedAt == null) {
31389
+ return [
31390
+ `# Evaluation Results: ${params.runId}`,
31391
+ "",
31392
+ "**Status**: results are not yet available",
31393
+ "",
31394
+ `Results for run \`${params.runId}\` are not ready yet.`,
31395
+ "",
31396
+ "> Try `platform_experiment_status` first to confirm the run id and that it is completed."
31397
+ ].join("\n");
31398
+ }
31399
+ const evaluationsByRow = /* @__PURE__ */ new Map();
31400
+ for (const evaluation of results.evaluations) {
31401
+ if (evaluatorFilter && evaluation.evaluator !== evaluatorFilter) continue;
31402
+ const key = rowKey(evaluation.index, evaluation.targetId);
31403
+ const list = evaluationsByRow.get(key) ?? [];
31404
+ list.push(evaluation);
31405
+ evaluationsByRow.set(key, list);
31406
+ }
31407
+ const evaluatorNames = Array.from(
31408
+ new Set(
31409
+ (evaluatorFilter ? results.evaluations.filter((e) => e.evaluator === evaluatorFilter) : results.evaluations).map((e) => e.evaluator)
31410
+ )
31411
+ );
31412
+ let rows = results.dataset.map((entry) => ({
31413
+ entry,
31414
+ evaluations: evaluationsByRow.get(rowKey(entry.index, entry.targetId)) ?? []
31415
+ }));
31416
+ if (filter === "failed") {
31417
+ rows = rows.filter(
31418
+ (r) => isFailedRow({ entry: r.entry, evaluations: r.evaluations })
31419
+ );
31420
+ }
31421
+ const totalMatching = rows.length;
31422
+ const rowsForSummary = rows;
31423
+ const truncated = rows.length > limit;
31424
+ rows = rows.slice(0, limit);
31425
+ const evaluatorAverages = /* @__PURE__ */ new Map();
31426
+ for (const r of rowsForSummary) {
31427
+ for (const e of r.evaluations) {
31428
+ const stats = evaluatorAverages.get(e.evaluator) ?? {
31429
+ sum: 0,
31430
+ count: 0,
31431
+ passed: 0,
31432
+ failed: 0,
31433
+ errored: 0
31434
+ };
31435
+ if (typeof e.score === "number") {
31436
+ stats.sum += e.score;
31437
+ stats.count += 1;
31438
+ }
31439
+ if (e.status === "error") stats.errored += 1;
31440
+ else if (e.passed === true) stats.passed += 1;
31441
+ else if (e.passed === false) stats.failed += 1;
31442
+ evaluatorAverages.set(e.evaluator, stats);
31443
+ }
31444
+ }
31445
+ const lines = [];
31446
+ lines.push(`# Evaluation Results: ${results.runId}`);
31447
+ lines.push("");
31448
+ lines.push(`**Experiment**: ${results.experimentId}`);
31449
+ lines.push(`**Total rows**: ${results.dataset.length}`);
31450
+ lines.push(`**Total evaluations**: ${results.evaluations.length}`);
31451
+ if (filter === "failed") {
31452
+ lines.push(`**Filter**: failed only`);
31453
+ }
31454
+ if (evaluatorFilter) {
31455
+ lines.push(`**Evaluator filter**: ${evaluatorFilter}`);
31456
+ }
31457
+ lines.push("");
31458
+ if (evaluatorAverages.size > 0) {
31459
+ lines.push("## Evaluator Summary");
31460
+ lines.push("");
31461
+ lines.push("| Evaluator | Avg Score | Passed | Failed | Errored |");
31462
+ lines.push("| --- | --- | --- | --- | --- |");
31463
+ for (const [name, stats] of evaluatorAverages) {
31464
+ const avg = stats.count > 0 ? (stats.sum / stats.count).toFixed(3) : "\u2014";
31465
+ lines.push(
31466
+ `| ${name} | ${avg} | ${stats.passed} | ${stats.failed} | ${stats.errored} |`
31467
+ );
31468
+ }
31469
+ lines.push("");
31470
+ }
31471
+ if (rows.length === 0) {
31472
+ lines.push("_No rows matched the filter._");
31473
+ return lines.join("\n");
31474
+ }
31475
+ lines.push(
31476
+ `## Rows (${rows.length}${truncated ? ` of ${totalMatching}` : ""})`
31477
+ );
31478
+ lines.push("");
31479
+ for (const { entry, evaluations } of rows) {
31480
+ const summary = summarizeEntry(entry.entry);
31481
+ lines.push(`### Row #${entry.index}${summary ? ` \u2014 ${summary}` : ""}`);
31482
+ if (entry.error) {
31483
+ lines.push(`- **Error**: ${entry.error}`);
31484
+ }
31485
+ if (entry.traceId) {
31486
+ lines.push(`- **Trace ID**: \`${entry.traceId}\``);
31487
+ }
31488
+ if (evaluations.length === 0) {
31489
+ lines.push(
31490
+ evaluatorNames.length === 0 ? "- _No evaluations recorded_" : "- _No evaluations recorded for this row_"
31491
+ );
31492
+ }
31493
+ for (const e of evaluations) {
31494
+ const parts = [`**${e.evaluator}**`];
31495
+ if (e.status === "error") parts.push("status=error");
31496
+ else if (typeof e.score === "number") parts.push(`score=${e.score.toFixed(3)}`);
31497
+ if (typeof e.passed === "boolean") {
31498
+ parts.push(`passed=${e.passed ? "yes" : "no"}`);
31499
+ }
31500
+ if (e.label) parts.push(`label=${e.label}`);
31501
+ lines.push(`- ${parts.join(" \xB7 ")}`);
31502
+ if (e.details) {
31503
+ lines.push(` - details: ${e.details}`);
31504
+ }
31505
+ }
31506
+ lines.push("");
31507
+ }
31508
+ if (truncated) {
31509
+ lines.push(
31510
+ `> Output truncated to ${limit} rows of ${totalMatching} matching to protect the agent's context window. Pass \`limit\` to expand or filter further.`
31511
+ );
31512
+ }
31513
+ return lines.join("\n");
31514
+ }
31515
+ var DEFAULT_ROW_CAP, rowKey, summarizeEntry, isFailedEvaluation, isFailedRow;
31516
+ var init_get_experiment_results = __esm({
31517
+ "src/tools/get-experiment-results.ts"() {
31518
+ "use strict";
31519
+ init_langwatch_api();
31520
+ DEFAULT_ROW_CAP = 50;
31521
+ rowKey = (index, targetId) => `${index}:${targetId ?? ""}`;
31522
+ summarizeEntry = (entry) => {
31523
+ const candidates = ["input", "question", "query", "prompt", "user"];
31524
+ for (const key of candidates) {
31525
+ const value = entry[key];
31526
+ if (typeof value === "string" && value.length > 0) {
31527
+ return value.length > 80 ? `${value.slice(0, 77)}...` : value;
31528
+ }
31529
+ }
31530
+ return "";
31531
+ };
31532
+ isFailedEvaluation = (e) => e.status === "error" || e.passed === false;
31533
+ isFailedRow = ({
31534
+ entry,
31535
+ evaluations
31536
+ }) => Boolean(entry.error) || evaluations.some(isFailedEvaluation);
31537
+ }
31538
+ });
31539
+
31540
+ // src/tools/list-experiment-runs.ts
31541
+ async function handleExperimentListRuns(params) {
31542
+ const requested = typeof params.limit === "number" && params.limit > 0 ? params.limit : DEFAULT_LIMIT;
31543
+ const effectiveLimit = Math.min(requested, MAX_LIMIT);
31544
+ const search = new URLSearchParams();
31545
+ search.set("experimentSlug", params.experimentSlug);
31546
+ search.set("pageSize", String(effectiveLimit));
31547
+ let result;
31548
+ try {
31549
+ result = await makeRequest(
31550
+ "GET",
31551
+ `/api/experiments/runs?${search.toString()}`
31552
+ );
31553
+ } catch (error48) {
31554
+ const message = error48 instanceof Error ? error48.message : String(error48);
31555
+ if (/404|not found/i.test(message)) {
31556
+ return [
31557
+ `# Evaluation Runs: ${params.experimentSlug}`,
31558
+ "",
31559
+ "**Status**: experiment not found",
31560
+ "",
31561
+ `No experiment with slug \`${params.experimentSlug}\` exists in this project.`,
31562
+ "",
31563
+ "> Run `platform_experiment_list` to discover available experiment slugs."
31564
+ ].join("\n");
31565
+ }
31566
+ throw error48;
31567
+ }
31568
+ if (result.runs.length === 0) {
31569
+ return [
31570
+ `# Evaluation Runs: ${result.experimentSlug}`,
31571
+ "",
31572
+ "_This experiment has no runs yet._",
31573
+ "",
31574
+ `> Trigger a run with \`platform_run_experiment\` (slug: \`${result.experimentSlug}\`) to populate this list.`
31575
+ ].join("\n");
31576
+ }
31577
+ const lines = [];
31578
+ lines.push(`# Evaluation Runs: ${result.experimentSlug}`);
31579
+ lines.push("");
31580
+ lines.push(
31581
+ `Showing ${result.runs.length} of ${result.pagination.totalHits} run${result.pagination.totalHits === 1 ? "" : "s"}.`
31582
+ );
31583
+ if (result.pagination.hasMore) {
31584
+ lines.push(
31585
+ `> More runs exist beyond this limit. Re-run with a higher \`limit\` (max ${MAX_LIMIT}) if needed.`
31586
+ );
31587
+ }
31588
+ lines.push("");
31589
+ lines.push("| Run ID | Status | Started | Finished | Result |");
31590
+ lines.push("|--------|--------|---------|----------|--------|");
31591
+ for (const run of result.runs) {
31592
+ lines.push(
31593
+ `| \`${run.runId}\` | ${runStatus(run)} | ${formatEpoch(run.timestamps.createdAt)} | ${formatEpoch(run.timestamps.finishedAt ?? null)} | ${passRate(run.summary?.evaluations ?? {})} |`
31594
+ );
31595
+ }
31596
+ lines.push("");
31597
+ lines.push(
31598
+ "> Use `platform_experiment_status <runId>` for live progress, or `platform_experiment_results <runId>` for per-row results."
31599
+ );
31600
+ return lines.join("\n");
31601
+ }
31602
+ var DEFAULT_LIMIT, MAX_LIMIT, formatEpoch, passRate, runStatus;
31603
+ var init_list_experiment_runs = __esm({
31604
+ "src/tools/list-experiment-runs.ts"() {
31605
+ "use strict";
31606
+ init_langwatch_api();
31607
+ DEFAULT_LIMIT = 25;
31608
+ MAX_LIMIT = 100;
31609
+ formatEpoch = (epoch) => {
31610
+ if (!epoch || !Number.isFinite(epoch)) return "\u2014";
31611
+ return new Date(epoch).toISOString().replace("T", " ").slice(0, 19) + " UTC";
31612
+ };
31613
+ passRate = (evaluations) => {
31614
+ const entries = Object.values(evaluations ?? {});
31615
+ if (entries.length === 0) return "\u2014";
31616
+ const passed = entries.filter((e) => typeof e.averagePassed === "number");
31617
+ if (passed.length === 0) {
31618
+ const scored = entries.filter((e) => typeof e.averageScore === "number");
31619
+ if (scored.length === 0) return "\u2014";
31620
+ const avg2 = scored.reduce((sum, e) => sum + (e.averageScore ?? 0), 0) / scored.length;
31621
+ return `${avg2.toFixed(2)} avg`;
31622
+ }
31623
+ const avg = passed.reduce((sum, e) => sum + (e.averagePassed ?? 0), 0) / passed.length;
31624
+ return `${(avg * 100).toFixed(0)}% pass`;
31625
+ };
31626
+ runStatus = (run) => {
31627
+ if (run.timestamps.stoppedAt) return "stopped";
31628
+ if (run.timestamps.finishedAt) return "completed";
31629
+ return "running";
31630
+ };
31631
+ }
31632
+ });
31633
+
31634
+ // src/tools/list-experiments.ts
31635
+ async function handleExperimentList(params) {
31636
+ const requested = typeof params.limit === "number" && params.limit > 0 ? params.limit : DEFAULT_LIMIT2;
31637
+ const effectiveLimit = Math.min(requested, MAX_LIMIT2);
31638
+ const search = new URLSearchParams();
31639
+ search.set("pageSize", String(effectiveLimit));
31640
+ const result = await makeRequest(
31641
+ "GET",
31642
+ `/api/experiments?${search.toString()}`
31643
+ );
31644
+ if (result.experiments.length === 0) {
31645
+ return [
31646
+ "# Experiments",
31647
+ "",
31648
+ "_No experiments found in this project._",
31649
+ "",
31650
+ "> Create an experiment in the LangWatch dashboard, then re-run this tool to discover its slug."
31651
+ ].join("\n");
31652
+ }
31653
+ const lines = [];
31654
+ lines.push("# Experiments");
31655
+ lines.push("");
31656
+ lines.push(
31657
+ `Showing ${result.experiments.length} of ${result.pagination.totalHits} experiment${result.pagination.totalHits === 1 ? "" : "s"}.`
31658
+ );
31659
+ if (result.pagination.hasMore) {
31660
+ lines.push(
31661
+ `> More experiments exist beyond this limit. Re-run with a higher \`limit\` (max ${MAX_LIMIT2}) if needed.`
31662
+ );
31663
+ }
31664
+ lines.push("");
31665
+ lines.push("| Slug | Name | Runs | Last Run |");
31666
+ lines.push("|------|------|------|----------|");
31667
+ for (const exp of result.experiments) {
31668
+ const name = escapeMarkdownTableCell(exp.name ?? exp.slug);
31669
+ lines.push(
31670
+ `| ${formatInlineCode(exp.slug)} | ${name} | ${exp.runsCount} | ${formatTimestamp(exp.lastRunAt)} |`
31671
+ );
31672
+ }
31673
+ lines.push("");
31674
+ lines.push(
31675
+ "> Use `platform_experiment_list_runs` with one of these slugs to see its runs."
31676
+ );
31677
+ return lines.join("\n");
31678
+ }
31679
+ var DEFAULT_LIMIT2, MAX_LIMIT2, formatTimestamp, escapeMarkdownTableCell, formatInlineCode;
31680
+ var init_list_experiments = __esm({
31681
+ "src/tools/list-experiments.ts"() {
31682
+ "use strict";
31683
+ init_langwatch_api();
31684
+ DEFAULT_LIMIT2 = 25;
31685
+ MAX_LIMIT2 = 100;
31686
+ formatTimestamp = (iso) => {
31687
+ if (!iso) return "\u2014";
31688
+ const d = new Date(iso);
31689
+ if (Number.isNaN(d.getTime())) return iso;
31690
+ return d.toISOString().replace("T", " ").slice(0, 19) + " UTC";
31691
+ };
31692
+ escapeMarkdownTableCell = (value) => value.replace(/[\\|]/g, (c) => `\\${c}`).replace(/\n/g, " ");
31693
+ formatInlineCode = (value) => `\`${value.replace(/[\\`|]/g, (c) => `\\${c}`).replace(/\n/g, " ")}\``;
31694
+ }
31695
+ });
31696
+
31697
+ // src/tools/run-experiment.ts
31698
+ async function handleRunExperiment(params) {
31699
+ const result = await makeRequest(
31700
+ "POST",
31701
+ `/api/experiments/${encodeURIComponent(params.slug)}/run`
31702
+ );
31703
+ const lines = [];
31704
+ lines.push(`Evaluation started!
31705
+ `);
31706
+ lines.push(`**Run ID**: ${result.runId}`);
31707
+ lines.push(`**Status**: ${result.status}`);
31708
+ lines.push(`**Total cells**: ${result.total}`);
31709
+ if (result.runUrl) lines.push(`**View at**: ${result.runUrl}`);
31710
+ lines.push("");
31711
+ lines.push(
31712
+ `> Use \`platform_experiment_status\` with run ID "${result.runId}" to check progress.`
31713
+ );
31714
+ return lines.join("\n");
31715
+ }
31716
+ async function handleExperimentStatus(params) {
31717
+ const status = await makeRequest(
31718
+ "GET",
31719
+ `/api/experiments/runs/${encodeURIComponent(params.runId)}`
31720
+ );
31721
+ const lines = [];
31722
+ lines.push(`# Evaluation Run ${status.runId}
31723
+ `);
31724
+ lines.push(`**Status**: ${status.status}`);
31725
+ lines.push(`**Progress**: ${status.progress}/${status.total} cells`);
31726
+ if (status.startedAt) {
31727
+ lines.push(`**Started**: ${new Date(status.startedAt).toISOString()}`);
31728
+ }
31729
+ if (status.finishedAt) {
31730
+ lines.push(`**Finished**: ${new Date(status.finishedAt).toISOString()}`);
31731
+ }
31732
+ if (status.summary) {
31733
+ lines.push("\n## Summary\n");
31734
+ if (status.summary.completedCells !== void 0) {
31735
+ lines.push(`**Completed**: ${status.summary.completedCells}`);
31736
+ }
31737
+ if (status.summary.failedCells) {
31738
+ lines.push(`**Failed**: ${status.summary.failedCells}`);
31739
+ }
31740
+ if (status.summary.duration) {
31741
+ lines.push(
31742
+ `**Duration**: ${(status.summary.duration / 1e3).toFixed(1)}s`
31743
+ );
31744
+ }
31745
+ if (status.summary.runUrl) {
31746
+ lines.push(`**View results**: ${status.summary.runUrl}`);
31747
+ }
31748
+ }
31749
+ return lines.join("\n");
31750
+ }
31751
+ var init_run_experiment = __esm({
31752
+ "src/tools/run-experiment.ts"() {
31753
+ "use strict";
31754
+ init_langwatch_api();
31755
+ }
31756
+ });
31757
+
31136
31758
  // src/tools/discover-scenario-schema.ts
31137
31759
  var discover_scenario_schema_exports = {};
31138
31760
  __export(discover_scenario_schema_exports, {
@@ -33091,118 +33713,6 @@ var init_discover_schema = __esm({
33091
33713
  }
33092
33714
  });
33093
33715
 
33094
- // src/langwatch-api.ts
33095
- async function makeRequest(method, path, body) {
33096
- const url2 = getConfig().endpoint + path;
33097
- const headers = {
33098
- "X-Auth-Token": requireApiKey()
33099
- };
33100
- if (body !== void 0) {
33101
- headers["Content-Type"] = "application/json";
33102
- }
33103
- const response = await fetch(url2, {
33104
- method,
33105
- headers,
33106
- ...body !== void 0 ? { body: JSON.stringify(body) } : {}
33107
- });
33108
- if (!response.ok) {
33109
- const responseBody = await response.text();
33110
- throw new Error(
33111
- `LangWatch API error ${response.status}: ${responseBody}`
33112
- );
33113
- }
33114
- if (response.status === 204 || response.headers?.get("content-length") === "0") {
33115
- return null;
33116
- }
33117
- return response.json();
33118
- }
33119
- async function searchTraces(params) {
33120
- const { format: format3 = "digest", ...rest } = params;
33121
- return makeRequest("POST", "/api/traces/search", {
33122
- ...rest,
33123
- format: format3
33124
- });
33125
- }
33126
- async function getTraceById(traceId, format3 = "digest") {
33127
- return makeRequest(
33128
- "GET",
33129
- `/api/traces/${encodeURIComponent(traceId)}?format=${format3}`
33130
- );
33131
- }
33132
- async function getAnalyticsTimeseries(params) {
33133
- return makeRequest(
33134
- "POST",
33135
- "/api/analytics/timeseries",
33136
- params
33137
- );
33138
- }
33139
- async function listPrompts() {
33140
- return makeRequest("GET", "/api/prompts");
33141
- }
33142
- async function getPrompt(idOrHandle, options) {
33143
- const params = new URLSearchParams();
33144
- if (options?.version != null) params.set("version", String(options.version));
33145
- if (options?.tag) params.set("tag", options.tag);
33146
- const query = params.toString() ? `?${params}` : "";
33147
- return makeRequest(
33148
- "GET",
33149
- `/api/prompts/${encodeURIComponent(idOrHandle)}${query}`
33150
- );
33151
- }
33152
- async function createPrompt(data) {
33153
- return makeRequest(
33154
- "POST",
33155
- "/api/prompts",
33156
- data
33157
- );
33158
- }
33159
- async function updatePrompt(idOrHandle, data) {
33160
- return makeRequest(
33161
- "PUT",
33162
- `/api/prompts/${encodeURIComponent(idOrHandle)}`,
33163
- data
33164
- );
33165
- }
33166
- async function assignPromptTag({
33167
- idOrHandle,
33168
- tag,
33169
- versionId
33170
- }) {
33171
- return makeRequest(
33172
- "PUT",
33173
- `/api/prompts/${encodeURIComponent(idOrHandle)}/tags/${encodeURIComponent(tag)}`,
33174
- { versionId }
33175
- );
33176
- }
33177
- async function listPromptTags() {
33178
- return makeRequest("GET", "/api/prompts/tags");
33179
- }
33180
- async function createPromptTag(name) {
33181
- return makeRequest("POST", "/api/prompts/tags", { name });
33182
- }
33183
- async function renamePromptTag({
33184
- tag,
33185
- name
33186
- }) {
33187
- return makeRequest(
33188
- "PUT",
33189
- `/api/prompts/tags/${encodeURIComponent(tag)}`,
33190
- { name }
33191
- );
33192
- }
33193
- async function deletePromptTag(tag) {
33194
- return makeRequest(
33195
- "DELETE",
33196
- `/api/prompts/tags/${encodeURIComponent(tag)}`
33197
- );
33198
- }
33199
- var init_langwatch_api = __esm({
33200
- "src/langwatch-api.ts"() {
33201
- "use strict";
33202
- init_config();
33203
- }
33204
- });
33205
-
33206
33716
  // src/utils/date-parsing.ts
33207
33717
  function parseRelativeDate(input) {
33208
33718
  if (input === "now") return Date.now();
@@ -35287,72 +35797,6 @@ var init_langwatch_api_secrets = __esm({
35287
35797
  }
35288
35798
  });
35289
35799
 
35290
- // src/tools/run-evaluation.ts
35291
- var run_evaluation_exports = {};
35292
- __export(run_evaluation_exports, {
35293
- handleEvaluationStatus: () => handleEvaluationStatus,
35294
- handleRunEvaluation: () => handleRunEvaluation
35295
- });
35296
- async function handleRunEvaluation(params) {
35297
- const result = await makeRequest(
35298
- "POST",
35299
- `/api/evaluations/v3/${encodeURIComponent(params.slug)}/run`
35300
- );
35301
- const lines = [];
35302
- lines.push(`Evaluation started!
35303
- `);
35304
- lines.push(`**Run ID**: ${result.runId}`);
35305
- lines.push(`**Status**: ${result.status}`);
35306
- lines.push(`**Total cells**: ${result.total}`);
35307
- if (result.runUrl) lines.push(`**View at**: ${result.runUrl}`);
35308
- lines.push("");
35309
- lines.push(
35310
- `> Use \`platform_evaluation_status\` with run ID "${result.runId}" to check progress.`
35311
- );
35312
- return lines.join("\n");
35313
- }
35314
- async function handleEvaluationStatus(params) {
35315
- const status = await makeRequest(
35316
- "GET",
35317
- `/api/evaluations/v3/runs/${encodeURIComponent(params.runId)}`
35318
- );
35319
- const lines = [];
35320
- lines.push(`# Evaluation Run ${status.runId}
35321
- `);
35322
- lines.push(`**Status**: ${status.status}`);
35323
- lines.push(`**Progress**: ${status.progress}/${status.total} cells`);
35324
- if (status.startedAt) {
35325
- lines.push(`**Started**: ${new Date(status.startedAt).toISOString()}`);
35326
- }
35327
- if (status.finishedAt) {
35328
- lines.push(`**Finished**: ${new Date(status.finishedAt).toISOString()}`);
35329
- }
35330
- if (status.summary) {
35331
- lines.push("\n## Summary\n");
35332
- if (status.summary.completedCells !== void 0) {
35333
- lines.push(`**Completed**: ${status.summary.completedCells}`);
35334
- }
35335
- if (status.summary.failedCells) {
35336
- lines.push(`**Failed**: ${status.summary.failedCells}`);
35337
- }
35338
- if (status.summary.duration) {
35339
- lines.push(
35340
- `**Duration**: ${(status.summary.duration / 1e3).toFixed(1)}s`
35341
- );
35342
- }
35343
- if (status.summary.runUrl) {
35344
- lines.push(`**View results**: ${status.summary.runUrl}`);
35345
- }
35346
- }
35347
- return lines.join("\n");
35348
- }
35349
- var init_run_evaluation = __esm({
35350
- "src/tools/run-evaluation.ts"() {
35351
- "use strict";
35352
- init_langwatch_api();
35353
- }
35354
- });
35355
-
35356
35800
  // src/langwatch-api-datasets.ts
35357
35801
  async function listDatasets(params) {
35358
35802
  const query = new URLSearchParams();
@@ -35728,6 +36172,305 @@ var init_delete_dataset_records = __esm({
35728
36172
  }
35729
36173
  });
35730
36174
 
36175
+ // src/langwatch-api-projects.ts
36176
+ async function listProjects(params) {
36177
+ const query = new URLSearchParams();
36178
+ if (params?.page) query.set("page", String(params.page));
36179
+ if (params?.limit) query.set("limit", String(params.limit));
36180
+ const qs = query.toString() ? `?${query}` : "";
36181
+ return makeRequest("GET", `/api/projects${qs}`);
36182
+ }
36183
+ async function getProject(id) {
36184
+ return makeRequest(
36185
+ "GET",
36186
+ `/api/projects/${encodeURIComponent(id)}`
36187
+ );
36188
+ }
36189
+ async function createProject(data) {
36190
+ return makeRequest("POST", "/api/projects", data);
36191
+ }
36192
+ async function updateProject(params) {
36193
+ const { id, ...data } = params;
36194
+ return makeRequest(
36195
+ "PATCH",
36196
+ `/api/projects/${encodeURIComponent(id)}`,
36197
+ data
36198
+ );
36199
+ }
36200
+ async function archiveProject(id) {
36201
+ return makeRequest(
36202
+ "DELETE",
36203
+ `/api/projects/${encodeURIComponent(id)}`
36204
+ );
36205
+ }
36206
+ var init_langwatch_api_projects = __esm({
36207
+ "src/langwatch-api-projects.ts"() {
36208
+ "use strict";
36209
+ init_langwatch_api();
36210
+ }
36211
+ });
36212
+
36213
+ // src/tools/list-projects.ts
36214
+ var list_projects_exports = {};
36215
+ __export(list_projects_exports, {
36216
+ handleListProjects: () => handleListProjects
36217
+ });
36218
+ async function handleListProjects(params) {
36219
+ const result = await listProjects({
36220
+ page: params?.page,
36221
+ limit: params?.limit ?? 100
36222
+ });
36223
+ const projects = result.data;
36224
+ if (!Array.isArray(projects) || projects.length === 0) {
36225
+ return "No projects found in this organization.\n\n> Tip: Use `platform_create_project` to create your first project.";
36226
+ }
36227
+ const lines = [];
36228
+ lines.push(`# Projects (${result.pagination.total} total)
36229
+ `);
36230
+ for (const p of projects) {
36231
+ lines.push(`## ${p.name}`);
36232
+ lines.push(`**ID**: ${p.id}`);
36233
+ lines.push(`**Slug**: ${p.slug}`);
36234
+ lines.push(`**Language**: ${p.language}`);
36235
+ lines.push(`**Framework**: ${p.framework}`);
36236
+ lines.push(`**Updated**: ${p.updatedAt}`);
36237
+ lines.push("");
36238
+ }
36239
+ if (result.pagination.totalPages > 1) {
36240
+ lines.push(
36241
+ `> Showing page ${result.pagination.page} of ${result.pagination.totalPages}. Use \`page\` parameter to navigate.`
36242
+ );
36243
+ }
36244
+ lines.push(
36245
+ "> Use `platform_get_project` with the ID to see full project details."
36246
+ );
36247
+ return lines.join("\n");
36248
+ }
36249
+ var init_list_projects = __esm({
36250
+ "src/tools/list-projects.ts"() {
36251
+ "use strict";
36252
+ init_langwatch_api_projects();
36253
+ }
36254
+ });
36255
+
36256
+ // src/tools/get-project.ts
36257
+ var get_project_exports = {};
36258
+ __export(get_project_exports, {
36259
+ handleGetProject: () => handleGetProject
36260
+ });
36261
+ async function handleGetProject(params) {
36262
+ const project = await getProject(params.id);
36263
+ const lines = [];
36264
+ lines.push(`# ${project.name}
36265
+ `);
36266
+ lines.push(`**ID**: ${project.id}`);
36267
+ lines.push(`**Slug**: ${project.slug}`);
36268
+ lines.push(`**Language**: ${project.language}`);
36269
+ lines.push(`**Framework**: ${project.framework}`);
36270
+ lines.push(`**Team ID**: ${project.teamId}`);
36271
+ lines.push(`**PII Redaction**: ${project.piiRedactionLevel}`);
36272
+ lines.push(`**Created**: ${project.createdAt}`);
36273
+ lines.push(`**Updated**: ${project.updatedAt}`);
36274
+ return lines.join("\n");
36275
+ }
36276
+ var init_get_project = __esm({
36277
+ "src/tools/get-project.ts"() {
36278
+ "use strict";
36279
+ init_langwatch_api_projects();
36280
+ }
36281
+ });
36282
+
36283
+ // src/tools/create-project.ts
36284
+ var create_project_exports = {};
36285
+ __export(create_project_exports, {
36286
+ handleCreateProject: () => handleCreateProject
36287
+ });
36288
+ async function handleCreateProject(params) {
36289
+ if (!params.teamId && !params.newTeamName) {
36290
+ return "Error: You must provide either `teamId` (to add to an existing team) or `newTeamName` (to create a new team for this project).";
36291
+ }
36292
+ const result = await createProject({
36293
+ name: params.name,
36294
+ language: params.language,
36295
+ framework: params.framework,
36296
+ teamId: params.teamId,
36297
+ newTeamName: params.newTeamName
36298
+ });
36299
+ if (!result.serviceApiKey) {
36300
+ throw new Error(
36301
+ "API did not return a service API key. The project was created but the key is missing \u2014 check the LangWatch UI."
36302
+ );
36303
+ }
36304
+ const lines = [];
36305
+ lines.push(`Project created successfully!
36306
+ `);
36307
+ lines.push(`**Name**: ${result.name}`);
36308
+ lines.push(`**ID**: ${result.id}`);
36309
+ lines.push(`**Slug**: ${result.slug}`);
36310
+ lines.push(`**Language**: ${result.language}`);
36311
+ lines.push(`**Framework**: ${result.framework}`);
36312
+ lines.push("");
36313
+ lines.push(`**Service API Key**: \`${result.serviceApiKey}\``);
36314
+ lines.push(`**Service API Key ID**: ${result.serviceApiKeyId}`);
36315
+ lines.push("");
36316
+ lines.push(
36317
+ "> \u26A0\uFE0F Save the service API key now \u2014 it will not be shown again. Use it as `LANGWATCH_API_KEY` to authenticate project-scoped operations."
36318
+ );
36319
+ return lines.join("\n");
36320
+ }
36321
+ var init_create_project = __esm({
36322
+ "src/tools/create-project.ts"() {
36323
+ "use strict";
36324
+ init_langwatch_api_projects();
36325
+ }
36326
+ });
36327
+
36328
+ // src/tools/update-project.ts
36329
+ var update_project_exports = {};
36330
+ __export(update_project_exports, {
36331
+ handleUpdateProject: () => handleUpdateProject
36332
+ });
36333
+ async function handleUpdateProject(params) {
36334
+ const project = await updateProject(params);
36335
+ const lines = [];
36336
+ lines.push(`Project updated successfully!
36337
+ `);
36338
+ lines.push(`**Name**: ${project.name}`);
36339
+ lines.push(`**ID**: ${project.id}`);
36340
+ lines.push(`**Slug**: ${project.slug}`);
36341
+ lines.push(`**Language**: ${project.language}`);
36342
+ lines.push(`**Framework**: ${project.framework}`);
36343
+ lines.push(`**PII Redaction**: ${project.piiRedactionLevel}`);
36344
+ return lines.join("\n");
36345
+ }
36346
+ var init_update_project = __esm({
36347
+ "src/tools/update-project.ts"() {
36348
+ "use strict";
36349
+ init_langwatch_api_projects();
36350
+ }
36351
+ });
36352
+
36353
+ // src/tools/archive-project.ts
36354
+ var archive_project_exports = {};
36355
+ __export(archive_project_exports, {
36356
+ handleArchiveProject: () => handleArchiveProject
36357
+ });
36358
+ async function handleArchiveProject(params) {
36359
+ const result = await archiveProject(params.id);
36360
+ return `Project archived successfully.
36361
+
36362
+ **Name**: ${result.name}
36363
+ **ID**: ${result.id}
36364
+ **Archived At**: ${result.archivedAt}`;
36365
+ }
36366
+ var init_archive_project = __esm({
36367
+ "src/tools/archive-project.ts"() {
36368
+ "use strict";
36369
+ init_langwatch_api_projects();
36370
+ }
36371
+ });
36372
+
36373
+ // src/langwatch-api-api-keys.ts
36374
+ async function listApiKeys() {
36375
+ return makeRequest("GET", "/api/api-keys");
36376
+ }
36377
+ async function createApiKey(data) {
36378
+ return makeRequest("POST", "/api/api-keys", data);
36379
+ }
36380
+ async function revokeApiKey(id) {
36381
+ return makeRequest(
36382
+ "DELETE",
36383
+ `/api/api-keys/${encodeURIComponent(id)}`
36384
+ );
36385
+ }
36386
+ var init_langwatch_api_api_keys = __esm({
36387
+ "src/langwatch-api-api-keys.ts"() {
36388
+ "use strict";
36389
+ init_langwatch_api();
36390
+ }
36391
+ });
36392
+
36393
+ // src/tools/list-api-keys.ts
36394
+ var list_api_keys_exports = {};
36395
+ __export(list_api_keys_exports, {
36396
+ handleListApiKeys: () => handleListApiKeys
36397
+ });
36398
+ async function handleListApiKeys() {
36399
+ const result = await listApiKeys();
36400
+ const keys = result.data;
36401
+ if (!Array.isArray(keys) || keys.length === 0) {
36402
+ return "No API keys found.\n\n> Tip: Use `platform_create_api_key` to create a new key.";
36403
+ }
36404
+ const lines = [];
36405
+ lines.push(`# API Keys (${keys.length} total)
36406
+ `);
36407
+ for (const k of keys) {
36408
+ const status = k.revokedAt ? "REVOKED" : k.expiresAt && new Date(k.expiresAt) < /* @__PURE__ */ new Date() ? "EXPIRED" : "ACTIVE";
36409
+ lines.push(`## ${k.name}`);
36410
+ lines.push(`**ID**: ${k.id}`);
36411
+ lines.push(`**Status**: ${status}`);
36412
+ if (k.description) lines.push(`**Description**: ${k.description}`);
36413
+ if (k.expiresAt) lines.push(`**Expires**: ${k.expiresAt}`);
36414
+ if (k.lastUsedAt) lines.push(`**Last Used**: ${k.lastUsedAt}`);
36415
+ lines.push(`**Created**: ${k.createdAt}`);
36416
+ if (k.roleBindings.length > 0) {
36417
+ const bindings = k.roleBindings.map((rb) => `${rb.role} on ${rb.scopeType}:${rb.scopeId}`).join(", ");
36418
+ lines.push(`**Bindings**: ${bindings}`);
36419
+ }
36420
+ lines.push("");
36421
+ }
36422
+ return lines.join("\n");
36423
+ }
36424
+ var init_list_api_keys = __esm({
36425
+ "src/tools/list-api-keys.ts"() {
36426
+ "use strict";
36427
+ init_langwatch_api_api_keys();
36428
+ }
36429
+ });
36430
+
36431
+ // src/tools/create-api-key.ts
36432
+ var create_api_key_exports = {};
36433
+ __export(create_api_key_exports, {
36434
+ handleCreateApiKey: () => handleCreateApiKey
36435
+ });
36436
+ async function handleCreateApiKey(params) {
36437
+ const result = await createApiKey(params);
36438
+ const lines = [];
36439
+ lines.push(`API key created successfully!
36440
+ `);
36441
+ lines.push(`**Name**: ${result.apiKey.name}`);
36442
+ lines.push(`**ID**: ${result.apiKey.id}`);
36443
+ lines.push(`**Token**: \`${result.token}\``);
36444
+ lines.push(`**Created**: ${result.apiKey.createdAt}`);
36445
+ lines.push("");
36446
+ lines.push(
36447
+ "> \u26A0\uFE0F Save this token now \u2014 it will not be shown again."
36448
+ );
36449
+ return lines.join("\n");
36450
+ }
36451
+ var init_create_api_key = __esm({
36452
+ "src/tools/create-api-key.ts"() {
36453
+ "use strict";
36454
+ init_langwatch_api_api_keys();
36455
+ }
36456
+ });
36457
+
36458
+ // src/tools/revoke-api-key.ts
36459
+ var revoke_api_key_exports = {};
36460
+ __export(revoke_api_key_exports, {
36461
+ handleRevokeApiKey: () => handleRevokeApiKey
36462
+ });
36463
+ async function handleRevokeApiKey(params) {
36464
+ await revokeApiKey(params.id);
36465
+ return `API key ${params.id} revoked successfully.`;
36466
+ }
36467
+ var init_revoke_api_key = __esm({
36468
+ "src/tools/revoke-api-key.ts"() {
36469
+ "use strict";
36470
+ init_langwatch_api_api_keys();
36471
+ }
36472
+ });
36473
+
35731
36474
  // src/create-mcp-server.ts
35732
36475
  function createMcpServer() {
35733
36476
  const server = new McpServer({
@@ -36989,30 +37732,86 @@ ${lines.join("\n")}`
36989
37732
  })
36990
37733
  );
36991
37734
  server.tool(
36992
- "platform_run_evaluation",
36993
- "Start an evaluation run by slug. Returns a run ID for polling status.",
37735
+ "platform_run_experiment",
37736
+ "Start an experiment run by slug. Returns a run ID for polling status.",
37737
+ {
37738
+ slug: external_exports.string().describe("The experiment slug to run")
37739
+ },
37740
+ withToolLogging("platform_run_experiment", async (params) => {
37741
+ requireApiKey();
37742
+ return {
37743
+ content: [{ type: "text", text: await handleRunExperiment(params) }]
37744
+ };
37745
+ })
37746
+ );
37747
+ server.tool(
37748
+ "platform_experiment_status",
37749
+ "Check the status of an experiment run. Returns progress and summary when completed.",
36994
37750
  {
36995
- slug: external_exports.string().describe("The evaluation slug to run")
37751
+ runId: external_exports.string().describe("The run ID returned from platform_run_experiment")
36996
37752
  },
36997
- withToolLogging("platform_run_evaluation", async (params) => {
37753
+ withToolLogging("platform_experiment_status", async (params) => {
36998
37754
  requireApiKey();
36999
- const { handleRunEvaluation: handleRunEvaluation2 } = await Promise.resolve().then(() => (init_run_evaluation(), run_evaluation_exports));
37000
37755
  return {
37001
- content: [{ type: "text", text: await handleRunEvaluation2(params) }]
37756
+ content: [{ type: "text", text: await handleExperimentStatus(params) }]
37002
37757
  };
37003
37758
  })
37004
37759
  );
37005
37760
  server.tool(
37006
- "platform_evaluation_status",
37007
- "Check the status of an evaluation run. Returns progress and summary when completed.",
37761
+ "platform_experiment_list",
37762
+ "List experiments configured in the LangWatch project. Returns a markdown table with each experiment's slug, name, last-run timestamp, and run count. Use this to discover experiment slugs before drilling into runs with platform_experiment_list_runs. Output is capped (default 25, max 100) to protect the agent's context window.",
37008
37763
  {
37009
- runId: external_exports.string().describe("The run ID returned from platform_run_evaluation")
37764
+ limit: external_exports.number().int().positive().max(100).optional().describe(
37765
+ "Maximum number of experiments to include (default 25, hard-capped at 100)"
37766
+ )
37767
+ },
37768
+ withToolLogging("platform_experiment_list", async (params) => {
37769
+ requireApiKey();
37770
+ return {
37771
+ content: [{ type: "text", text: await handleExperimentList(params) }]
37772
+ };
37773
+ })
37774
+ );
37775
+ server.tool(
37776
+ "platform_experiment_list_runs",
37777
+ "List experiment runs for a specific experiment slug. Returns a markdown table with each run's id, status, started/finished timestamps, and pass-rate summary. Use this to discover run ids before calling platform_experiment_results. Output is capped (default 25, max 100) to protect the agent's context window.",
37778
+ {
37779
+ experimentSlug: external_exports.string().describe(
37780
+ "Experiment slug from platform_experiment_list (e.g. 'checkout-flow')"
37781
+ ),
37782
+ limit: external_exports.number().int().positive().max(100).optional().describe(
37783
+ "Maximum number of runs to include (default 25, hard-capped at 100)"
37784
+ )
37010
37785
  },
37011
- withToolLogging("platform_evaluation_status", async (params) => {
37786
+ withToolLogging("platform_experiment_list_runs", async (params) => {
37012
37787
  requireApiKey();
37013
- const { handleEvaluationStatus: handleEvaluationStatus2 } = await Promise.resolve().then(() => (init_run_evaluation(), run_evaluation_exports));
37014
37788
  return {
37015
- content: [{ type: "text", text: await handleEvaluationStatus2(params) }]
37789
+ content: [{ type: "text", text: await handleExperimentListRuns(params) }]
37790
+ };
37791
+ })
37792
+ );
37793
+ server.tool(
37794
+ "platform_experiment_results",
37795
+ "Fetch per-row results for a completed experiment run so you can debug evaluator scores and missed rows. Returns a markdown report: per-evaluator averages plus row-by-row scores and failure details. Output is capped at 50 rows to protect the agent's context window \u2014 narrow with `filter: 'failed'` or `evaluator` to see what matters.",
37796
+ {
37797
+ runId: external_exports.string().describe("The run ID returned from platform_run_experiment"),
37798
+ experimentSlug: external_exports.string().optional().describe(
37799
+ "Experiment slug \u2014 required when fetching results for runs older than 24h (Redis state may have expired). Use platform_experiment_list_runs to find the slug."
37800
+ ),
37801
+ filter: external_exports.enum(["all", "failed"]).optional().describe(
37802
+ "Filter rows: 'failed' shows only rows that errored or failed an evaluation; 'all' (default) shows everything"
37803
+ ),
37804
+ evaluator: external_exports.string().optional().describe("Show only this evaluator's results (matched on `evaluator` field)"),
37805
+ limit: external_exports.number().int().positive().max(50).optional().describe(
37806
+ "Maximum number of rows to include in the markdown output (default 50, hard-capped at 50)."
37807
+ )
37808
+ },
37809
+ withToolLogging("platform_experiment_results", async (params) => {
37810
+ requireApiKey();
37811
+ return {
37812
+ content: [
37813
+ { type: "text", text: await handleExperimentResults(params) }
37814
+ ]
37016
37815
  };
37017
37816
  })
37018
37817
  );
@@ -37171,6 +37970,141 @@ ${lines.join("\n")}`
37171
37970
  };
37172
37971
  }
37173
37972
  );
37973
+ server.tool(
37974
+ "platform_list_projects",
37975
+ "List all projects in your LangWatch organization. Requires an org-level API key.",
37976
+ {
37977
+ page: external_exports.number().int().positive().optional().describe("Page number (default: 1)"),
37978
+ limit: external_exports.number().int().positive().max(1e3).optional().describe("Results per page (default: 100)")
37979
+ },
37980
+ withToolLogging("platform_list_projects", async (params) => {
37981
+ requireApiKey();
37982
+ const { handleListProjects: handleListProjects2 } = await Promise.resolve().then(() => (init_list_projects(), list_projects_exports));
37983
+ return {
37984
+ content: [{ type: "text", text: await handleListProjects2(params) }]
37985
+ };
37986
+ })
37987
+ );
37988
+ server.tool(
37989
+ "platform_get_project",
37990
+ "Get details of a specific project by its ID.",
37991
+ {
37992
+ id: external_exports.string().describe("The project ID")
37993
+ },
37994
+ withToolLogging("platform_get_project", async (params) => {
37995
+ requireApiKey();
37996
+ const { handleGetProject: handleGetProject2 } = await Promise.resolve().then(() => (init_get_project(), get_project_exports));
37997
+ return {
37998
+ content: [{ type: "text", text: await handleGetProject2(params) }]
37999
+ };
38000
+ })
38001
+ );
38002
+ server.tool(
38003
+ "platform_create_project",
38004
+ `Create a new project in your LangWatch organization. Returns a one-time service API key for the project.
38005
+
38006
+ You must provide either teamId (to add the project to an existing team) or newTeamName (to create a new team for the project).`,
38007
+ {
38008
+ name: external_exports.string().describe("Project name"),
38009
+ language: external_exports.string().describe('Programming language (e.g. "python", "typescript")'),
38010
+ framework: external_exports.string().describe('Framework (e.g. "openai", "langchain", "custom")'),
38011
+ teamId: external_exports.string().optional().describe("ID of an existing team to add the project to"),
38012
+ newTeamName: external_exports.string().optional().describe("Name for a new team to create for this project")
38013
+ },
38014
+ withToolLogging("platform_create_project", async (params) => {
38015
+ requireApiKey();
38016
+ const { handleCreateProject: handleCreateProject2 } = await Promise.resolve().then(() => (init_create_project(), create_project_exports));
38017
+ return {
38018
+ content: [{ type: "text", text: await handleCreateProject2(params) }]
38019
+ };
38020
+ })
38021
+ );
38022
+ server.tool(
38023
+ "platform_update_project",
38024
+ "Update an existing project's name, language, framework, or PII redaction level.",
38025
+ {
38026
+ id: external_exports.string().describe("The project ID to update"),
38027
+ name: external_exports.string().optional().describe("New project name"),
38028
+ language: external_exports.string().optional().describe("New programming language"),
38029
+ framework: external_exports.string().optional().describe("New framework"),
38030
+ piiRedactionLevel: external_exports.enum(["STRICT", "ESSENTIAL", "DISABLED"]).optional().describe("PII redaction level")
38031
+ },
38032
+ withToolLogging("platform_update_project", async (params) => {
38033
+ requireApiKey();
38034
+ const { handleUpdateProject: handleUpdateProject2 } = await Promise.resolve().then(() => (init_update_project(), update_project_exports));
38035
+ return {
38036
+ content: [{ type: "text", text: await handleUpdateProject2(params) }]
38037
+ };
38038
+ })
38039
+ );
38040
+ server.tool(
38041
+ "platform_archive_project",
38042
+ "Archive (soft-delete) a project. The project can be restored later if needed.",
38043
+ {
38044
+ id: external_exports.string().describe("The project ID to archive")
38045
+ },
38046
+ withToolLogging("platform_archive_project", async (params) => {
38047
+ requireApiKey();
38048
+ const { handleArchiveProject: handleArchiveProject2 } = await Promise.resolve().then(() => (init_archive_project(), archive_project_exports));
38049
+ return {
38050
+ content: [{ type: "text", text: await handleArchiveProject2(params) }]
38051
+ };
38052
+ })
38053
+ );
38054
+ server.tool(
38055
+ "platform_list_api_keys",
38056
+ "List all API keys in your LangWatch organization. Shows key metadata, status (active/revoked/expired), and role bindings. API key tokens are never returned.",
38057
+ {},
38058
+ withToolLogging("platform_list_api_keys", async () => {
38059
+ requireApiKey();
38060
+ const { handleListApiKeys: handleListApiKeys2 } = await Promise.resolve().then(() => (init_list_api_keys(), list_api_keys_exports));
38061
+ return {
38062
+ content: [{ type: "text", text: await handleListApiKeys2() }]
38063
+ };
38064
+ })
38065
+ );
38066
+ server.tool(
38067
+ "platform_create_api_key",
38068
+ `Create a new API key. Two types available:
38069
+
38070
+ - **personal**: Tied to a user, requires explicit role bindings (e.g. ADMIN on PROJECT:proj_123).
38071
+ - **service**: Not tied to a user. Use projectIds for project-scoped service keys, or omit for org-wide access.
38072
+
38073
+ The token is returned once and cannot be retrieved again.`,
38074
+ {
38075
+ keyType: external_exports.enum(["personal", "service"]).describe("Key type: 'personal' (user-tied) or 'service' (headless)"),
38076
+ name: external_exports.string().describe("Key name (max 100 chars)"),
38077
+ description: external_exports.string().optional().describe("Key description (max 500 chars)"),
38078
+ expiresAt: external_exports.string().optional().describe("Expiration date (ISO string)"),
38079
+ bindings: external_exports.array(external_exports.object({
38080
+ role: external_exports.enum(["ADMIN", "MEMBER", "VIEWER"]).describe("Role"),
38081
+ scopeType: external_exports.enum(["ORGANIZATION", "TEAM", "PROJECT"]).describe("Scope type"),
38082
+ scopeId: external_exports.string().describe("Scope ID (org, team, or project ID)")
38083
+ })).optional().describe("Role bindings (required for personal keys)"),
38084
+ projectIds: external_exports.array(external_exports.string()).optional().describe("Project IDs for service keys (creates ADMIN bindings per project)")
38085
+ },
38086
+ withToolLogging("platform_create_api_key", async (params) => {
38087
+ requireApiKey();
38088
+ const { handleCreateApiKey: handleCreateApiKey2 } = await Promise.resolve().then(() => (init_create_api_key(), create_api_key_exports));
38089
+ return {
38090
+ content: [{ type: "text", text: await handleCreateApiKey2(params) }]
38091
+ };
38092
+ })
38093
+ );
38094
+ server.tool(
38095
+ "platform_revoke_api_key",
38096
+ "Revoke an API key. Once revoked, the key can no longer be used for authentication.",
38097
+ {
38098
+ id: external_exports.string().describe("The API key ID to revoke")
38099
+ },
38100
+ withToolLogging("platform_revoke_api_key", async (params) => {
38101
+ requireApiKey();
38102
+ const { handleRevokeApiKey: handleRevokeApiKey2 } = await Promise.resolve().then(() => (init_revoke_api_key(), revoke_api_key_exports));
38103
+ return {
38104
+ content: [{ type: "text", text: await handleRevokeApiKey2(params) }]
38105
+ };
38106
+ })
38107
+ );
37174
38108
  }
37175
38109
  var modelSchema;
37176
38110
  var init_create_mcp_server = __esm({
@@ -37181,6 +38115,10 @@ var init_create_mcp_server = __esm({
37181
38115
  init_package();
37182
38116
  init_config();
37183
38117
  init_create_dataset();
38118
+ init_get_experiment_results();
38119
+ init_list_experiment_runs();
38120
+ init_list_experiments();
38121
+ init_run_experiment();
37184
38122
  modelSchema = external_exports.string().describe(
37185
38123
  'Model in "provider/model-name" format, e.g., "openai/gpt-4o", "anthropic/claude-sonnet-4-5-20250929"'
37186
38124
  );
@@ -57102,9 +58040,9 @@ var require_is_promise = __commonJS({
57102
58040
  }
57103
58041
  });
57104
58042
 
57105
- // node_modules/.pnpm/path-to-regexp@8.3.0/node_modules/path-to-regexp/dist/index.js
58043
+ // node_modules/.pnpm/path-to-regexp@8.4.2/node_modules/path-to-regexp/dist/index.js
57106
58044
  var require_dist2 = __commonJS({
57107
- "node_modules/.pnpm/path-to-regexp@8.3.0/node_modules/path-to-regexp/dist/index.js"(exports) {
58045
+ "node_modules/.pnpm/path-to-regexp@8.4.2/node_modules/path-to-regexp/dist/index.js"(exports) {
57108
58046
  "use strict";
57109
58047
  Object.defineProperty(exports, "__esModule", { value: true });
57110
58048
  exports.PathError = exports.TokenData = void 0;
@@ -57117,19 +58055,7 @@ var require_dist2 = __commonJS({
57117
58055
  var NOOP_VALUE = (value) => value;
57118
58056
  var ID_START = /^[$_\p{ID_Start}]$/u;
57119
58057
  var ID_CONTINUE = /^[$\u200c\u200d\p{ID_Continue}]$/u;
57120
- var SIMPLE_TOKENS = {
57121
- // Groups.
57122
- "{": "{",
57123
- "}": "}",
57124
- // Reserved.
57125
- "(": "(",
57126
- ")": ")",
57127
- "[": "[",
57128
- "]": "]",
57129
- "+": "+",
57130
- "?": "?",
57131
- "!": "!"
57132
- };
58058
+ var ID = /^[$_\p{ID_Start}][$\u200c\u200d\p{ID_Continue}]*$/u;
57133
58059
  function escapeText(str) {
57134
58060
  return str.replace(/[{}()\[\]+?!:*\\]/g, "\\$&");
57135
58061
  }
@@ -57157,97 +58083,90 @@ var require_dist2 = __commonJS({
57157
58083
  function parse3(str, options = {}) {
57158
58084
  const { encodePath = NOOP_VALUE } = options;
57159
58085
  const chars = [...str];
57160
- const tokens = [];
57161
58086
  let index = 0;
57162
- let pos = 0;
57163
- function name() {
57164
- let value = "";
57165
- if (ID_START.test(chars[index])) {
57166
- do {
57167
- value += chars[index++];
57168
- } while (ID_CONTINUE.test(chars[index]));
57169
- } else if (chars[index] === '"') {
57170
- let quoteStart = index;
57171
- while (index++ < chars.length) {
57172
- if (chars[index] === '"') {
57173
- index++;
57174
- quoteStart = 0;
57175
- break;
57176
- }
57177
- if (chars[index] === "\\")
57178
- index++;
57179
- value += chars[index];
57180
- }
57181
- if (quoteStart) {
57182
- throw new PathError(`Unterminated quote at index ${quoteStart}`, str);
57183
- }
57184
- }
57185
- if (!value) {
57186
- throw new PathError(`Missing parameter name at index ${index}`, str);
57187
- }
57188
- return value;
57189
- }
57190
- while (index < chars.length) {
57191
- const value = chars[index];
57192
- const type = SIMPLE_TOKENS[value];
57193
- if (type) {
57194
- tokens.push({ type, index: index++, value });
57195
- } else if (value === "\\") {
57196
- tokens.push({ type: "escape", index: index++, value: chars[index++] });
57197
- } else if (value === ":") {
57198
- tokens.push({ type: "param", index: index++, value: name() });
57199
- } else if (value === "*") {
57200
- tokens.push({ type: "wildcard", index: index++, value: name() });
57201
- } else {
57202
- tokens.push({ type: "char", index: index++, value });
57203
- }
57204
- }
57205
- tokens.push({ type: "end", index, value: "" });
57206
- function consumeUntil(endType) {
58087
+ function consumeUntil(end) {
57207
58088
  const output = [];
57208
- while (true) {
57209
- const token = tokens[pos++];
57210
- if (token.type === endType)
57211
- break;
57212
- if (token.type === "char" || token.type === "escape") {
57213
- let path = token.value;
57214
- let cur = tokens[pos];
57215
- while (cur.type === "char" || cur.type === "escape") {
57216
- path += cur.value;
57217
- cur = tokens[++pos];
58089
+ let path = "";
58090
+ function writePath() {
58091
+ if (!path)
58092
+ return;
58093
+ output.push({
58094
+ type: "text",
58095
+ value: encodePath(path)
58096
+ });
58097
+ path = "";
58098
+ }
58099
+ while (index < chars.length) {
58100
+ const value = chars[index++];
58101
+ if (value === end) {
58102
+ writePath();
58103
+ return output;
58104
+ }
58105
+ if (value === "\\") {
58106
+ if (index === chars.length) {
58107
+ throw new PathError(`Unexpected end after \\ at index ${index}`, str);
57218
58108
  }
57219
- output.push({
57220
- type: "text",
57221
- value: encodePath(path)
57222
- });
58109
+ path += chars[index++];
57223
58110
  continue;
57224
58111
  }
57225
- if (token.type === "param" || token.type === "wildcard") {
57226
- output.push({
57227
- type: token.type,
57228
- name: token.value
57229
- });
58112
+ if (value === ":" || value === "*") {
58113
+ const type = value === ":" ? "param" : "wildcard";
58114
+ let name = "";
58115
+ if (ID_START.test(chars[index])) {
58116
+ do {
58117
+ name += chars[index++];
58118
+ } while (ID_CONTINUE.test(chars[index]));
58119
+ } else if (chars[index] === '"') {
58120
+ let quoteStart = index;
58121
+ while (index < chars.length) {
58122
+ if (chars[++index] === '"') {
58123
+ index++;
58124
+ quoteStart = 0;
58125
+ break;
58126
+ }
58127
+ if (chars[index] === "\\")
58128
+ index++;
58129
+ name += chars[index];
58130
+ }
58131
+ if (quoteStart) {
58132
+ throw new PathError(`Unterminated quote at index ${quoteStart}`, str);
58133
+ }
58134
+ }
58135
+ if (!name) {
58136
+ throw new PathError(`Missing parameter name at index ${index}`, str);
58137
+ }
58138
+ writePath();
58139
+ output.push({ type, name });
57230
58140
  continue;
57231
58141
  }
57232
- if (token.type === "{") {
58142
+ if (value === "{") {
58143
+ writePath();
57233
58144
  output.push({
57234
58145
  type: "group",
57235
58146
  tokens: consumeUntil("}")
57236
58147
  });
57237
58148
  continue;
57238
58149
  }
57239
- throw new PathError(`Unexpected ${token.type} at index ${token.index}, expected ${endType}`, str);
58150
+ if (value === "}" || value === "(" || value === ")" || value === "[" || value === "]" || value === "+" || value === "?" || value === "!") {
58151
+ throw new PathError(`Unexpected ${value} at index ${index - 1}`, str);
58152
+ }
58153
+ path += value;
58154
+ }
58155
+ if (end) {
58156
+ throw new PathError(`Unexpected end at index ${index}, expected ${end}`, str);
57240
58157
  }
58158
+ writePath();
57241
58159
  return output;
57242
58160
  }
57243
- return new TokenData(consumeUntil("end"), str);
58161
+ return new TokenData(consumeUntil(""), str);
57244
58162
  }
57245
58163
  function compile(path, options = {}) {
57246
58164
  const { encode: encode3 = encodeURIComponent, delimiter = DEFAULT_DELIMITER } = options;
57247
58165
  const data = typeof path === "object" ? path : parse3(path, options);
57248
58166
  const fn = tokensToFunction(data.tokens, delimiter, encode3);
57249
58167
  return function path2(params = {}) {
57250
- const [path3, ...missing] = fn(params);
58168
+ const missing = [];
58169
+ const path3 = fn(params, missing);
57251
58170
  if (missing.length) {
57252
58171
  throw new TypeError(`Missing parameters: ${missing.join(", ")}`);
57253
58172
  }
@@ -57256,55 +58175,61 @@ var require_dist2 = __commonJS({
57256
58175
  }
57257
58176
  function tokensToFunction(tokens, delimiter, encode3) {
57258
58177
  const encoders = tokens.map((token) => tokenToFunction(token, delimiter, encode3));
57259
- return (data) => {
57260
- const result = [""];
58178
+ return (data, missing) => {
58179
+ let result = "";
57261
58180
  for (const encoder of encoders) {
57262
- const [value, ...extras] = encoder(data);
57263
- result[0] += value;
57264
- result.push(...extras);
58181
+ result += encoder(data, missing);
57265
58182
  }
57266
58183
  return result;
57267
58184
  };
57268
58185
  }
57269
58186
  function tokenToFunction(token, delimiter, encode3) {
57270
58187
  if (token.type === "text")
57271
- return () => [token.value];
58188
+ return () => token.value;
57272
58189
  if (token.type === "group") {
57273
58190
  const fn = tokensToFunction(token.tokens, delimiter, encode3);
57274
- return (data) => {
57275
- const [value, ...missing] = fn(data);
57276
- if (!missing.length)
57277
- return [value];
57278
- return [""];
58191
+ return (data, missing) => {
58192
+ const len = missing.length;
58193
+ const value = fn(data, missing);
58194
+ if (missing.length === len)
58195
+ return value;
58196
+ missing.length = len;
58197
+ return "";
57279
58198
  };
57280
58199
  }
57281
58200
  const encodeValue = encode3 || NOOP_VALUE;
57282
58201
  if (token.type === "wildcard" && encode3 !== false) {
57283
- return (data) => {
58202
+ return (data, missing) => {
57284
58203
  const value = data[token.name];
57285
- if (value == null)
57286
- return ["", token.name];
58204
+ if (value == null) {
58205
+ missing.push(token.name);
58206
+ return "";
58207
+ }
57287
58208
  if (!Array.isArray(value) || value.length === 0) {
57288
58209
  throw new TypeError(`Expected "${token.name}" to be a non-empty array`);
57289
58210
  }
57290
- return [
57291
- value.map((value2, index) => {
57292
- if (typeof value2 !== "string") {
57293
- throw new TypeError(`Expected "${token.name}/${index}" to be a string`);
57294
- }
57295
- return encodeValue(value2);
57296
- }).join(delimiter)
57297
- ];
58211
+ let result = "";
58212
+ for (let i = 0; i < value.length; i++) {
58213
+ if (typeof value[i] !== "string") {
58214
+ throw new TypeError(`Expected "${token.name}/${i}" to be a string`);
58215
+ }
58216
+ if (i > 0)
58217
+ result += delimiter;
58218
+ result += encodeValue(value[i]);
58219
+ }
58220
+ return result;
57298
58221
  };
57299
58222
  }
57300
- return (data) => {
58223
+ return (data, missing) => {
57301
58224
  const value = data[token.name];
57302
- if (value == null)
57303
- return ["", token.name];
58225
+ if (value == null) {
58226
+ missing.push(token.name);
58227
+ return "";
58228
+ }
57304
58229
  if (typeof value !== "string") {
57305
58230
  throw new TypeError(`Expected "${token.name}" to be a string`);
57306
58231
  }
57307
- return [encodeValue(value)];
58232
+ return encodeValue(value);
57308
58233
  };
57309
58234
  }
57310
58235
  function match(path, options = {}) {
@@ -57336,106 +58261,134 @@ var require_dist2 = __commonJS({
57336
58261
  function pathToRegexp(path, options = {}) {
57337
58262
  const { delimiter = DEFAULT_DELIMITER, end = true, sensitive = false, trailing = true } = options;
57338
58263
  const keys = [];
57339
- const flags = sensitive ? "" : "i";
57340
- const sources = [];
57341
- for (const input of pathsToArray(path, [])) {
57342
- const data = typeof input === "object" ? input : parse3(input, options);
57343
- for (const tokens of flatten(data.tokens, 0, [])) {
57344
- sources.push(toRegExpSource(tokens, delimiter, keys, data.originalPath));
58264
+ let source = "";
58265
+ let combinations = 0;
58266
+ function process4(path2) {
58267
+ if (Array.isArray(path2)) {
58268
+ for (const p of path2)
58269
+ process4(p);
58270
+ return;
57345
58271
  }
58272
+ const data = typeof path2 === "object" ? path2 : parse3(path2, options);
58273
+ flatten(data.tokens, 0, [], (tokens) => {
58274
+ if (combinations >= 256) {
58275
+ throw new PathError("Too many path combinations", data.originalPath);
58276
+ }
58277
+ if (combinations > 0)
58278
+ source += "|";
58279
+ source += toRegExpSource(tokens, delimiter, keys, data.originalPath);
58280
+ combinations++;
58281
+ });
57346
58282
  }
57347
- let pattern = `^(?:${sources.join("|")})`;
58283
+ process4(path);
58284
+ let pattern = `^(?:${source})`;
57348
58285
  if (trailing)
57349
- pattern += `(?:${escape2(delimiter)}$)?`;
57350
- pattern += end ? "$" : `(?=${escape2(delimiter)}|$)`;
57351
- const regexp = new RegExp(pattern, flags);
57352
- return { regexp, keys };
57353
- }
57354
- function pathsToArray(paths, init) {
57355
- if (Array.isArray(paths)) {
57356
- for (const p of paths)
57357
- pathsToArray(p, init);
57358
- } else {
57359
- init.push(paths);
57360
- }
57361
- return init;
58286
+ pattern += "(?:" + escape2(delimiter) + "$)?";
58287
+ pattern += end ? "$" : "(?=" + escape2(delimiter) + "|$)";
58288
+ return { regexp: new RegExp(pattern, sensitive ? "" : "i"), keys };
57362
58289
  }
57363
- function* flatten(tokens, index, init) {
57364
- if (index === tokens.length) {
57365
- return yield init;
57366
- }
57367
- const token = tokens[index];
57368
- if (token.type === "group") {
57369
- for (const seq of flatten(token.tokens, 0, init.slice())) {
57370
- yield* flatten(tokens, index + 1, seq);
58290
+ function flatten(tokens, index, result, callback) {
58291
+ while (index < tokens.length) {
58292
+ const token = tokens[index++];
58293
+ if (token.type === "group") {
58294
+ const len = result.length;
58295
+ flatten(token.tokens, 0, result, (seq) => flatten(tokens, index, seq, callback));
58296
+ result.length = len;
58297
+ continue;
57371
58298
  }
57372
- } else {
57373
- init.push(token);
58299
+ result.push(token);
57374
58300
  }
57375
- yield* flatten(tokens, index + 1, init);
58301
+ callback(result);
57376
58302
  }
57377
58303
  function toRegExpSource(tokens, delimiter, keys, originalPath) {
57378
58304
  let result = "";
57379
58305
  let backtrack = "";
57380
- let isSafeSegmentParam = true;
57381
- for (const token of tokens) {
58306
+ let wildcardBacktrack = "";
58307
+ let prevCaptureType = 0;
58308
+ let hasSegmentCapture = 0;
58309
+ let index = 0;
58310
+ function hasInSegment(index2, type) {
58311
+ while (index2 < tokens.length) {
58312
+ const token = tokens[index2++];
58313
+ if (token.type === type)
58314
+ return true;
58315
+ if (token.type === "text") {
58316
+ if (token.value.includes(delimiter))
58317
+ break;
58318
+ }
58319
+ }
58320
+ return false;
58321
+ }
58322
+ function peekText(index2) {
58323
+ let result2 = "";
58324
+ while (index2 < tokens.length) {
58325
+ const token = tokens[index2++];
58326
+ if (token.type !== "text")
58327
+ break;
58328
+ result2 += token.value;
58329
+ }
58330
+ return result2;
58331
+ }
58332
+ while (index < tokens.length) {
58333
+ const token = tokens[index++];
57382
58334
  if (token.type === "text") {
57383
58335
  result += escape2(token.value);
57384
58336
  backtrack += token.value;
57385
- isSafeSegmentParam || (isSafeSegmentParam = token.value.includes(delimiter));
58337
+ if (prevCaptureType === 2)
58338
+ wildcardBacktrack += token.value;
58339
+ if (token.value.includes(delimiter))
58340
+ hasSegmentCapture = 0;
57386
58341
  continue;
57387
58342
  }
57388
58343
  if (token.type === "param" || token.type === "wildcard") {
57389
- if (!isSafeSegmentParam && !backtrack) {
58344
+ if (prevCaptureType && !backtrack) {
57390
58345
  throw new PathError(`Missing text before "${token.name}" ${token.type}`, originalPath);
57391
58346
  }
57392
58347
  if (token.type === "param") {
57393
- result += `(${negate(delimiter, isSafeSegmentParam ? "" : backtrack)}+)`;
58348
+ result += hasSegmentCapture & 2 ? `(${negate(delimiter, backtrack)}+)` : hasInSegment(index, "wildcard") ? `(${negate(delimiter, peekText(index))}+)` : hasSegmentCapture & 1 ? `(${negate(delimiter, backtrack)}+|${escape2(backtrack)})` : `(${negate(delimiter, "")}+)`;
58349
+ hasSegmentCapture |= prevCaptureType = 1;
57394
58350
  } else {
57395
- result += `([\\s\\S]+)`;
58351
+ result += hasSegmentCapture & 2 ? `(${negate(backtrack, "")}+)` : wildcardBacktrack ? `(${negate(wildcardBacktrack, "")}+|${negate(delimiter, "")}+)` : `([^]+)`;
58352
+ wildcardBacktrack = "";
58353
+ hasSegmentCapture |= prevCaptureType = 2;
57396
58354
  }
57397
58355
  keys.push(token);
57398
58356
  backtrack = "";
57399
- isSafeSegmentParam = false;
57400
58357
  continue;
57401
58358
  }
58359
+ throw new TypeError(`Unknown token type: ${token.type}`);
57402
58360
  }
57403
58361
  return result;
57404
58362
  }
57405
- function negate(delimiter, backtrack) {
57406
- if (backtrack.length < 2) {
57407
- if (delimiter.length < 2)
57408
- return `[^${escape2(delimiter + backtrack)}]`;
57409
- return `(?:(?!${escape2(delimiter)})[^${escape2(backtrack)}])`;
57410
- }
57411
- if (delimiter.length < 2) {
57412
- return `(?:(?!${escape2(backtrack)})[^${escape2(delimiter)}])`;
57413
- }
57414
- return `(?:(?!${escape2(backtrack)}|${escape2(delimiter)})[\\s\\S])`;
57415
- }
57416
- function stringifyTokens(tokens) {
58363
+ function negate(a, b) {
58364
+ if (b.length > a.length)
58365
+ return negate(b, a);
58366
+ if (a === b)
58367
+ b = "";
58368
+ if (b.length > 1)
58369
+ return `(?:(?!${escape2(a)}|${escape2(b)})[^])`;
58370
+ if (a.length > 1)
58371
+ return `(?:(?!${escape2(a)})[^${escape2(b)}])`;
58372
+ return `[^${escape2(a + b)}]`;
58373
+ }
58374
+ function stringifyTokens(tokens, index) {
57417
58375
  let value = "";
57418
- let i = 0;
57419
- function name(value2) {
57420
- const isSafe = isNameSafe(value2) && isNextNameSafe(tokens[i]);
57421
- return isSafe ? value2 : JSON.stringify(value2);
57422
- }
57423
- while (i < tokens.length) {
57424
- const token = tokens[i++];
58376
+ while (index < tokens.length) {
58377
+ const token = tokens[index++];
57425
58378
  if (token.type === "text") {
57426
58379
  value += escapeText(token.value);
57427
58380
  continue;
57428
58381
  }
57429
58382
  if (token.type === "group") {
57430
- value += `{${stringifyTokens(token.tokens)}}`;
58383
+ value += "{" + stringifyTokens(token.tokens, 0) + "}";
57431
58384
  continue;
57432
58385
  }
57433
58386
  if (token.type === "param") {
57434
- value += `:${name(token.name)}`;
58387
+ value += ":" + stringifyName(token.name, tokens[index]);
57435
58388
  continue;
57436
58389
  }
57437
58390
  if (token.type === "wildcard") {
57438
- value += `*${name(token.name)}`;
58391
+ value += "*" + stringifyName(token.name, tokens[index]);
57439
58392
  continue;
57440
58393
  }
57441
58394
  throw new TypeError(`Unknown token type: ${token.type}`);
@@ -57443,16 +58396,15 @@ var require_dist2 = __commonJS({
57443
58396
  return value;
57444
58397
  }
57445
58398
  function stringify(data) {
57446
- return stringifyTokens(data.tokens);
58399
+ return stringifyTokens(data.tokens, 0);
57447
58400
  }
57448
- function isNameSafe(name) {
57449
- const [first, ...rest] = name;
57450
- return ID_START.test(first) && rest.every((char) => ID_CONTINUE.test(char));
57451
- }
57452
- function isNextNameSafe(token) {
57453
- if (token && token.type === "text")
57454
- return !ID_CONTINUE.test(token.value[0]);
57455
- return true;
58401
+ function stringifyName(name, next) {
58402
+ if (!ID.test(name))
58403
+ return JSON.stringify(name);
58404
+ if ((next === null || next === void 0 ? void 0 : next.type) === "text" && ID_CONTINUE.test(next.value[0])) {
58405
+ return JSON.stringify(name);
58406
+ }
58407
+ return name;
57456
58408
  }
57457
58409
  }
57458
58410
  });
@@ -60806,8 +61758,8 @@ var require_express2 = __commonJS({
60806
61758
  }
60807
61759
  });
60808
61760
 
60809
- // node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.5/node_modules/@hono/node-server/dist/index.mjs
60810
- import { Http2ServerRequest as Http2ServerRequest2 } from "http2";
61761
+ // node_modules/.pnpm/@hono+node-server@1.19.14_hono@4.12.14/node_modules/@hono/node-server/dist/index.mjs
61762
+ import { Http2ServerRequest as Http2ServerRequest2, constants as h2constants } from "http2";
60811
61763
  import { Http2ServerRequest } from "http2";
60812
61764
  import { Readable } from "stream";
60813
61765
  import crypto2 from "crypto";
@@ -60856,9 +61808,9 @@ function writeFromReadableStream(stream, writable) {
60856
61808
  }
60857
61809
  return writeFromReadableStreamDefaultReader(stream.getReader(), writable);
60858
61810
  }
60859
- var RequestError, toRequestError, GlobalRequest, Request, newHeadersFromIncoming, wrapBodyStream, newRequestFromIncoming, getRequestCache, requestCache, incomingKey, urlKey, headersKey, abortControllerKey, getAbortController, requestPrototype, newRequest, responseCache, getResponseCache, cacheKey, GlobalResponse, Response2, buildOutgoingHttpHeaders, X_ALREADY_SENT, outgoingEnded, handleRequestError, handleFetchError, handleResponseError, flushHeaders, responseViaCache, isPromise2, responseViaResponseObject, getRequestListener;
61811
+ var RequestError, toRequestError, GlobalRequest, Request, newHeadersFromIncoming, wrapBodyStream, newRequestFromIncoming, getRequestCache, requestCache, incomingKey, urlKey, headersKey, abortControllerKey, getAbortController, requestPrototype, newRequest, responseCache, getResponseCache, cacheKey, GlobalResponse, Response2, buildOutgoingHttpHeaders, X_ALREADY_SENT, outgoingEnded, incomingDraining, DRAIN_TIMEOUT_MS, MAX_DRAIN_BYTES, drainIncoming, handleRequestError, handleFetchError, handleResponseError, flushHeaders, responseViaCache, isPromise2, responseViaResponseObject, getRequestListener;
60860
61812
  var init_dist = __esm({
60861
- "node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.5/node_modules/@hono/node-server/dist/index.mjs"() {
61813
+ "node_modules/.pnpm/@hono+node-server@1.19.14_hono@4.12.14/node_modules/@hono/node-server/dist/index.mjs"() {
60862
61814
  RequestError = class extends Error {
60863
61815
  constructor(message, options) {
60864
61816
  super(message, options);
@@ -61003,6 +61955,17 @@ var init_dist = __esm({
61003
61955
  }
61004
61956
  });
61005
61957
  });
61958
+ Object.defineProperty(requestPrototype, Symbol.for("nodejs.util.inspect.custom"), {
61959
+ value: function(depth, options, inspectFn) {
61960
+ const props = {
61961
+ method: this.method,
61962
+ url: this.url,
61963
+ headers: this.headers,
61964
+ nativeRequest: this[requestCache]
61965
+ };
61966
+ return `Request (lightweight) ${inspectFn(props, { ...options, depth: depth == null ? null : depth - 1 })}`;
61967
+ }
61968
+ });
61006
61969
  Object.setPrototypeOf(requestPrototype, Request.prototype);
61007
61970
  newRequest = (incoming, defaultHostname) => {
61008
61971
  const req = Object.create(requestPrototype);
@@ -61107,6 +62070,17 @@ var init_dist = __esm({
61107
62070
  }
61108
62071
  });
61109
62072
  });
62073
+ Object.defineProperty(Response2.prototype, Symbol.for("nodejs.util.inspect.custom"), {
62074
+ value: function(depth, options, inspectFn) {
62075
+ const props = {
62076
+ status: this.status,
62077
+ headers: this.headers,
62078
+ ok: this.ok,
62079
+ nativeResponse: this[responseCache]
62080
+ };
62081
+ return `Response (lightweight) ${inspectFn(props, { ...options, depth: depth == null ? null : depth - 1 })}`;
62082
+ }
62083
+ });
61110
62084
  Object.setPrototypeOf(Response2, GlobalResponse);
61111
62085
  Object.setPrototypeOf(Response2.prototype, GlobalResponse.prototype);
61112
62086
  buildOutgoingHttpHeaders = (headers) => {
@@ -61133,6 +62107,50 @@ var init_dist = __esm({
61133
62107
  global.crypto = crypto2;
61134
62108
  }
61135
62109
  outgoingEnded = Symbol("outgoingEnded");
62110
+ incomingDraining = Symbol("incomingDraining");
62111
+ DRAIN_TIMEOUT_MS = 500;
62112
+ MAX_DRAIN_BYTES = 64 * 1024 * 1024;
62113
+ drainIncoming = (incoming) => {
62114
+ const incomingWithDrainState = incoming;
62115
+ if (incoming.destroyed || incomingWithDrainState[incomingDraining]) {
62116
+ return;
62117
+ }
62118
+ incomingWithDrainState[incomingDraining] = true;
62119
+ if (incoming instanceof Http2ServerRequest2) {
62120
+ try {
62121
+ ;
62122
+ incoming.stream?.close?.(h2constants.NGHTTP2_NO_ERROR);
62123
+ } catch {
62124
+ }
62125
+ return;
62126
+ }
62127
+ let bytesRead = 0;
62128
+ const cleanup = () => {
62129
+ clearTimeout(timer);
62130
+ incoming.off("data", onData);
62131
+ incoming.off("end", cleanup);
62132
+ incoming.off("error", cleanup);
62133
+ };
62134
+ const forceClose = () => {
62135
+ cleanup();
62136
+ const socket = incoming.socket;
62137
+ if (socket && !socket.destroyed) {
62138
+ socket.destroySoon();
62139
+ }
62140
+ };
62141
+ const timer = setTimeout(forceClose, DRAIN_TIMEOUT_MS);
62142
+ timer.unref?.();
62143
+ const onData = (chunk) => {
62144
+ bytesRead += chunk.length;
62145
+ if (bytesRead > MAX_DRAIN_BYTES) {
62146
+ forceClose();
62147
+ }
62148
+ };
62149
+ incoming.on("data", onData);
62150
+ incoming.on("end", cleanup);
62151
+ incoming.on("error", cleanup);
62152
+ incoming.resume();
62153
+ };
61136
62154
  handleRequestError = () => new Response(null, {
61137
62155
  status: 400
61138
62156
  });
@@ -61304,14 +62322,18 @@ var init_dist = __esm({
61304
62322
  setTimeout(() => {
61305
62323
  if (!incomingEnded) {
61306
62324
  setTimeout(() => {
61307
- incoming.destroy();
61308
- outgoing.destroy();
62325
+ drainIncoming(incoming);
61309
62326
  });
61310
62327
  }
61311
62328
  });
61312
62329
  }
61313
62330
  };
61314
62331
  }
62332
+ outgoing.on("finish", () => {
62333
+ if (!incomingEnded) {
62334
+ drainIncoming(incoming);
62335
+ }
62336
+ });
61315
62337
  }
61316
62338
  outgoing.on("close", () => {
61317
62339
  const abortController = req[abortControllerKey];
@@ -61326,7 +62348,7 @@ var init_dist = __esm({
61326
62348
  setTimeout(() => {
61327
62349
  if (!incomingEnded) {
61328
62350
  setTimeout(() => {
61329
- incoming.destroy();
62351
+ drainIncoming(incoming);
61330
62352
  });
61331
62353
  }
61332
62354
  });