@langwatch/mcp-server 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/.python-version +1 -0
  2. package/CHANGELOG.md +21 -0
  3. package/CONTRIBUTING.md +1 -1
  4. package/README.md +55 -1
  5. package/dist/{archive-project-MK3673A7.js → archive-project-4EQGLBJJ.js} +5 -5
  6. package/dist/{archive-scenario-KATSXRIN.js → archive-scenario-W6BXYDZ3.js} +5 -5
  7. package/dist/{archive-suite-C3KX6IIZ.js → archive-suite-4T6BSRS7.js} +5 -5
  8. package/dist/{assign-prompt-tag-E3C5W6PI.js → assign-prompt-tag-VLXUWEKU.js} +4 -4
  9. package/dist/{chunk-VYPSKRPN.js → chunk-4QC7SA2L.js} +91 -91
  10. package/dist/{chunk-T7WJVS2N.js → chunk-5CCZFUXS.js} +2 -2
  11. package/dist/{chunk-J45SVWPR.js → chunk-77BNWQ3U.js} +2 -2
  12. package/dist/{chunk-XY4STOBE.js → chunk-7RHG56OH.js} +2 -2
  13. package/dist/{chunk-5UWY24RP.js → chunk-A2LEVYQ5.js} +2 -2
  14. package/dist/{chunk-UXXA4D6K.js → chunk-AQJO2EI5.js} +2 -2
  15. package/dist/{chunk-EU22L52K.js → chunk-CDYQOY5U.js} +2 -2
  16. package/dist/{chunk-O3LWVN67.js → chunk-J42FWRJ2.js} +2 -2
  17. package/dist/{chunk-BJ7B4R26.js → chunk-SAS5OB7F.js} +18 -2
  18. package/dist/{chunk-DAIQKS27.js → chunk-SFB4MU6H.js} +2 -2
  19. package/dist/{chunk-WWMDHZZV.js → chunk-TJCXFNDT.js} +2 -2
  20. package/dist/{chunk-CE6QMZOP.js → chunk-TOXJQDIZ.js} +4 -4
  21. package/dist/chunk-UJPXFA26.js +267 -0
  22. package/dist/{chunk-KOO5733S.js → chunk-WT4PO4A3.js} +8 -2
  23. package/dist/{chunk-RYRB2YVJ.js → chunk-YX3A3CFM.js} +2 -2
  24. package/dist/{chunk-WDH5P5RF.js → chunk-YZLYHLLI.js} +2 -2
  25. package/dist/{chunk-Y3HDZ6OW.js → chunk-ZWIL4EFL.js} +2 -2
  26. package/dist/config.js +2 -2
  27. package/dist/{create-agent-7W57J7MT.js → create-agent-7XHO6UIS.js} +5 -5
  28. package/dist/{create-annotation-W2XELBCQ.js → create-annotation-YQXRQC6A.js} +5 -5
  29. package/dist/{create-api-key-MKRXKFJM.js → create-api-key-YUS36KBU.js} +5 -5
  30. package/dist/{create-dashboard-QGL7IODC.js → create-dashboard-4Z5JO5LB.js} +5 -5
  31. package/dist/{create-dataset-3PH7A4HG.js → create-dataset-E6NMSVX7.js} +5 -5
  32. package/dist/{create-dataset-records-4DZS3VRL.js → create-dataset-records-SKHPRD2K.js} +5 -5
  33. package/dist/{create-evaluator-YWH6NC4M.js → create-evaluator-JXF5PF33.js} +5 -5
  34. package/dist/create-mcp-server.js +4 -4
  35. package/dist/{create-project-BOBQ32C5.js → create-project-CS2CB57Y.js} +5 -5
  36. package/dist/{create-prompt-FLCFGITE.js → create-prompt-F5RMX3L3.js} +4 -4
  37. package/dist/{create-prompt-tag-EMPNIKEA.js → create-prompt-tag-GMRWTEFR.js} +4 -4
  38. package/dist/{create-scenario-BSBIHUL6.js → create-scenario-JDR2VB2H.js} +5 -5
  39. package/dist/{create-suite-TWF6BBR4.js → create-suite-LZS6QIAF.js} +5 -5
  40. package/dist/{delete-agent-7MSYNY5E.js → delete-agent-O3EEH4S5.js} +5 -5
  41. package/dist/{delete-annotation-ZT5IGN24.js → delete-annotation-XP6FQM7A.js} +5 -5
  42. package/dist/{delete-dashboard-BTIY5S3L.js → delete-dashboard-RFUNYCNP.js} +5 -5
  43. package/dist/{delete-dataset-U45HQHPR.js → delete-dataset-3MJFRDLP.js} +5 -5
  44. package/dist/{delete-dataset-records-R43IMAWB.js → delete-dataset-records-WPMU5GL5.js} +5 -5
  45. package/dist/{delete-evaluator-U6JMQ6C7.js → delete-evaluator-33SP2JFX.js} +5 -5
  46. package/dist/{delete-prompt-tag-4EV4TDHB.js → delete-prompt-tag-KNMZVSPB.js} +4 -4
  47. package/dist/{delete-workflow-5QYALXEL.js → delete-workflow-3NUXO46U.js} +5 -5
  48. package/dist/{discover-evaluator-schema-MRGHVNTT.js → discover-evaluator-schema-XTAD4X7D.js} +52 -36
  49. package/dist/{discover-scenario-schema-UPBTCWPG.js → discover-scenario-schema-FE64QK2D.js} +2 -2
  50. package/dist/{discover-schema-ICGXPHUW.js → discover-schema-L6QDPON3.js} +2 -2
  51. package/dist/{get-agent-7QJVPH72.js → get-agent-Y7MWZ65F.js} +5 -5
  52. package/dist/{get-analytics-PVERWOA5.js → get-analytics-TETCSOK6.js} +4 -4
  53. package/dist/{get-dashboard-ZZPC3WMD.js → get-dashboard-KHBEGZGL.js} +5 -5
  54. package/dist/{get-dataset-25TB2LQH.js → get-dataset-RCMU5VAH.js} +5 -5
  55. package/dist/{get-evaluator-3FTRQKEC.js → get-evaluator-ADMKVWYZ.js} +5 -5
  56. package/dist/{get-project-5OAXYC57.js → get-project-RAK7URQJ.js} +5 -5
  57. package/dist/{get-prompt-I753LZKZ.js → get-prompt-OY5B7TRI.js} +4 -4
  58. package/dist/{get-scenario-DSSTR6FI.js → get-scenario-ZTAJJL5T.js} +5 -5
  59. package/dist/{get-simulation-run-RQPMS2MC.js → get-simulation-run-T2ZQWYH2.js} +5 -5
  60. package/dist/{get-suite-GTOCY5PL.js → get-suite-J7JVWO6O.js} +5 -5
  61. package/dist/{get-trace-O5VT3NAC.js → get-trace-K7U234Q4.js} +4 -4
  62. package/dist/{get-workflow-3EZDOEIF.js → get-workflow-L5L2PSK3.js} +5 -5
  63. package/dist/http-security-EU3CHTY7.js +26 -0
  64. package/dist/{http-server-2ACJ3CXW.js → http-server-YXHFPPGA.js} +1033 -693
  65. package/dist/index.js +3066 -2105
  66. package/dist/{langwatch-api-annotations-E65MI3WZ.js → langwatch-api-annotations-FDAS6NQ7.js} +5 -5
  67. package/dist/{langwatch-api-dashboards-QCDECRCY.js → langwatch-api-dashboards-JTVCS7ZJ.js} +5 -5
  68. package/dist/{langwatch-api-monitors-UIO2KTDV.js → langwatch-api-monitors-3J7UIQME.js} +4 -4
  69. package/dist/{langwatch-api-secrets-4T2EKSJ7.js → langwatch-api-secrets-BUBSNCNO.js} +4 -4
  70. package/dist/{langwatch-api-triggers-MPOEKPUY.js → langwatch-api-triggers-EDFUCJN6.js} +4 -4
  71. package/dist/langwatch-api-workflows-NBJX5KOG.js +16 -0
  72. package/dist/{list-agents-TIJTP566.js → list-agents-KFHKGPXV.js} +5 -5
  73. package/dist/{list-annotations-CGX5BT7E.js → list-annotations-ZTVP4EEL.js} +5 -5
  74. package/dist/{list-api-keys-JLWJPFRX.js → list-api-keys-CWD4UQT5.js} +5 -5
  75. package/dist/{list-dashboards-RNIWX3TX.js → list-dashboards-PWG6P6KR.js} +5 -5
  76. package/dist/{list-dataset-records-B5MHZR66.js → list-dataset-records-IOE7LQXS.js} +5 -5
  77. package/dist/{list-datasets-BVCAMQCP.js → list-datasets-ZT4JYUDT.js} +5 -5
  78. package/dist/{list-evaluators-65FBTL2U.js → list-evaluators-SJHC7VBH.js} +5 -5
  79. package/dist/{list-model-providers-GRK3I3VV.js → list-model-providers-PPD2WPD2.js} +5 -5
  80. package/dist/{list-projects-JLMBFMW3.js → list-projects-K7QAIX2I.js} +5 -5
  81. package/dist/{list-prompt-tags-UHNWDGQI.js → list-prompt-tags-FOO6TNHB.js} +4 -4
  82. package/dist/{list-prompts-7254B3U7.js → list-prompts-SC2HAUFG.js} +4 -4
  83. package/dist/{list-scenarios-46YNICKM.js → list-scenarios-F2WYNRIE.js} +5 -5
  84. package/dist/{list-simulation-runs-LGNEFNPN.js → list-simulation-runs-KF5THG5H.js} +5 -5
  85. package/dist/{list-suites-5VK4HXEK.js → list-suites-CRY4VWW6.js} +5 -5
  86. package/dist/{list-workflows-MLQDM6CP.js → list-workflows-QSJWURCK.js} +5 -5
  87. package/dist/{rename-prompt-tag-RHQMNEQL.js → rename-prompt-tag-EKWU5QF3.js} +4 -4
  88. package/dist/{report-issue-DXJ6TPTC.js → report-issue-XYVAPAYJ.js} +7 -7
  89. package/dist/{revoke-api-key-3Y35EMBT.js → revoke-api-key-FTRTZMOF.js} +5 -5
  90. package/dist/{run-agent-RBSIFKRT.js → run-agent-6SM4XNA7.js} +5 -5
  91. package/dist/{run-suite-K3DNQ3SE.js → run-suite-NKZCJ2IN.js} +5 -5
  92. package/dist/{run-workflow-5LVBZYLS.js → run-workflow-QPXC627O.js} +5 -5
  93. package/dist/{search-traces-U4HLOCZ2.js → search-traces-A6HFKPLJ.js} +4 -4
  94. package/dist/{set-model-provider-V3M5CDIY.js → set-model-provider-3WKT63ZN.js} +5 -5
  95. package/dist/{update-agent-47RZIHS7.js → update-agent-SMAEHLXH.js} +5 -5
  96. package/dist/{update-dataset-G6QJJGS5.js → update-dataset-BDUK7TUO.js} +5 -5
  97. package/dist/{update-dataset-record-RMWLSWCS.js → update-dataset-record-4ZSDRBSW.js} +5 -5
  98. package/dist/{update-evaluator-SFRRI5Q3.js → update-evaluator-LS6TIBY7.js} +5 -5
  99. package/dist/{update-project-PI5DWBVK.js → update-project-LKVYXENH.js} +5 -5
  100. package/dist/{update-prompt-RQFTEO7Y.js → update-prompt-ODCRQRN6.js} +4 -4
  101. package/dist/{update-scenario-G3IU2UIB.js → update-scenario-NEXCAQI7.js} +5 -5
  102. package/dist/{update-suite-TRGGLNR7.js → update-suite-SNO3GS7T.js} +5 -5
  103. package/package.json +3 -3
  104. package/pyproject.toml +1 -1
  105. package/src/__tests__/config.unit.test.ts +33 -0
  106. package/src/__tests__/docker.integration.test.ts +91 -7
  107. package/src/__tests__/documentation-fetch-security.integration.test.ts +8 -2
  108. package/src/__tests__/feature-map-tool-drift.unit.test.ts +93 -0
  109. package/src/__tests__/http-security-origin.unit.test.ts +97 -0
  110. package/src/__tests__/http-security-sessions.unit.test.ts +209 -0
  111. package/src/__tests__/http-security-verifier.unit.test.ts +248 -0
  112. package/src/__tests__/http-server-allocation.integration.test.ts +279 -0
  113. package/src/__tests__/http-server-origin.integration.test.ts +169 -0
  114. package/src/__tests__/http-server-session-auth.integration.test.ts +341 -0
  115. package/src/__tests__/http-transport.integration.test.ts +85 -87
  116. package/src/__tests__/support/http-server-harness.ts +138 -0
  117. package/src/config.ts +17 -2
  118. package/src/http-security.ts +492 -0
  119. package/src/http-server.ts +536 -152
  120. package/src/index.ts +49 -2
  121. package/src/tools/discover-evaluator-schema.ts +2 -2
  122. package/tsconfig.json +2 -2
  123. package/uv.lock +2 -2
  124. package/dist/langwatch-api-workflows-5HRZ7HR4.js +0 -16
  125. package/pnpm-workspace.yaml +0 -34
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  makeRequest
3
- } from "./chunk-5UWY24RP.js";
3
+ } from "./chunk-A2LEVYQ5.js";
4
4
 
5
5
  // src/langwatch-api-workflows.ts
6
6
  async function listWorkflows() {
@@ -32,4 +32,4 @@ export {
32
32
  runWorkflow,
33
33
  deleteWorkflow
34
34
  };
35
- //# sourceMappingURL=chunk-T7WJVS2N.js.map
35
+ //# sourceMappingURL=chunk-5CCZFUXS.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  makeRequest
3
- } from "./chunk-5UWY24RP.js";
3
+ } from "./chunk-A2LEVYQ5.js";
4
4
 
5
5
  // src/langwatch-api-datasets.ts
6
6
  async function listDatasets(params) {
@@ -83,4 +83,4 @@ export {
83
83
  deleteDatasetRecords,
84
84
  listDatasetRecords
85
85
  };
86
- //# sourceMappingURL=chunk-J45SVWPR.js.map
86
+ //# sourceMappingURL=chunk-77BNWQ3U.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  makeRequest
3
- } from "./chunk-5UWY24RP.js";
3
+ } from "./chunk-A2LEVYQ5.js";
4
4
 
5
5
  // src/langwatch-api-projects.ts
6
6
  async function listProjects(params) {
@@ -41,4 +41,4 @@ export {
41
41
  updateProject,
42
42
  archiveProject
43
43
  };
44
- //# sourceMappingURL=chunk-XY4STOBE.js.map
44
+ //# sourceMappingURL=chunk-7RHG56OH.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  getConfig,
3
3
  requireApiKey
4
- } from "./chunk-KOO5733S.js";
4
+ } from "./chunk-WT4PO4A3.js";
5
5
 
6
6
  // src/langwatch-api.ts
7
7
  var LangWatchApiError = class extends Error {
@@ -214,4 +214,4 @@ export {
214
214
  renamePromptTag,
215
215
  deletePromptTag
216
216
  };
217
- //# sourceMappingURL=chunk-5UWY24RP.js.map
217
+ //# sourceMappingURL=chunk-A2LEVYQ5.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  makeRequest
3
- } from "./chunk-5UWY24RP.js";
3
+ } from "./chunk-A2LEVYQ5.js";
4
4
 
5
5
  // src/langwatch-api-dashboards.ts
6
6
  async function listDashboards() {
@@ -36,4 +36,4 @@ export {
36
36
  renameDashboard,
37
37
  deleteDashboard
38
38
  };
39
- //# sourceMappingURL=chunk-UXXA4D6K.js.map
39
+ //# sourceMappingURL=chunk-AQJO2EI5.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  makeRequest
3
- } from "./chunk-5UWY24RP.js";
3
+ } from "./chunk-A2LEVYQ5.js";
4
4
 
5
5
  // src/langwatch-api-evaluators.ts
6
6
  function getEvaluatorType(evaluator) {
@@ -41,4 +41,4 @@ export {
41
41
  updateEvaluator,
42
42
  deleteEvaluator
43
43
  };
44
- //# sourceMappingURL=chunk-EU22L52K.js.map
44
+ //# sourceMappingURL=chunk-CDYQOY5U.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  makeRequest
3
- } from "./chunk-5UWY24RP.js";
3
+ } from "./chunk-A2LEVYQ5.js";
4
4
 
5
5
  // src/langwatch-api-scenarios.ts
6
6
  async function listScenarios() {
@@ -37,4 +37,4 @@ export {
37
37
  updateScenario,
38
38
  archiveScenario
39
39
  };
40
- //# sourceMappingURL=chunk-O3LWVN67.js.map
40
+ //# sourceMappingURL=chunk-J42FWRJ2.js.map
@@ -10,6 +10,14 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
10
10
  if (typeof require !== "undefined") return require.apply(this, arguments);
11
11
  throw Error('Dynamic require of "' + x + '" is not supported');
12
12
  });
13
+ var __esm = (fn, res, err) => function __init() {
14
+ if (err) throw err[0];
15
+ try {
16
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
17
+ } catch (e) {
18
+ throw err = [e], e;
19
+ }
20
+ };
13
21
  var __commonJS = (cb, mod) => function __require2() {
14
22
  try {
15
23
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
@@ -17,6 +25,10 @@ var __commonJS = (cb, mod) => function __require2() {
17
25
  throw mod = 0, e;
18
26
  }
19
27
  };
28
+ var __export = (target, all) => {
29
+ for (var name in all)
30
+ __defProp(target, name, { get: all[name], enumerable: true });
31
+ };
20
32
  var __copyProps = (to, from, except, desc) => {
21
33
  if (from && typeof from === "object" || typeof from === "function") {
22
34
  for (let key of __getOwnPropNames(from))
@@ -33,10 +45,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
33
45
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
34
46
  mod
35
47
  ));
48
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
36
49
 
37
50
  export {
38
51
  __require,
52
+ __esm,
39
53
  __commonJS,
40
- __toESM
54
+ __export,
55
+ __toESM,
56
+ __toCommonJS
41
57
  };
42
- //# sourceMappingURL=chunk-BJ7B4R26.js.map
58
+ //# sourceMappingURL=chunk-SAS5OB7F.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  makeRequest
3
- } from "./chunk-5UWY24RP.js";
3
+ } from "./chunk-A2LEVYQ5.js";
4
4
 
5
5
  // src/langwatch-api-model-providers.ts
6
6
  async function listModelProviders() {
@@ -19,4 +19,4 @@ export {
19
19
  listModelProviders,
20
20
  setModelProvider
21
21
  };
22
- //# sourceMappingURL=chunk-DAIQKS27.js.map
22
+ //# sourceMappingURL=chunk-SFB4MU6H.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  makeRequest
3
- } from "./chunk-5UWY24RP.js";
3
+ } from "./chunk-A2LEVYQ5.js";
4
4
 
5
5
  // src/langwatch-api-api-keys.ts
6
6
  async function listApiKeys() {
@@ -21,4 +21,4 @@ export {
21
21
  createApiKey,
22
22
  revokeApiKey
23
23
  };
24
- //# sourceMappingURL=chunk-WWMDHZZV.js.map
24
+ //# sourceMappingURL=chunk-TJCXFNDT.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  makeRequest
3
- } from "./chunk-5UWY24RP.js";
3
+ } from "./chunk-A2LEVYQ5.js";
4
4
 
5
5
  // src/public-http-request.ts
6
6
  import { lookup as dnsLookup } from "dns/promises";
@@ -8,7 +8,7 @@ import { request as httpRequest } from "http";
8
8
  import { request as httpsRequest } from "https";
9
9
  import { isIP } from "net";
10
10
 
11
- // ../langwatch/packages/ssrf/src/index.ts
11
+ // ../../packages/ssrf/src/index.ts
12
12
  function ipv4ToBytes(input) {
13
13
  const parts = input.split(".");
14
14
  if (parts.length !== 4) return null;
@@ -410,7 +410,7 @@ async function runAgent(id, input) {
410
410
  `Agent "${agent.name}" (type: ${agent.type}) cannot be executed directly. Only HTTP agents and workflow-linked agents can be run.`
411
411
  );
412
412
  }
413
- const { runWorkflow } = await import("./langwatch-api-workflows-5HRZ7HR4.js");
413
+ const { runWorkflow } = await import("./langwatch-api-workflows-NBJX5KOG.js");
414
414
  const result = await runWorkflow(workflowId, input);
415
415
  return { agentType: agent.type, result };
416
416
  }
@@ -429,4 +429,4 @@ export {
429
429
  runAgent,
430
430
  deleteAgent
431
431
  };
432
- //# sourceMappingURL=chunk-CE6QMZOP.js.map
432
+ //# sourceMappingURL=chunk-TOXJQDIZ.js.map
@@ -0,0 +1,267 @@
1
+ // src/http-security.ts
2
+ import { createHmac, randomBytes, timingSafeEqual } from "crypto";
3
+ var DEFAULT_BIND_HOST = "127.0.0.1";
4
+ var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["127.0.0.1", "::1", "localhost"]);
5
+ function stripBrackets(host) {
6
+ return host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host;
7
+ }
8
+ function isLoopbackHost(host) {
9
+ return LOOPBACK_HOSTS.has(stripBrackets(host.trim().toLowerCase()));
10
+ }
11
+ var ALWAYS_ALLOWED_ORIGIN_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "::1"]);
12
+ function normalizeOrigin(origin) {
13
+ let parsed;
14
+ try {
15
+ parsed = new URL(origin.trim());
16
+ } catch {
17
+ return null;
18
+ }
19
+ if (parsed.origin === "null") return null;
20
+ return {
21
+ origin: parsed.origin,
22
+ hostname: stripBrackets(parsed.hostname.toLowerCase())
23
+ };
24
+ }
25
+ function parseAllowedOrigins(raw) {
26
+ if (!raw) return [];
27
+ const parsed = raw.split(",").map((entry) => normalizeOrigin(entry)?.origin).filter((entry) => entry !== void 0);
28
+ return [...new Set(parsed)];
29
+ }
30
+ function isOriginAllowed({
31
+ origin,
32
+ allowedOrigins
33
+ }) {
34
+ const normalized = normalizeOrigin(origin);
35
+ if (!normalized) return false;
36
+ if (ALWAYS_ALLOWED_ORIGIN_HOSTS.has(normalized.hostname)) return true;
37
+ return allowedOrigins.includes(normalized.origin);
38
+ }
39
+ var KEY_DERIVATION_SECRET = randomBytes(32);
40
+ function hashApiKey(apiKey) {
41
+ return createHmac("sha256", KEY_DERIVATION_SECRET).update(apiKey).digest("hex");
42
+ }
43
+ function apiKeysMatch({
44
+ presentedKey,
45
+ expectedKey
46
+ }) {
47
+ const presented = createHmac("sha256", KEY_DERIVATION_SECRET).update(presentedKey).digest();
48
+ const expected = createHmac("sha256", KEY_DERIVATION_SECRET).update(expectedKey).digest();
49
+ return timingSafeEqual(presented, expected);
50
+ }
51
+ function createRateLimiter({
52
+ windowMs,
53
+ maxRequests
54
+ }) {
55
+ const entries = /* @__PURE__ */ new Map();
56
+ return {
57
+ isBlocked(ip) {
58
+ const entry = entries.get(ip);
59
+ if (!entry || Date.now() - entry.windowStart > windowMs) return false;
60
+ return entry.count >= maxRequests;
61
+ },
62
+ track(ip) {
63
+ const now = Date.now();
64
+ const entry = entries.get(ip);
65
+ if (!entry || now - entry.windowStart > windowMs) {
66
+ entries.set(ip, { count: 1, windowStart: now });
67
+ } else {
68
+ entry.count++;
69
+ }
70
+ },
71
+ sweep() {
72
+ const now = Date.now();
73
+ for (const [ip, entry] of entries) {
74
+ if (now - entry.windowStart > windowMs) entries.delete(ip);
75
+ }
76
+ },
77
+ clear() {
78
+ entries.clear();
79
+ }
80
+ };
81
+ }
82
+ var VERIFY_PATH = "/api/me/project";
83
+ function createApiKeyVerifier({
84
+ endpoint,
85
+ positiveTtlMs = 6e4,
86
+ negativeTtlMs = 3e4,
87
+ maxEntries = 1e4,
88
+ requestTimeoutMs = 5e3,
89
+ fetchImpl = fetch
90
+ }) {
91
+ const cache = /* @__PURE__ */ new Map();
92
+ const inFlight = /* @__PURE__ */ new Map();
93
+ function sweep() {
94
+ const now = Date.now();
95
+ for (const [key, entry] of cache) {
96
+ if (now >= entry.expiresAt) cache.delete(key);
97
+ }
98
+ }
99
+ function remember(hashed, valid) {
100
+ if (cache.size >= maxEntries) {
101
+ sweep();
102
+ while (cache.size >= maxEntries) {
103
+ const oldest = cache.keys().next();
104
+ if (oldest.done) break;
105
+ cache.delete(oldest.value);
106
+ }
107
+ }
108
+ cache.set(hashed, {
109
+ valid,
110
+ expiresAt: Date.now() + (valid ? positiveTtlMs : negativeTtlMs)
111
+ });
112
+ }
113
+ async function askApi(apiKey) {
114
+ let response;
115
+ try {
116
+ response = await fetchImpl(`${endpoint}${VERIFY_PATH}`, {
117
+ method: "GET",
118
+ headers: { "X-Auth-Token": apiKey },
119
+ // An upstream that accepts the connection and never answers would
120
+ // otherwise leave the in-flight promise unsettled, parking every
121
+ // request for this key behind it until the socket dies.
122
+ signal: AbortSignal.timeout(requestTimeoutMs)
123
+ });
124
+ } catch {
125
+ return null;
126
+ }
127
+ await response.body?.cancel().catch(() => void 0);
128
+ if (response.ok) return true;
129
+ if (response.status === 401 || response.status === 403) return false;
130
+ return null;
131
+ }
132
+ return {
133
+ async verify(apiKey) {
134
+ const hashed = hashApiKey(apiKey);
135
+ const cached = cache.get(hashed);
136
+ if (cached && Date.now() < cached.expiresAt) return cached.valid;
137
+ const pending = inFlight.get(hashed);
138
+ if (pending) return pending;
139
+ const request = askApi(apiKey).then((result) => {
140
+ if (result !== null) remember(hashed, result);
141
+ return result === true;
142
+ }).finally(() => {
143
+ inFlight.delete(hashed);
144
+ });
145
+ inFlight.set(hashed, request);
146
+ return request;
147
+ },
148
+ sweep,
149
+ clear() {
150
+ cache.clear();
151
+ inFlight.clear();
152
+ }
153
+ };
154
+ }
155
+ function createSessionStore({
156
+ maxAgeMs,
157
+ closeTransport
158
+ }) {
159
+ const sessions = /* @__PURE__ */ new Map();
160
+ const countByKey = /* @__PURE__ */ new Map();
161
+ function decrement(apiKey) {
162
+ const hashed = hashApiKey(apiKey);
163
+ const next = (countByKey.get(hashed) ?? 1) - 1;
164
+ if (next <= 0) countByKey.delete(hashed);
165
+ else countByKey.set(hashed, next);
166
+ }
167
+ function drop(sessionId, record) {
168
+ sessions.delete(sessionId);
169
+ decrement(record.apiKey);
170
+ }
171
+ function reserve(apiKey) {
172
+ const hashed = hashApiKey(apiKey);
173
+ countByKey.set(hashed, (countByKey.get(hashed) ?? 0) + 1);
174
+ let settled = false;
175
+ return {
176
+ commit({ sessionId, transport }) {
177
+ if (settled) return;
178
+ settled = true;
179
+ const existing = sessions.get(sessionId);
180
+ if (existing) drop(sessionId, existing);
181
+ sessions.set(sessionId, {
182
+ transport,
183
+ apiKey,
184
+ lastActivityAt: Date.now()
185
+ });
186
+ },
187
+ release() {
188
+ if (settled) return;
189
+ settled = true;
190
+ decrement(apiKey);
191
+ }
192
+ };
193
+ }
194
+ return {
195
+ get(sessionId) {
196
+ return sessions.get(sessionId);
197
+ },
198
+ reserve,
199
+ add({ sessionId, transport, apiKey }) {
200
+ reserve(apiKey).commit({ sessionId, transport });
201
+ },
202
+ touch(sessionId) {
203
+ const record = sessions.get(sessionId);
204
+ if (record) record.lastActivityAt = Date.now();
205
+ },
206
+ remove(sessionId) {
207
+ const record = sessions.get(sessionId);
208
+ if (record) drop(sessionId, record);
209
+ },
210
+ countForKey(apiKey) {
211
+ return countByKey.get(hashApiKey(apiKey)) ?? 0;
212
+ },
213
+ sweep() {
214
+ const now = Date.now();
215
+ for (const [sessionId, record] of sessions) {
216
+ if (now - record.lastActivityAt > maxAgeMs) {
217
+ drop(sessionId, record);
218
+ closeTransport(record.transport);
219
+ }
220
+ }
221
+ },
222
+ closeAll() {
223
+ for (const [sessionId, record] of sessions) {
224
+ drop(sessionId, record);
225
+ closeTransport(record.transport);
226
+ }
227
+ },
228
+ get size() {
229
+ return sessions.size;
230
+ }
231
+ };
232
+ }
233
+ function admitOAuthToken({
234
+ apiKey,
235
+ tokens,
236
+ maxPerKey
237
+ }) {
238
+ const now = Date.now();
239
+ const held = [];
240
+ for (const [token, entry] of tokens) {
241
+ if (now >= entry.expiresAt) {
242
+ tokens.delete(token);
243
+ continue;
244
+ }
245
+ if (entry.apiKey === apiKey) {
246
+ held.push({ token, expiresAt: entry.expiresAt });
247
+ }
248
+ }
249
+ held.sort((a, b) => a.expiresAt - b.expiresAt);
250
+ for (let i = 0; i <= held.length - maxPerKey; i += 1) {
251
+ tokens.delete(held[i].token);
252
+ }
253
+ }
254
+
255
+ export {
256
+ DEFAULT_BIND_HOST,
257
+ isLoopbackHost,
258
+ parseAllowedOrigins,
259
+ isOriginAllowed,
260
+ hashApiKey,
261
+ apiKeysMatch,
262
+ createRateLimiter,
263
+ createApiKeyVerifier,
264
+ createSessionStore,
265
+ admitOAuthToken
266
+ };
267
+ //# sourceMappingURL=chunk-UJPXFA26.js.map
@@ -22,11 +22,17 @@ function getGlobalState() {
22
22
  }
23
23
  };
24
24
  }
25
+ function normalizeEndpoint(endpoint) {
26
+ const trimmed = endpoint.trim();
27
+ let end = trimmed.length;
28
+ while (end > 0 && trimmed[end - 1] === "/") end--;
29
+ return trimmed.slice(0, end);
30
+ }
25
31
  function initConfig(args) {
26
32
  const state = getGlobalState();
27
33
  state.globalConfig = {
28
34
  apiKey: args.apiKey || process.env.LANGWATCH_API_KEY,
29
- endpoint: args.endpoint || process.env.LANGWATCH_ENDPOINT || "https://app.langwatch.ai",
35
+ endpoint: normalizeEndpoint(args.endpoint ?? "") || normalizeEndpoint(process.env.LANGWATCH_ENDPOINT ?? "") || "https://app.langwatch.ai",
30
36
  projectId: process.env.LANGWATCH_PROJECT_ID
31
37
  };
32
38
  }
@@ -69,4 +75,4 @@ export {
69
75
  requireApiKey,
70
76
  runWithConfig
71
77
  };
72
- //# sourceMappingURL=chunk-KOO5733S.js.map
78
+ //# sourceMappingURL=chunk-WT4PO4A3.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  makeRequest
3
- } from "./chunk-5UWY24RP.js";
3
+ } from "./chunk-A2LEVYQ5.js";
4
4
 
5
5
  // src/langwatch-api-annotations.ts
6
6
  async function listAnnotations() {
@@ -39,4 +39,4 @@ export {
39
39
  createAnnotation,
40
40
  deleteAnnotation
41
41
  };
42
- //# sourceMappingURL=chunk-RYRB2YVJ.js.map
42
+ //# sourceMappingURL=chunk-YX3A3CFM.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  makeRequest
3
- } from "./chunk-5UWY24RP.js";
3
+ } from "./chunk-A2LEVYQ5.js";
4
4
 
5
5
  // src/langwatch-api-suites.ts
6
6
  async function listSuites() {
@@ -45,4 +45,4 @@ export {
45
45
  runSuite,
46
46
  archiveSuite
47
47
  };
48
- //# sourceMappingURL=chunk-WDH5P5RF.js.map
48
+ //# sourceMappingURL=chunk-YZLYHLLI.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  makeRequest
3
- } from "./chunk-5UWY24RP.js";
3
+ } from "./chunk-A2LEVYQ5.js";
4
4
 
5
5
  // src/langwatch-api-simulation-runs.ts
6
6
  async function listSimulationRuns(params) {
@@ -22,4 +22,4 @@ export {
22
22
  listSimulationRuns,
23
23
  getSimulationRun
24
24
  };
25
- //# sourceMappingURL=chunk-Y3HDZ6OW.js.map
25
+ //# sourceMappingURL=chunk-ZWIL4EFL.js.map
package/dist/config.js CHANGED
@@ -3,8 +3,8 @@ import {
3
3
  initConfig,
4
4
  requireApiKey,
5
5
  runWithConfig
6
- } from "./chunk-KOO5733S.js";
7
- import "./chunk-BJ7B4R26.js";
6
+ } from "./chunk-WT4PO4A3.js";
7
+ import "./chunk-SAS5OB7F.js";
8
8
  export {
9
9
  getConfig,
10
10
  initConfig,
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  createAgent
3
- } from "./chunk-CE6QMZOP.js";
4
- import "./chunk-5UWY24RP.js";
5
- import "./chunk-KOO5733S.js";
6
- import "./chunk-BJ7B4R26.js";
3
+ } from "./chunk-TOXJQDIZ.js";
4
+ import "./chunk-A2LEVYQ5.js";
5
+ import "./chunk-WT4PO4A3.js";
6
+ import "./chunk-SAS5OB7F.js";
7
7
 
8
8
  // src/tools/create-agent.ts
9
9
  async function handleCreateAgent(params) {
@@ -21,4 +21,4 @@ async function handleCreateAgent(params) {
21
21
  export {
22
22
  handleCreateAgent
23
23
  };
24
- //# sourceMappingURL=create-agent-7W57J7MT.js.map
24
+ //# sourceMappingURL=create-agent-7XHO6UIS.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  createAnnotation
3
- } from "./chunk-RYRB2YVJ.js";
4
- import "./chunk-5UWY24RP.js";
5
- import "./chunk-KOO5733S.js";
6
- import "./chunk-BJ7B4R26.js";
3
+ } from "./chunk-YX3A3CFM.js";
4
+ import "./chunk-A2LEVYQ5.js";
5
+ import "./chunk-WT4PO4A3.js";
6
+ import "./chunk-SAS5OB7F.js";
7
7
 
8
8
  // src/tools/create-annotation.ts
9
9
  async function handleCreateAnnotation(params) {
@@ -22,4 +22,4 @@ async function handleCreateAnnotation(params) {
22
22
  export {
23
23
  handleCreateAnnotation
24
24
  };
25
- //# sourceMappingURL=create-annotation-W2XELBCQ.js.map
25
+ //# sourceMappingURL=create-annotation-YQXRQC6A.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  createApiKey
3
- } from "./chunk-WWMDHZZV.js";
4
- import "./chunk-5UWY24RP.js";
5
- import "./chunk-KOO5733S.js";
6
- import "./chunk-BJ7B4R26.js";
3
+ } from "./chunk-TJCXFNDT.js";
4
+ import "./chunk-A2LEVYQ5.js";
5
+ import "./chunk-WT4PO4A3.js";
6
+ import "./chunk-SAS5OB7F.js";
7
7
 
8
8
  // src/tools/create-api-key.ts
9
9
  async function handleCreateApiKey(params) {
@@ -24,4 +24,4 @@ async function handleCreateApiKey(params) {
24
24
  export {
25
25
  handleCreateApiKey
26
26
  };
27
- //# sourceMappingURL=create-api-key-MKRXKFJM.js.map
27
+ //# sourceMappingURL=create-api-key-YUS36KBU.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  createDashboard
3
- } from "./chunk-UXXA4D6K.js";
4
- import "./chunk-5UWY24RP.js";
5
- import "./chunk-KOO5733S.js";
6
- import "./chunk-BJ7B4R26.js";
3
+ } from "./chunk-AQJO2EI5.js";
4
+ import "./chunk-A2LEVYQ5.js";
5
+ import "./chunk-WT4PO4A3.js";
6
+ import "./chunk-SAS5OB7F.js";
7
7
 
8
8
  // src/tools/create-dashboard.ts
9
9
  async function handleCreateDashboard(params) {
@@ -16,4 +16,4 @@ async function handleCreateDashboard(params) {
16
16
  export {
17
17
  handleCreateDashboard
18
18
  };
19
- //# sourceMappingURL=create-dashboard-QGL7IODC.js.map
19
+ //# sourceMappingURL=create-dashboard-4Z5JO5LB.js.map
@@ -4,10 +4,10 @@ import {
4
4
  import "./chunk-NUFPTHKU.js";
5
5
  import {
6
6
  createDataset
7
- } from "./chunk-J45SVWPR.js";
8
- import "./chunk-5UWY24RP.js";
9
- import "./chunk-KOO5733S.js";
10
- import "./chunk-BJ7B4R26.js";
7
+ } from "./chunk-77BNWQ3U.js";
8
+ import "./chunk-A2LEVYQ5.js";
9
+ import "./chunk-WT4PO4A3.js";
10
+ import "./chunk-SAS5OB7F.js";
11
11
 
12
12
  // src/tools/create-dataset.ts
13
13
  async function handleCreateDataset(params) {
@@ -20,4 +20,4 @@ async function handleCreateDataset(params) {
20
20
  export {
21
21
  handleCreateDataset
22
22
  };
23
- //# sourceMappingURL=create-dataset-3PH7A4HG.js.map
23
+ //# sourceMappingURL=create-dataset-E6NMSVX7.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  createDatasetRecords
3
- } from "./chunk-J45SVWPR.js";
4
- import "./chunk-5UWY24RP.js";
5
- import "./chunk-KOO5733S.js";
6
- import "./chunk-BJ7B4R26.js";
3
+ } from "./chunk-77BNWQ3U.js";
4
+ import "./chunk-A2LEVYQ5.js";
5
+ import "./chunk-WT4PO4A3.js";
6
+ import "./chunk-SAS5OB7F.js";
7
7
 
8
8
  // src/tools/create-dataset-records.ts
9
9
  async function handleCreateDatasetRecords(params) {
@@ -20,4 +20,4 @@ async function handleCreateDatasetRecords(params) {
20
20
  export {
21
21
  handleCreateDatasetRecords
22
22
  };
23
- //# sourceMappingURL=create-dataset-records-4DZS3VRL.js.map
23
+ //# sourceMappingURL=create-dataset-records-SKHPRD2K.js.map