@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.
- package/.release-please-shim +1 -0
- package/CHANGELOG.md +87 -0
- package/LICENSE +7 -0
- package/dist/archive-project-HZBRPR2S.js +19 -0
- package/dist/{archive-scenario-WJ2A7ETN.js → archive-scenario-P5RRITRM.js} +4 -4
- package/dist/{archive-suite-4JOM4SSL.js → archive-suite-NUUFD2EM.js} +4 -4
- package/dist/{assign-prompt-tag-GL7EAAF3.js → assign-prompt-tag-FKCCZPML.js} +3 -3
- package/dist/{chunk-2WPLXEKF.js → chunk-42ZHHHIJ.js} +20 -5
- package/dist/chunk-ADSJ2FDA.js +44 -0
- package/dist/{chunk-IE4M5OGE.js → chunk-BB7EOKHR.js} +2 -2
- package/dist/chunk-BBJ5WAJB.js +24 -0
- package/dist/{chunk-EGH5RPXM.js → chunk-BYWYM2RP.js} +2 -2
- package/dist/{chunk-2GT7IFWK.js → chunk-CCM4ZFGF.js} +2 -2
- package/dist/{chunk-LUMEZEHL.js → chunk-CHKCEZBP.js} +2 -2
- package/dist/{chunk-ZVS4UKN2.js → chunk-HKY3GW45.js} +2 -2
- package/dist/{chunk-EUQDVOSU.js → chunk-JHOSVOHT.js} +2 -2
- package/dist/{chunk-E5JYYU3J.js → chunk-JVLJKQJG.js} +669 -94
- package/dist/{chunk-BWWY5KEF.js → chunk-KOO5733S.js} +3 -2
- package/dist/{chunk-HYMIWO3U.js → chunk-R7C7OUVG.js} +2 -2
- package/dist/{chunk-WQG2DFHX.js → chunk-TROIWSEQ.js} +2 -2
- package/dist/{chunk-CCWCIJJ3.js → chunk-X2SEURT2.js} +2 -2
- package/dist/{chunk-4AUB2BIA.js → chunk-XC62KJIT.js} +3 -3
- package/dist/config.js +1 -1
- package/dist/{create-agent-MBOOT3XK.js → create-agent-K5Q7BFGZ.js} +4 -4
- package/dist/{create-annotation-XMV6A7ED.js → create-annotation-KN3GE3DK.js} +4 -4
- package/dist/create-api-key-OQI5PUNQ.js +26 -0
- package/dist/{create-dashboard-VRKLFVZJ.js → create-dashboard-G4QA5AXP.js} +4 -4
- package/dist/{create-dataset-7HQPZCRE.js → create-dataset-WQSC37N7.js} +4 -4
- package/dist/{create-dataset-records-2NIVFYTV.js → create-dataset-records-B4RL3FLC.js} +4 -4
- package/dist/{create-evaluator-WYFRFLRC.js → create-evaluator-YFFQIR7E.js} +4 -4
- package/dist/create-mcp-server.js +3 -2
- package/dist/create-project-CUVQ67VN.js +44 -0
- package/dist/{create-prompt-IEN7O6JT.js → create-prompt-NGXKSP4X.js} +3 -3
- package/dist/{create-prompt-tag-CAEZ45VO.js → create-prompt-tag-IUKYPVHH.js} +3 -3
- package/dist/{create-scenario-6YHSMGLP.js → create-scenario-FNBXALH3.js} +4 -4
- package/dist/{create-suite-H5XOFDE5.js → create-suite-DJEPD4ZB.js} +4 -4
- package/dist/{delete-agent-JKTNBWAA.js → delete-agent-TJI5XBBM.js} +4 -4
- package/dist/{delete-annotation-ACMDV6QO.js → delete-annotation-KRP53TUU.js} +4 -4
- package/dist/{delete-dashboard-VJSR7CRU.js → delete-dashboard-N5SZJIR3.js} +4 -4
- package/dist/{delete-dataset-RTTTWP4D.js → delete-dataset-KDUOHL2P.js} +4 -4
- package/dist/{delete-dataset-records-KNQTIPQK.js → delete-dataset-records-DM4W3PAW.js} +4 -4
- package/dist/{delete-evaluator-7FVC5WM4.js → delete-evaluator-7ZATLJOA.js} +4 -4
- package/dist/{delete-prompt-tag-ZMZUAGFW.js → delete-prompt-tag-I6HNMSVJ.js} +3 -3
- package/dist/{delete-workflow-EYQ3T4RQ.js → delete-workflow-QEO74JQR.js} +4 -4
- package/dist/{get-agent-E3QSTVKG.js → get-agent-3KDWCP5N.js} +4 -4
- package/dist/{get-analytics-2OHV763I.js → get-analytics-GPVJX7SF.js} +3 -3
- package/dist/{get-dashboard-PC7JDHH6.js → get-dashboard-YPTIE5YY.js} +4 -4
- package/dist/{get-dataset-H5IK5FVU.js → get-dataset-6DQFYITM.js} +4 -4
- package/dist/{get-evaluator-UWVUPYTM.js → get-evaluator-PCM6XQAU.js} +4 -4
- package/dist/get-project-JCMWXVLU.js +26 -0
- package/dist/{get-prompt-WZUOLLQC.js → get-prompt-5XAGWWBG.js} +3 -3
- package/dist/{get-scenario-Q6LCNUYN.js → get-scenario-7XBCDZWX.js} +4 -4
- package/dist/{get-simulation-run-Z2XKO256.js → get-simulation-run-AV24FJWI.js} +4 -4
- package/dist/{get-suite-BXK5TN7P.js → get-suite-4DBVHFEM.js} +4 -4
- package/dist/{get-trace-4EJAYVBG.js → get-trace-MRBDS3HJ.js} +3 -3
- package/dist/{get-workflow-O34QJLHD.js → get-workflow-UR4Y6UFX.js} +4 -4
- package/dist/{http-server-ISHF7NJX.js → http-server-DEGNV5EP.js} +4 -3
- package/dist/index.js +1453 -431
- package/dist/{langwatch-api-annotations-ERBG27RF.js → langwatch-api-annotations-ZJDRB4JH.js} +4 -4
- package/dist/{langwatch-api-dashboards-G6TR7VVO.js → langwatch-api-dashboards-WARLI6NF.js} +4 -4
- package/dist/{langwatch-api-monitors-WSXZLS2B.js → langwatch-api-monitors-4XKXHYCG.js} +3 -3
- package/dist/{langwatch-api-secrets-RR5DKG2X.js → langwatch-api-secrets-6SHK5G7Q.js} +3 -3
- package/dist/{langwatch-api-triggers-2RTNSWQY.js → langwatch-api-triggers-5SX6R2WU.js} +3 -3
- package/dist/langwatch-api-workflows-NLJENNXE.js +15 -0
- package/dist/{list-agents-AW3P6FJV.js → list-agents-NECO7MPI.js} +4 -4
- package/dist/{list-annotations-QNCGWPQ3.js → list-annotations-3OJEO774.js} +4 -4
- package/dist/list-api-keys-AWW7ROLB.js +37 -0
- package/dist/{list-dashboards-R7RK2IXL.js → list-dashboards-DVPVVVKW.js} +4 -4
- package/dist/{list-dataset-records-WVCSQP7P.js → list-dataset-records-I4BYORF5.js} +4 -4
- package/dist/{list-datasets-KEXRLDEU.js → list-datasets-WUAE5HGX.js} +4 -4
- package/dist/{list-evaluators-7R2LB4JH.js → list-evaluators-B6OSVAM2.js} +4 -4
- package/dist/{list-model-providers-OBYJCKBX.js → list-model-providers-NL6IP4UZ.js} +4 -4
- package/dist/list-projects-5FHMJ4PQ.js +42 -0
- package/dist/{list-prompt-tags-6LY3ZPYI.js → list-prompt-tags-Z2DD6FLQ.js} +3 -3
- package/dist/{list-prompts-VWEZ4CDE.js → list-prompts-VNXKHK7T.js} +3 -3
- package/dist/{list-scenarios-TXD4W2ZJ.js → list-scenarios-CFZHXL76.js} +4 -4
- package/dist/{list-simulation-runs-RHPOLMFI.js → list-simulation-runs-AM2BXLBW.js} +4 -4
- package/dist/{list-suites-FSGBX27Z.js → list-suites-ZDOHAAXF.js} +4 -4
- package/dist/{list-workflows-VRGEZ3EN.js → list-workflows-WBRBKLIT.js} +4 -4
- package/dist/{rename-prompt-tag-VOJJLX4M.js → rename-prompt-tag-A4RJUK7Z.js} +3 -3
- package/dist/revoke-api-key-ZSPSPF5G.js +15 -0
- package/dist/{run-agent-KTCC7TB7.js → run-agent-JFNDY7MR.js} +4 -4
- package/dist/{run-suite-BTMHGI2D.js → run-suite-TH7LO5TJ.js} +4 -4
- package/dist/{run-workflow-IGAYGKJL.js → run-workflow-CK3JP5U2.js} +4 -4
- package/dist/{search-traces-VYFUIMXH.js → search-traces-3BBVYPC3.js} +3 -3
- package/dist/{set-model-provider-W5IUI326.js → set-model-provider-WOC5FNMV.js} +4 -4
- package/dist/{update-agent-4BB7EYLR.js → update-agent-YMEV5MTL.js} +4 -4
- package/dist/{update-dataset-CXBKZ4W3.js → update-dataset-EYT5POFM.js} +4 -4
- package/dist/{update-dataset-record-HOHAMHXG.js → update-dataset-record-VFF5JTX4.js} +4 -4
- package/dist/{update-evaluator-IVOR6FTR.js → update-evaluator-6IJHFG2E.js} +4 -4
- package/dist/update-project-OIT4WPFI.js +24 -0
- package/dist/{update-prompt-OWQAKE7K.js → update-prompt-ZU2DD6KM.js} +3 -3
- package/dist/{update-scenario-GDFVILPN.js → update-scenario-3VUTPDRU.js} +4 -4
- package/dist/{update-suite-BXYUYSPT.js → update-suite-C6JFDQHL.js} +4 -4
- package/package.json +7 -7
- package/pnpm-workspace.yaml +2 -0
- package/pyproject.toml +3 -0
- package/src/__tests__/all-tools.integration.test.ts +9 -0
- package/src/__tests__/datasets.integration.test.ts +17 -0
- package/src/__tests__/datasets.unit.test.ts +4 -0
- package/src/__tests__/experiment-list-tools.unit.test.ts +157 -0
- package/src/__tests__/get-experiment-results.unit.test.ts +222 -0
- package/src/__tests__/project-api-key-tools.unit.test.ts +451 -0
- package/src/__tests__/scenario-tools.unit.test.ts +3 -0
- package/src/config.ts +2 -0
- package/src/create-mcp-server.ts +257 -13
- package/src/langwatch-api-api-keys.ts +54 -0
- package/src/langwatch-api-projects.ts +82 -0
- package/src/langwatch-api.ts +22 -4
- package/src/tools/archive-project.ts +14 -0
- package/src/tools/create-api-key.ts +29 -0
- package/src/tools/create-project.ts +45 -0
- package/src/tools/get-experiment-results.ts +273 -0
- package/src/tools/get-project.ts +20 -0
- package/src/tools/list-api-keys.ts +33 -0
- package/src/tools/list-experiment-runs.ts +142 -0
- package/src/tools/list-experiments.ts +95 -0
- package/src/tools/list-projects.ts +41 -0
- package/src/tools/revoke-api-key.ts +9 -0
- package/src/tools/{run-evaluation.ts → run-experiment.ts} +5 -5
- package/src/tools/update-project.ts +22 -0
- package/uv.lock +192 -530
- package/Dockerfile +0 -22
- package/build.js +0 -12
- package/dist/archive-scenario-WJ2A7ETN.js.map +0 -1
- package/dist/archive-suite-4JOM4SSL.js.map +0 -1
- package/dist/assign-prompt-tag-GL7EAAF3.js.map +0 -1
- package/dist/chunk-2GT7IFWK.js.map +0 -1
- package/dist/chunk-2WPLXEKF.js.map +0 -1
- package/dist/chunk-4AUB2BIA.js.map +0 -1
- package/dist/chunk-BWWY5KEF.js.map +0 -1
- package/dist/chunk-CCWCIJJ3.js.map +0 -1
- package/dist/chunk-E5JYYU3J.js.map +0 -1
- package/dist/chunk-EGH5RPXM.js.map +0 -1
- package/dist/chunk-EUQDVOSU.js.map +0 -1
- package/dist/chunk-HYMIWO3U.js.map +0 -1
- package/dist/chunk-IE4M5OGE.js.map +0 -1
- package/dist/chunk-LUMEZEHL.js.map +0 -1
- package/dist/chunk-NUFPTHKU.js.map +0 -1
- package/dist/chunk-WQG2DFHX.js.map +0 -1
- package/dist/chunk-WVI5CJ6S.js.map +0 -1
- package/dist/chunk-ZVS4UKN2.js.map +0 -1
- package/dist/chunk-ZXKLPC2E.js.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/create-agent-MBOOT3XK.js.map +0 -1
- package/dist/create-annotation-XMV6A7ED.js.map +0 -1
- package/dist/create-dashboard-VRKLFVZJ.js.map +0 -1
- package/dist/create-dataset-7HQPZCRE.js.map +0 -1
- package/dist/create-dataset-records-2NIVFYTV.js.map +0 -1
- package/dist/create-evaluator-WYFRFLRC.js.map +0 -1
- package/dist/create-mcp-server.js.map +0 -1
- package/dist/create-prompt-IEN7O6JT.js.map +0 -1
- package/dist/create-prompt-tag-CAEZ45VO.js.map +0 -1
- package/dist/create-scenario-6YHSMGLP.js.map +0 -1
- package/dist/create-suite-H5XOFDE5.js.map +0 -1
- package/dist/delete-agent-JKTNBWAA.js.map +0 -1
- package/dist/delete-annotation-ACMDV6QO.js.map +0 -1
- package/dist/delete-dashboard-VJSR7CRU.js.map +0 -1
- package/dist/delete-dataset-RTTTWP4D.js.map +0 -1
- package/dist/delete-dataset-records-KNQTIPQK.js.map +0 -1
- package/dist/delete-evaluator-7FVC5WM4.js.map +0 -1
- package/dist/delete-prompt-tag-ZMZUAGFW.js.map +0 -1
- package/dist/delete-workflow-EYQ3T4RQ.js.map +0 -1
- package/dist/discover-evaluator-schema-H23XCLNE.js.map +0 -1
- package/dist/discover-scenario-schema-MEEEVND7.js.map +0 -1
- package/dist/discover-schema-3T52ORPB.js.map +0 -1
- package/dist/get-agent-E3QSTVKG.js.map +0 -1
- package/dist/get-analytics-2OHV763I.js.map +0 -1
- package/dist/get-dashboard-PC7JDHH6.js.map +0 -1
- package/dist/get-dataset-H5IK5FVU.js.map +0 -1
- package/dist/get-evaluator-UWVUPYTM.js.map +0 -1
- package/dist/get-prompt-WZUOLLQC.js.map +0 -1
- package/dist/get-scenario-Q6LCNUYN.js.map +0 -1
- package/dist/get-simulation-run-Z2XKO256.js.map +0 -1
- package/dist/get-suite-BXK5TN7P.js.map +0 -1
- package/dist/get-trace-4EJAYVBG.js.map +0 -1
- package/dist/get-workflow-O34QJLHD.js.map +0 -1
- package/dist/http-server-ISHF7NJX.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/langwatch-api-annotations-ERBG27RF.js.map +0 -1
- package/dist/langwatch-api-dashboards-G6TR7VVO.js.map +0 -1
- package/dist/langwatch-api-monitors-WSXZLS2B.js.map +0 -1
- package/dist/langwatch-api-secrets-RR5DKG2X.js.map +0 -1
- package/dist/langwatch-api-triggers-2RTNSWQY.js.map +0 -1
- package/dist/langwatch-api-workflows-VJRIIDZ7.js +0 -15
- package/dist/langwatch-api-workflows-VJRIIDZ7.js.map +0 -1
- package/dist/list-agents-AW3P6FJV.js.map +0 -1
- package/dist/list-annotations-QNCGWPQ3.js.map +0 -1
- package/dist/list-dashboards-R7RK2IXL.js.map +0 -1
- package/dist/list-dataset-records-WVCSQP7P.js.map +0 -1
- package/dist/list-datasets-KEXRLDEU.js.map +0 -1
- package/dist/list-evaluators-7R2LB4JH.js.map +0 -1
- package/dist/list-model-providers-OBYJCKBX.js.map +0 -1
- package/dist/list-prompt-tags-6LY3ZPYI.js.map +0 -1
- package/dist/list-prompts-VWEZ4CDE.js.map +0 -1
- package/dist/list-scenarios-TXD4W2ZJ.js.map +0 -1
- package/dist/list-simulation-runs-RHPOLMFI.js.map +0 -1
- package/dist/list-suites-FSGBX27Z.js.map +0 -1
- package/dist/list-workflows-VRGEZ3EN.js.map +0 -1
- package/dist/rename-prompt-tag-VOJJLX4M.js.map +0 -1
- package/dist/run-agent-KTCC7TB7.js.map +0 -1
- package/dist/run-evaluation-2X3V3Q6L.js +0 -64
- package/dist/run-evaluation-2X3V3Q6L.js.map +0 -1
- package/dist/run-suite-BTMHGI2D.js.map +0 -1
- package/dist/run-workflow-IGAYGKJL.js.map +0 -1
- package/dist/search-traces-VYFUIMXH.js.map +0 -1
- package/dist/set-model-provider-W5IUI326.js.map +0 -1
- package/dist/update-agent-4BB7EYLR.js.map +0 -1
- package/dist/update-dataset-CXBKZ4W3.js.map +0 -1
- package/dist/update-dataset-record-HOHAMHXG.js.map +0 -1
- package/dist/update-evaluator-IVOR6FTR.js.map +0 -1
- package/dist/update-prompt-OWQAKE7K.js.map +0 -1
- package/dist/update-scenario-GDFVILPN.js.map +0 -1
- package/dist/update-suite-BXYUYSPT.js.map +0 -1
- package/tests/evaluations.ipynb +0 -649
- package/tests/fixtures/azure/azure_openai_stream_bot_expected.py +0 -102
- package/tests/fixtures/azure/azure_openai_stream_bot_input.py +0 -78
- package/tests/fixtures/dspy/dspy_bot_expected.py +0 -61
- package/tests/fixtures/dspy/dspy_bot_input.py +0 -53
- package/tests/fixtures/fastapi/fastapi_app_expected.py +0 -68
- package/tests/fixtures/fastapi/fastapi_app_input.py +0 -60
- package/tests/fixtures/fastapi/prompt_management_fastapi_expected.py +0 -114
- package/tests/fixtures/fastapi/prompt_management_fastapi_input.py +0 -88
- package/tests/fixtures/haystack/haystack_bot_expected.py +0 -141
- package/tests/fixtures/haystack/haystack_bot_input.py +0 -69
- package/tests/fixtures/langchain/langchain_bot_expected.py +0 -53
- package/tests/fixtures/langchain/langchain_bot_input.py +0 -45
- package/tests/fixtures/langchain/langchain_bot_with_memory_expected.py +0 -69
- package/tests/fixtures/langchain/langchain_bot_with_memory_input.py +0 -61
- package/tests/fixtures/langchain/langchain_rag_bot_expected.py +0 -97
- package/tests/fixtures/langchain/langchain_rag_bot_input.py +0 -77
- package/tests/fixtures/langchain/langchain_rag_bot_vertex_ai_expected.py +0 -116
- package/tests/fixtures/langchain/langchain_rag_bot_vertex_ai_input.py +0 -81
- package/tests/fixtures/langchain/langgraph_rag_bot_with_threads_expected.py +0 -331
- package/tests/fixtures/langchain/langgraph_rag_bot_with_threads_input.py +0 -106
- package/tests/fixtures/litellm/litellm_bot_expected.py +0 -40
- package/tests/fixtures/litellm/litellm_bot_input.py +0 -35
- package/tests/fixtures/openai/openai_bot_expected.py +0 -43
- package/tests/fixtures/openai/openai_bot_function_call_expected.py +0 -91
- package/tests/fixtures/openai/openai_bot_function_call_input.py +0 -82
- package/tests/fixtures/openai/openai_bot_input.py +0 -36
- package/tests/fixtures/openai/openai_bot_rag_expected.py +0 -73
- package/tests/fixtures/openai/openai_bot_rag_input.py +0 -51
- package/tests/fixtures/opentelemetry/openinference_dspy_bot_expected.py +0 -63
- package/tests/fixtures/opentelemetry/openinference_dspy_bot_input.py +0 -58
- package/tests/fixtures/opentelemetry/openinference_langchain_bot_expected.py +0 -53
- package/tests/fixtures/opentelemetry/openinference_langchain_bot_input.py +0 -52
- package/tests/fixtures/opentelemetry/openinference_openai_bot_expected.py +0 -49
- package/tests/fixtures/opentelemetry/openinference_openai_bot_input.py +0 -41
- package/tests/fixtures/opentelemetry/openllmetry_openai_bot_expected.py +0 -44
- package/tests/fixtures/opentelemetry/openllmetry_openai_bot_input.py +0 -40
- package/tests/fixtures/strands/strands_bot_expected.py +0 -84
- package/tests/fixtures/strands/strands_bot_input.py +0 -52
- package/tests/scenario-openai.test.ts +0 -160
- package/tsup.config.ts +0 -14
- package/vitest.config.js +0 -7
package/src/config.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { AsyncLocalStorage } from "node:async_hooks";
|
|
|
3
3
|
export interface McpConfig {
|
|
4
4
|
apiKey: string | undefined;
|
|
5
5
|
endpoint: string;
|
|
6
|
+
projectId?: string;
|
|
6
7
|
}
|
|
7
8
|
|
|
8
9
|
// ---------------------------------------------------------------------------
|
|
@@ -56,6 +57,7 @@ export function initConfig(args: { apiKey?: string; endpoint?: string }): void {
|
|
|
56
57
|
args.endpoint ||
|
|
57
58
|
process.env.LANGWATCH_ENDPOINT ||
|
|
58
59
|
"https://app.langwatch.ai",
|
|
60
|
+
projectId: process.env.LANGWATCH_PROJECT_ID,
|
|
59
61
|
};
|
|
60
62
|
}
|
|
61
63
|
|
package/src/create-mcp-server.ts
CHANGED
|
@@ -7,6 +7,10 @@ import {
|
|
|
7
7
|
createDatasetSchema,
|
|
8
8
|
datasetColumnDefinitionSchema,
|
|
9
9
|
} from "./schemas/create-dataset.js";
|
|
10
|
+
import { handleExperimentResults } from "./tools/get-experiment-results.js";
|
|
11
|
+
import { handleExperimentListRuns } from "./tools/list-experiment-runs.js";
|
|
12
|
+
import { handleExperimentList } from "./tools/list-experiments.js";
|
|
13
|
+
import { handleRunExperiment, handleExperimentStatus } from "./tools/run-experiment.js";
|
|
10
14
|
|
|
11
15
|
const modelSchema = z
|
|
12
16
|
.string()
|
|
@@ -1541,34 +1545,124 @@ NOTE: Scenarios can be created two ways. Determine which approach the user needs
|
|
|
1541
1545
|
})
|
|
1542
1546
|
);
|
|
1543
1547
|
|
|
1544
|
-
// --- Platform
|
|
1548
|
+
// --- Platform Experiment Execution Tools (require API key) ---
|
|
1545
1549
|
|
|
1546
1550
|
server.tool(
|
|
1547
|
-
"
|
|
1548
|
-
"Start an
|
|
1551
|
+
"platform_run_experiment",
|
|
1552
|
+
"Start an experiment run by slug. Returns a run ID for polling status.",
|
|
1549
1553
|
{
|
|
1550
|
-
slug: z.string().describe("The
|
|
1554
|
+
slug: z.string().describe("The experiment slug to run"),
|
|
1551
1555
|
},
|
|
1552
|
-
withToolLogging("
|
|
1556
|
+
withToolLogging("platform_run_experiment", async (params) => {
|
|
1553
1557
|
requireApiKey();
|
|
1554
|
-
const { handleRunEvaluation } = await import("./tools/run-evaluation.js");
|
|
1555
1558
|
return {
|
|
1556
|
-
content: [{ type: "text", text: await
|
|
1559
|
+
content: [{ type: "text", text: await handleRunExperiment(params) }],
|
|
1557
1560
|
};
|
|
1558
1561
|
})
|
|
1559
1562
|
);
|
|
1560
1563
|
|
|
1561
1564
|
server.tool(
|
|
1562
|
-
"
|
|
1563
|
-
"Check the status of an
|
|
1565
|
+
"platform_experiment_status",
|
|
1566
|
+
"Check the status of an experiment run. Returns progress and summary when completed.",
|
|
1564
1567
|
{
|
|
1565
|
-
runId: z.string().describe("The run ID returned from
|
|
1568
|
+
runId: z.string().describe("The run ID returned from platform_run_experiment"),
|
|
1566
1569
|
},
|
|
1567
|
-
withToolLogging("
|
|
1570
|
+
withToolLogging("platform_experiment_status", async (params) => {
|
|
1568
1571
|
requireApiKey();
|
|
1569
|
-
const { handleEvaluationStatus } = await import("./tools/run-evaluation.js");
|
|
1570
1572
|
return {
|
|
1571
|
-
content: [{ type: "text", text: await
|
|
1573
|
+
content: [{ type: "text", text: await handleExperimentStatus(params) }],
|
|
1574
|
+
};
|
|
1575
|
+
})
|
|
1576
|
+
);
|
|
1577
|
+
|
|
1578
|
+
server.tool(
|
|
1579
|
+
"platform_experiment_list",
|
|
1580
|
+
"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.",
|
|
1581
|
+
{
|
|
1582
|
+
limit: z
|
|
1583
|
+
.number()
|
|
1584
|
+
.int()
|
|
1585
|
+
.positive()
|
|
1586
|
+
.max(100)
|
|
1587
|
+
.optional()
|
|
1588
|
+
.describe(
|
|
1589
|
+
"Maximum number of experiments to include (default 25, hard-capped at 100)",
|
|
1590
|
+
),
|
|
1591
|
+
},
|
|
1592
|
+
withToolLogging("platform_experiment_list", async (params) => {
|
|
1593
|
+
requireApiKey();
|
|
1594
|
+
return {
|
|
1595
|
+
content: [{ type: "text", text: await handleExperimentList(params) }],
|
|
1596
|
+
};
|
|
1597
|
+
})
|
|
1598
|
+
);
|
|
1599
|
+
|
|
1600
|
+
server.tool(
|
|
1601
|
+
"platform_experiment_list_runs",
|
|
1602
|
+
"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.",
|
|
1603
|
+
{
|
|
1604
|
+
experimentSlug: z
|
|
1605
|
+
.string()
|
|
1606
|
+
.describe(
|
|
1607
|
+
"Experiment slug from platform_experiment_list (e.g. 'checkout-flow')",
|
|
1608
|
+
),
|
|
1609
|
+
limit: z
|
|
1610
|
+
.number()
|
|
1611
|
+
.int()
|
|
1612
|
+
.positive()
|
|
1613
|
+
.max(100)
|
|
1614
|
+
.optional()
|
|
1615
|
+
.describe(
|
|
1616
|
+
"Maximum number of runs to include (default 25, hard-capped at 100)",
|
|
1617
|
+
),
|
|
1618
|
+
},
|
|
1619
|
+
withToolLogging("platform_experiment_list_runs", async (params) => {
|
|
1620
|
+
requireApiKey();
|
|
1621
|
+
return {
|
|
1622
|
+
content: [{ type: "text", text: await handleExperimentListRuns(params) }],
|
|
1623
|
+
};
|
|
1624
|
+
})
|
|
1625
|
+
);
|
|
1626
|
+
|
|
1627
|
+
server.tool(
|
|
1628
|
+
"platform_experiment_results",
|
|
1629
|
+
"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 — narrow with `filter: 'failed'` or `evaluator` to see what matters.",
|
|
1630
|
+
{
|
|
1631
|
+
runId: z
|
|
1632
|
+
.string()
|
|
1633
|
+
.describe("The run ID returned from platform_run_experiment"),
|
|
1634
|
+
experimentSlug: z
|
|
1635
|
+
.string()
|
|
1636
|
+
.optional()
|
|
1637
|
+
.describe(
|
|
1638
|
+
"Experiment slug — required when fetching results for runs older than 24h (Redis state may have expired). Use platform_experiment_list_runs to find the slug.",
|
|
1639
|
+
),
|
|
1640
|
+
filter: z
|
|
1641
|
+
.enum(["all", "failed"])
|
|
1642
|
+
.optional()
|
|
1643
|
+
.describe(
|
|
1644
|
+
"Filter rows: 'failed' shows only rows that errored or failed an evaluation; 'all' (default) shows everything",
|
|
1645
|
+
),
|
|
1646
|
+
evaluator: z
|
|
1647
|
+
.string()
|
|
1648
|
+
.optional()
|
|
1649
|
+
.describe("Show only this evaluator's results (matched on `evaluator` field)"),
|
|
1650
|
+
limit: z
|
|
1651
|
+
.number()
|
|
1652
|
+
.int()
|
|
1653
|
+
.positive()
|
|
1654
|
+
.max(50)
|
|
1655
|
+
.optional()
|
|
1656
|
+
.describe(
|
|
1657
|
+
"Maximum number of rows to include in the markdown output (default 50, hard-capped at 50).",
|
|
1658
|
+
),
|
|
1659
|
+
},
|
|
1660
|
+
withToolLogging("platform_experiment_results", async (params) => {
|
|
1661
|
+
requireApiKey();
|
|
1662
|
+
return {
|
|
1663
|
+
content: [
|
|
1664
|
+
{ type: "text", text: await handleExperimentResults(params) },
|
|
1665
|
+
],
|
|
1572
1666
|
};
|
|
1573
1667
|
})
|
|
1574
1668
|
);
|
|
@@ -1796,4 +1890,154 @@ NOTE: Scenarios can be created two ways. Determine which approach the user needs
|
|
|
1796
1890
|
};
|
|
1797
1891
|
}
|
|
1798
1892
|
);
|
|
1893
|
+
|
|
1894
|
+
// --- Platform Project Tools ---
|
|
1895
|
+
// These tools manage projects on the LangWatch platform via the REST API.
|
|
1896
|
+
// They require an API key with org-level permissions.
|
|
1897
|
+
|
|
1898
|
+
server.tool(
|
|
1899
|
+
"platform_list_projects",
|
|
1900
|
+
"List all projects in your LangWatch organization. Requires an org-level API key.",
|
|
1901
|
+
{
|
|
1902
|
+
page: z.number().int().positive().optional().describe("Page number (default: 1)"),
|
|
1903
|
+
limit: z.number().int().positive().max(1000).optional().describe("Results per page (default: 100)"),
|
|
1904
|
+
},
|
|
1905
|
+
withToolLogging("platform_list_projects", async (params) => {
|
|
1906
|
+
requireApiKey();
|
|
1907
|
+
const { handleListProjects } = await import("./tools/list-projects.js");
|
|
1908
|
+
return {
|
|
1909
|
+
content: [{ type: "text", text: await handleListProjects(params) }],
|
|
1910
|
+
};
|
|
1911
|
+
})
|
|
1912
|
+
);
|
|
1913
|
+
|
|
1914
|
+
server.tool(
|
|
1915
|
+
"platform_get_project",
|
|
1916
|
+
"Get details of a specific project by its ID.",
|
|
1917
|
+
{
|
|
1918
|
+
id: z.string().describe("The project ID"),
|
|
1919
|
+
},
|
|
1920
|
+
withToolLogging("platform_get_project", async (params) => {
|
|
1921
|
+
requireApiKey();
|
|
1922
|
+
const { handleGetProject } = await import("./tools/get-project.js");
|
|
1923
|
+
return {
|
|
1924
|
+
content: [{ type: "text", text: await handleGetProject(params) }],
|
|
1925
|
+
};
|
|
1926
|
+
})
|
|
1927
|
+
);
|
|
1928
|
+
|
|
1929
|
+
server.tool(
|
|
1930
|
+
"platform_create_project",
|
|
1931
|
+
`Create a new project in your LangWatch organization. Returns a one-time service API key for the project.
|
|
1932
|
+
|
|
1933
|
+
You must provide either teamId (to add the project to an existing team) or newTeamName (to create a new team for the project).`,
|
|
1934
|
+
{
|
|
1935
|
+
name: z.string().describe("Project name"),
|
|
1936
|
+
language: z.string().describe('Programming language (e.g. "python", "typescript")'),
|
|
1937
|
+
framework: z.string().describe('Framework (e.g. "openai", "langchain", "custom")'),
|
|
1938
|
+
teamId: z.string().optional().describe("ID of an existing team to add the project to"),
|
|
1939
|
+
newTeamName: z.string().optional().describe("Name for a new team to create for this project"),
|
|
1940
|
+
},
|
|
1941
|
+
withToolLogging("platform_create_project", async (params) => {
|
|
1942
|
+
requireApiKey();
|
|
1943
|
+
const { handleCreateProject } = await import("./tools/create-project.js");
|
|
1944
|
+
return {
|
|
1945
|
+
content: [{ type: "text", text: await handleCreateProject(params) }],
|
|
1946
|
+
};
|
|
1947
|
+
})
|
|
1948
|
+
);
|
|
1949
|
+
|
|
1950
|
+
server.tool(
|
|
1951
|
+
"platform_update_project",
|
|
1952
|
+
"Update an existing project's name, language, framework, or PII redaction level.",
|
|
1953
|
+
{
|
|
1954
|
+
id: z.string().describe("The project ID to update"),
|
|
1955
|
+
name: z.string().optional().describe("New project name"),
|
|
1956
|
+
language: z.string().optional().describe("New programming language"),
|
|
1957
|
+
framework: z.string().optional().describe("New framework"),
|
|
1958
|
+
piiRedactionLevel: z.enum(["STRICT", "ESSENTIAL", "DISABLED"]).optional().describe("PII redaction level"),
|
|
1959
|
+
},
|
|
1960
|
+
withToolLogging("platform_update_project", async (params) => {
|
|
1961
|
+
requireApiKey();
|
|
1962
|
+
const { handleUpdateProject } = await import("./tools/update-project.js");
|
|
1963
|
+
return {
|
|
1964
|
+
content: [{ type: "text", text: await handleUpdateProject(params) }],
|
|
1965
|
+
};
|
|
1966
|
+
})
|
|
1967
|
+
);
|
|
1968
|
+
|
|
1969
|
+
server.tool(
|
|
1970
|
+
"platform_archive_project",
|
|
1971
|
+
"Archive (soft-delete) a project. The project can be restored later if needed.",
|
|
1972
|
+
{
|
|
1973
|
+
id: z.string().describe("The project ID to archive"),
|
|
1974
|
+
},
|
|
1975
|
+
withToolLogging("platform_archive_project", async (params) => {
|
|
1976
|
+
requireApiKey();
|
|
1977
|
+
const { handleArchiveProject } = await import("./tools/archive-project.js");
|
|
1978
|
+
return {
|
|
1979
|
+
content: [{ type: "text", text: await handleArchiveProject(params) }],
|
|
1980
|
+
};
|
|
1981
|
+
})
|
|
1982
|
+
);
|
|
1983
|
+
|
|
1984
|
+
// --- Platform API Key Tools (require org-level API key) ---
|
|
1985
|
+
// These tools manage API keys on the LangWatch platform via the REST API.
|
|
1986
|
+
|
|
1987
|
+
server.tool(
|
|
1988
|
+
"platform_list_api_keys",
|
|
1989
|
+
"List all API keys in your LangWatch organization. Shows key metadata, status (active/revoked/expired), and role bindings. API key tokens are never returned.",
|
|
1990
|
+
{},
|
|
1991
|
+
withToolLogging("platform_list_api_keys", async () => {
|
|
1992
|
+
requireApiKey();
|
|
1993
|
+
const { handleListApiKeys } = await import("./tools/list-api-keys.js");
|
|
1994
|
+
return {
|
|
1995
|
+
content: [{ type: "text", text: await handleListApiKeys() }],
|
|
1996
|
+
};
|
|
1997
|
+
})
|
|
1998
|
+
);
|
|
1999
|
+
|
|
2000
|
+
server.tool(
|
|
2001
|
+
"platform_create_api_key",
|
|
2002
|
+
`Create a new API key. Two types available:
|
|
2003
|
+
|
|
2004
|
+
- **personal**: Tied to a user, requires explicit role bindings (e.g. ADMIN on PROJECT:proj_123).
|
|
2005
|
+
- **service**: Not tied to a user. Use projectIds for project-scoped service keys, or omit for org-wide access.
|
|
2006
|
+
|
|
2007
|
+
The token is returned once and cannot be retrieved again.`,
|
|
2008
|
+
{
|
|
2009
|
+
keyType: z.enum(["personal", "service"]).describe("Key type: 'personal' (user-tied) or 'service' (headless)"),
|
|
2010
|
+
name: z.string().describe("Key name (max 100 chars)"),
|
|
2011
|
+
description: z.string().optional().describe("Key description (max 500 chars)"),
|
|
2012
|
+
expiresAt: z.string().optional().describe("Expiration date (ISO string)"),
|
|
2013
|
+
bindings: z.array(z.object({
|
|
2014
|
+
role: z.enum(["ADMIN", "MEMBER", "VIEWER"]).describe("Role"),
|
|
2015
|
+
scopeType: z.enum(["ORGANIZATION", "TEAM", "PROJECT"]).describe("Scope type"),
|
|
2016
|
+
scopeId: z.string().describe("Scope ID (org, team, or project ID)"),
|
|
2017
|
+
})).optional().describe("Role bindings (required for personal keys)"),
|
|
2018
|
+
projectIds: z.array(z.string()).optional().describe("Project IDs for service keys (creates ADMIN bindings per project)"),
|
|
2019
|
+
},
|
|
2020
|
+
withToolLogging("platform_create_api_key", async (params) => {
|
|
2021
|
+
requireApiKey();
|
|
2022
|
+
const { handleCreateApiKey } = await import("./tools/create-api-key.js");
|
|
2023
|
+
return {
|
|
2024
|
+
content: [{ type: "text", text: await handleCreateApiKey(params) }],
|
|
2025
|
+
};
|
|
2026
|
+
})
|
|
2027
|
+
);
|
|
2028
|
+
|
|
2029
|
+
server.tool(
|
|
2030
|
+
"platform_revoke_api_key",
|
|
2031
|
+
"Revoke an API key. Once revoked, the key can no longer be used for authentication.",
|
|
2032
|
+
{
|
|
2033
|
+
id: z.string().describe("The API key ID to revoke"),
|
|
2034
|
+
},
|
|
2035
|
+
withToolLogging("platform_revoke_api_key", async (params) => {
|
|
2036
|
+
requireApiKey();
|
|
2037
|
+
const { handleRevokeApiKey } = await import("./tools/revoke-api-key.js");
|
|
2038
|
+
return {
|
|
2039
|
+
content: [{ type: "text", text: await handleRevokeApiKey(params) }],
|
|
2040
|
+
};
|
|
2041
|
+
})
|
|
2042
|
+
);
|
|
1799
2043
|
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { makeRequest } from "./langwatch-api.js";
|
|
2
|
+
|
|
3
|
+
export interface RoleBinding {
|
|
4
|
+
id: string;
|
|
5
|
+
role: string;
|
|
6
|
+
scopeType: string;
|
|
7
|
+
scopeId: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface ApiKeySummary {
|
|
11
|
+
id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
description: string | null;
|
|
14
|
+
createdAt: string;
|
|
15
|
+
expiresAt: string | null;
|
|
16
|
+
lastUsedAt: string | null;
|
|
17
|
+
revokedAt: string | null;
|
|
18
|
+
roleBindings: RoleBinding[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ApiKeyCreateResponse {
|
|
22
|
+
token: string;
|
|
23
|
+
apiKey: {
|
|
24
|
+
id: string;
|
|
25
|
+
name: string;
|
|
26
|
+
createdAt: string;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function listApiKeys(): Promise<{ data: ApiKeySummary[] }> {
|
|
31
|
+
return makeRequest("GET", "/api/api-keys") as Promise<{ data: ApiKeySummary[] }>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function createApiKey(data: {
|
|
35
|
+
keyType: "personal" | "service";
|
|
36
|
+
name: string;
|
|
37
|
+
description?: string;
|
|
38
|
+
expiresAt?: string;
|
|
39
|
+
bindings?: Array<{
|
|
40
|
+
role: "ADMIN" | "MEMBER" | "VIEWER";
|
|
41
|
+
scopeType: "ORGANIZATION" | "TEAM" | "PROJECT";
|
|
42
|
+
scopeId: string;
|
|
43
|
+
}>;
|
|
44
|
+
projectIds?: string[];
|
|
45
|
+
}): Promise<ApiKeyCreateResponse> {
|
|
46
|
+
return makeRequest("POST", "/api/api-keys", data) as Promise<ApiKeyCreateResponse>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function revokeApiKey(id: string): Promise<{ success: boolean }> {
|
|
50
|
+
return makeRequest(
|
|
51
|
+
"DELETE",
|
|
52
|
+
`/api/api-keys/${encodeURIComponent(id)}`,
|
|
53
|
+
) as Promise<{ success: boolean }>;
|
|
54
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { makeRequest } from "./langwatch-api.js";
|
|
2
|
+
|
|
3
|
+
export interface ProjectSummary {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
slug: string;
|
|
7
|
+
language: string;
|
|
8
|
+
framework: string;
|
|
9
|
+
teamId: string;
|
|
10
|
+
piiRedactionLevel: string;
|
|
11
|
+
createdAt: string;
|
|
12
|
+
updatedAt: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ProjectListResponse {
|
|
16
|
+
data: ProjectSummary[];
|
|
17
|
+
pagination: {
|
|
18
|
+
page: number;
|
|
19
|
+
limit: number;
|
|
20
|
+
total: number;
|
|
21
|
+
totalPages: number;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface ProjectCreateResponse extends ProjectSummary {
|
|
26
|
+
serviceApiKey: string;
|
|
27
|
+
serviceApiKeyId: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function listProjects(params?: {
|
|
31
|
+
page?: number;
|
|
32
|
+
limit?: number;
|
|
33
|
+
}): Promise<ProjectListResponse> {
|
|
34
|
+
const query = new URLSearchParams();
|
|
35
|
+
if (params?.page) query.set("page", String(params.page));
|
|
36
|
+
if (params?.limit) query.set("limit", String(params.limit));
|
|
37
|
+
const qs = query.toString() ? `?${query}` : "";
|
|
38
|
+
return makeRequest("GET", `/api/projects${qs}`) as Promise<ProjectListResponse>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function getProject(id: string): Promise<ProjectSummary> {
|
|
42
|
+
return makeRequest(
|
|
43
|
+
"GET",
|
|
44
|
+
`/api/projects/${encodeURIComponent(id)}`,
|
|
45
|
+
) as Promise<ProjectSummary>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export async function createProject(data: {
|
|
49
|
+
name: string;
|
|
50
|
+
language: string;
|
|
51
|
+
framework: string;
|
|
52
|
+
teamId?: string;
|
|
53
|
+
newTeamName?: string;
|
|
54
|
+
}): Promise<ProjectCreateResponse> {
|
|
55
|
+
return makeRequest("POST", "/api/projects", data) as Promise<ProjectCreateResponse>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export async function updateProject(params: {
|
|
59
|
+
id: string;
|
|
60
|
+
name?: string;
|
|
61
|
+
language?: string;
|
|
62
|
+
framework?: string;
|
|
63
|
+
piiRedactionLevel?: "STRICT" | "ESSENTIAL" | "DISABLED";
|
|
64
|
+
}): Promise<ProjectSummary> {
|
|
65
|
+
const { id, ...data } = params;
|
|
66
|
+
return makeRequest(
|
|
67
|
+
"PATCH",
|
|
68
|
+
`/api/projects/${encodeURIComponent(id)}`,
|
|
69
|
+
data,
|
|
70
|
+
) as Promise<ProjectSummary>;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export async function archiveProject(id: string): Promise<{
|
|
74
|
+
id: string;
|
|
75
|
+
name: string;
|
|
76
|
+
archivedAt: string;
|
|
77
|
+
}> {
|
|
78
|
+
return makeRequest(
|
|
79
|
+
"DELETE",
|
|
80
|
+
`/api/projects/${encodeURIComponent(id)}`,
|
|
81
|
+
) as Promise<{ id: string; name: string; archivedAt: string }>;
|
|
82
|
+
}
|
package/src/langwatch-api.ts
CHANGED
|
@@ -105,23 +105,39 @@ export interface PromptMutationResponse {
|
|
|
105
105
|
|
|
106
106
|
// --- HTTP client ---
|
|
107
107
|
|
|
108
|
+
export class LangWatchApiError extends Error {
|
|
109
|
+
constructor(
|
|
110
|
+
message: string,
|
|
111
|
+
public readonly status: number,
|
|
112
|
+
public readonly responseBody: string,
|
|
113
|
+
) {
|
|
114
|
+
super(message);
|
|
115
|
+
this.name = "LangWatchApiError";
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
108
119
|
/**
|
|
109
120
|
* Sends an HTTP request to the LangWatch API.
|
|
110
121
|
*
|
|
111
122
|
* Builds the full URL from the configured endpoint, adds authentication,
|
|
112
123
|
* and handles JSON serialization/deserialization.
|
|
113
124
|
*
|
|
114
|
-
* @throws
|
|
125
|
+
* @throws LangWatchApiError with status code and response body when the
|
|
126
|
+
* response is not OK.
|
|
115
127
|
*/
|
|
116
128
|
export async function makeRequest(
|
|
117
129
|
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE",
|
|
118
130
|
path: string,
|
|
119
131
|
body?: unknown
|
|
120
132
|
): Promise<unknown> {
|
|
121
|
-
const
|
|
133
|
+
const config = getConfig();
|
|
134
|
+
const url = config.endpoint + path;
|
|
122
135
|
const headers: Record<string, string> = {
|
|
123
136
|
"X-Auth-Token": requireApiKey(),
|
|
124
137
|
};
|
|
138
|
+
if (config.projectId) {
|
|
139
|
+
headers["X-Project-Id"] = config.projectId;
|
|
140
|
+
}
|
|
125
141
|
|
|
126
142
|
if (body !== undefined) {
|
|
127
143
|
headers["Content-Type"] = "application/json";
|
|
@@ -135,8 +151,10 @@ export async function makeRequest(
|
|
|
135
151
|
|
|
136
152
|
if (!response.ok) {
|
|
137
153
|
const responseBody = await response.text();
|
|
138
|
-
throw new
|
|
139
|
-
`LangWatch API error ${response.status}: ${responseBody}
|
|
154
|
+
throw new LangWatchApiError(
|
|
155
|
+
`LangWatch API error ${response.status}: ${responseBody}`,
|
|
156
|
+
response.status,
|
|
157
|
+
responseBody,
|
|
140
158
|
);
|
|
141
159
|
}
|
|
142
160
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { archiveProject as apiArchiveProject } from "../langwatch-api-projects.js";
|
|
2
|
+
|
|
3
|
+
export async function handleArchiveProject(params: {
|
|
4
|
+
id: string;
|
|
5
|
+
}): Promise<string> {
|
|
6
|
+
const result = await apiArchiveProject(params.id);
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
`Project archived successfully.\n\n` +
|
|
10
|
+
`**Name**: ${result.name}\n` +
|
|
11
|
+
`**ID**: ${result.id}\n` +
|
|
12
|
+
`**Archived At**: ${result.archivedAt}`
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createApiKey as apiCreateApiKey } from "../langwatch-api-api-keys.js";
|
|
2
|
+
|
|
3
|
+
export async function handleCreateApiKey(params: {
|
|
4
|
+
keyType: "personal" | "service";
|
|
5
|
+
name: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
expiresAt?: string;
|
|
8
|
+
bindings?: Array<{
|
|
9
|
+
role: "ADMIN" | "MEMBER" | "VIEWER";
|
|
10
|
+
scopeType: "ORGANIZATION" | "TEAM" | "PROJECT";
|
|
11
|
+
scopeId: string;
|
|
12
|
+
}>;
|
|
13
|
+
projectIds?: string[];
|
|
14
|
+
}): Promise<string> {
|
|
15
|
+
const result = await apiCreateApiKey(params);
|
|
16
|
+
|
|
17
|
+
const lines: string[] = [];
|
|
18
|
+
lines.push(`API key created successfully!\n`);
|
|
19
|
+
lines.push(`**Name**: ${result.apiKey.name}`);
|
|
20
|
+
lines.push(`**ID**: ${result.apiKey.id}`);
|
|
21
|
+
lines.push(`**Token**: \`${result.token}\``);
|
|
22
|
+
lines.push(`**Created**: ${result.apiKey.createdAt}`);
|
|
23
|
+
lines.push("");
|
|
24
|
+
lines.push(
|
|
25
|
+
"> ⚠️ Save this token now — it will not be shown again.",
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
return lines.join("\n");
|
|
29
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { createProject as apiCreateProject } from "../langwatch-api-projects.js";
|
|
2
|
+
|
|
3
|
+
export async function handleCreateProject(params: {
|
|
4
|
+
name: string;
|
|
5
|
+
language: string;
|
|
6
|
+
framework: string;
|
|
7
|
+
teamId?: string;
|
|
8
|
+
newTeamName?: string;
|
|
9
|
+
}): Promise<string> {
|
|
10
|
+
if (!params.teamId && !params.newTeamName) {
|
|
11
|
+
return "Error: You must provide either `teamId` (to add to an existing team) or `newTeamName` (to create a new team for this project).";
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const result = await apiCreateProject({
|
|
15
|
+
name: params.name,
|
|
16
|
+
language: params.language,
|
|
17
|
+
framework: params.framework,
|
|
18
|
+
teamId: params.teamId,
|
|
19
|
+
newTeamName: params.newTeamName,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
if (!result.serviceApiKey) {
|
|
23
|
+
throw new Error(
|
|
24
|
+
"API did not return a service API key. The project was created but the key is missing — check the LangWatch UI.",
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const lines: string[] = [];
|
|
29
|
+
lines.push(`Project created successfully!\n`);
|
|
30
|
+
lines.push(`**Name**: ${result.name}`);
|
|
31
|
+
lines.push(`**ID**: ${result.id}`);
|
|
32
|
+
lines.push(`**Slug**: ${result.slug}`);
|
|
33
|
+
lines.push(`**Language**: ${result.language}`);
|
|
34
|
+
lines.push(`**Framework**: ${result.framework}`);
|
|
35
|
+
lines.push("");
|
|
36
|
+
lines.push(`**Service API Key**: \`${result.serviceApiKey}\``);
|
|
37
|
+
lines.push(`**Service API Key ID**: ${result.serviceApiKeyId}`);
|
|
38
|
+
lines.push("");
|
|
39
|
+
lines.push(
|
|
40
|
+
"> ⚠️ Save the service API key now — it will not be shown again. " +
|
|
41
|
+
"Use it as `LANGWATCH_API_KEY` to authenticate project-scoped operations.",
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
return lines.join("\n");
|
|
45
|
+
}
|