From 9bf2cf3e1f2f0c96fe09c4d7d8eabb90b7bc2889 Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 17:18:07 +0200
Subject: [PATCH 01/24] chore(http-ts): bump payments for MPP, drop OpenAI, add
plan-id env
---
http-simple-agent-ts/.env.example | 30 +-
http-simple-agent-ts/package.json | 12 +-
http-simple-agent-ts/tsconfig.json | 2 +-
http-simple-agent-ts/yarn.lock | 728 ++++++++++++++++-------------
4 files changed, 419 insertions(+), 353 deletions(-)
diff --git a/http-simple-agent-ts/.env.example b/http-simple-agent-ts/.env.example
index 154196ce..0cd9bb8b 100644
--- a/http-simple-agent-ts/.env.example
+++ b/http-simple-agent-ts/.env.example
@@ -1,29 +1,11 @@
-# =============================================================================
-# Nevermined Configuration (required for both agent and client)
-# =============================================================================
-
-# Your Nevermined API key (get it from https://nevermined.app)
+# Nevermined (required)
NVM_API_KEY=nvm:your-api-key
-
-# Environment: 'sandbox' (Base Sepolia) or 'live' (Arbitrum One)
NVM_ENVIRONMENT=sandbox
-# The Plan ID that protects the /ask endpoint
-NVM_PLAN_ID=your-plan-id
-
-# =============================================================================
-# Agent Configuration (server)
-# =============================================================================
+# Plan IDs — created by `yarn register-plans` (see scripts/register-plans.ts)
+PLAN_ID_CREDITS=
+PLAN_ID_TIME=
+PLAN_ID_PAYG=
-# OpenAI API Key for the AI endpoint
-OPENAI_API_KEY=sk-your-openai-api-key
-
-# Server port (optional, defaults to 3000)
+# Server
PORT=3000
-
-# =============================================================================
-# Client Configuration
-# =============================================================================
-
-# URL of the agent server (optional, defaults to http://localhost:3000)
-SERVER_URL=http://localhost:3000
diff --git a/http-simple-agent-ts/package.json b/http-simple-agent-ts/package.json
index c28d59cc..0579fe26 100644
--- a/http-simple-agent-ts/package.json
+++ b/http-simple-agent-ts/package.json
@@ -7,17 +7,17 @@
"type": "module",
"scripts": {
"agent": "tsx src/agent.ts",
- "agent:observability": "tsx src/agent-observability.ts",
"client": "tsx src/client.ts",
+ "register-plans": "tsx scripts/register-plans.ts",
+ "smoke": "tsx scripts/smoke.ts",
+ "pricing:selfcheck": "tsx src/pricing.selfcheck.ts",
"build": "tsc",
- "start:agent": "node dist/agent.js",
- "start:client": "node dist/client.js"
+ "start": "node dist/agent.js"
},
"dependencies": {
- "@nevermined-io/payments": "^1.1.0",
+ "@nevermined-io/payments": "1.11.2",
"dotenv": "^16.4.5",
- "express": "^4.19.2",
- "openai": "^4.77.0"
+ "express": "^4.19.2"
},
"devDependencies": {
"@types/express": "^4.17.21",
diff --git a/http-simple-agent-ts/tsconfig.json b/http-simple-agent-ts/tsconfig.json
index 627f0e60..3fc4e6ff 100644
--- a/http-simple-agent-ts/tsconfig.json
+++ b/http-simple-agent-ts/tsconfig.json
@@ -10,5 +10,5 @@
"rootDir": "src"
},
"include": ["src/**/*"],
- "exclude": ["node_modules", "dist"]
+ "exclude": ["node_modules", "dist", "src/agent-observability.ts"]
}
diff --git a/http-simple-agent-ts/yarn.lock b/http-simple-agent-ts/yarn.lock
index d92f1db7..d2a884db 100644
--- a/http-simple-agent-ts/yarn.lock
+++ b/http-simple-agent-ts/yarn.lock
@@ -2,10 +2,10 @@
# yarn lockfile v1
-"@a2a-js/sdk@^0.3.4":
- version "0.3.7"
- resolved "https://registry.yarnpkg.com/@a2a-js/sdk/-/sdk-0.3.7.tgz#3e7f65ba29cda90d81a70001f5391cace8431d4c"
- integrity sha512-1WBghkOjgiKt4rPNje8jlB9VateVQXqyjlc887bY/H8yM82Hlf0+5JW8zB98BPExKAplI5XqtXVH980J6vqi+w==
+"@a2a-js/sdk@^0.3.13":
+ version "0.3.14"
+ resolved "https://registry.yarnpkg.com/@a2a-js/sdk/-/sdk-0.3.14.tgz#e807b4e6516ea8c4af621ad9789d8dad6173058d"
+ integrity sha512-F6Ew1AtPzCLhTn8h9yiqTe7DiDf6XVrSnq9V1YqSl9eWqPm6anMveTiKdCSb/76cW0YiJc24rNaUrVezFFHbqQ==
dependencies:
uuid "^11.1.0"
@@ -144,6 +144,32 @@
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz#9e585ab6086bef994c6e8a5b3a0481219ada862b"
integrity sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==
+"@google-cloud/opentelemetry-cloud-trace-exporter@^3.0.0":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@google-cloud/opentelemetry-cloud-trace-exporter/-/opentelemetry-cloud-trace-exporter-3.1.0.tgz#1c34bb1c9b4dd50040afd298f21e2653189a5674"
+ integrity sha512-O7tpsMYLcZA7eE+y5ZpLBYHZfruvnYhmh4RLI2xTelVMsmR2JJolQCi3gk6dlDo58QDh7UzmX48X8TeNG1oG2g==
+ dependencies:
+ "@google-cloud/opentelemetry-resource-util" "^3.1.0"
+ "@grpc/grpc-js" "^1.1.8"
+ "@grpc/proto-loader" "^0.8.0"
+ google-auth-library "^10.0.0"
+
+"@google-cloud/opentelemetry-resource-util@^3.1.0":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@google-cloud/opentelemetry-resource-util/-/opentelemetry-resource-util-3.1.0.tgz#d255fd66acc6fe2e49eec30611fc53812bae9464"
+ integrity sha512-dTvbFl+q9ac0Me8+GaDrFdwDBia/L8Qxxi/NY/jeHaUogDIpqOtLoqcXV9HdgiLxy5vjEGaJMqir1nVra1qG7w==
+ dependencies:
+ "@opentelemetry/semantic-conventions" "^1.22.0"
+ gcp-metadata "^9.0.0"
+
+"@grpc/grpc-js@^1.1.8":
+ version "1.14.4"
+ resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.14.4.tgz#e73ff57d97802f063999545f43ebb2b1eca65d9d"
+ integrity sha512-k9Dj3DV/itK9D06Y8f190Qgop7/Ui+D0njFV3LHMPwPT75DpXLQohE9Wmz0QElrJnzsjB7KPWiKJbOl7IPDArQ==
+ dependencies:
+ "@grpc/proto-loader" "^0.8.0"
+ "@js-sdsl/ordered-map" "^4.4.2"
+
"@grpc/grpc-js@^1.10.9", "@grpc/grpc-js@^1.7.1":
version "1.14.3"
resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.14.3.tgz#4c9b817a900ae4020ddc28515ae4b52c78cfb8da"
@@ -182,34 +208,29 @@
resolved "https://registry.yarnpkg.com/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz#9299f82874bab9e4c7f9c48d865becbfe8d6907c"
integrity sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==
-"@langchain/core@^0.3.58":
- version "0.3.80"
- resolved "https://registry.yarnpkg.com/@langchain/core/-/core-0.3.80.tgz#c494a6944e53ab28bf32dc531e257b17cfc8f797"
- integrity sha512-vcJDV2vk1AlCwSh3aBm/urQ1ZrlXFFBocv11bz/NBUfLWD5/UDNMzwPdaAd2dKvNmTWa9FM2lirLU3+JCf4cRA==
+"@langchain/core@>=1.0.0 <2.0.0":
+ version "1.2.9"
+ resolved "https://registry.yarnpkg.com/@langchain/core/-/core-1.2.9.tgz#4f5fb27ba07c51ce4fb8e1dc32eb36945737afa1"
+ integrity sha512-conzSEj9Zu1AyXJLXsSbgrtxtxinmI1yGqQ5CIJZSoV5rvv+yvQE/vgBnoySpBQ/bl3YPgj2FL/gbDjWykLSfg==
dependencies:
"@cfworker/json-schema" "^4.0.2"
- ansi-styles "^5.0.0"
- camelcase "6"
- decamelize "1.2.0"
+ "@standard-schema/spec" "^1.1.0"
js-tiktoken "^1.0.12"
- langsmith "^0.3.67"
+ langsmith ">=0.5.0 <1.0.0"
mustache "^4.2.0"
p-queue "^6.6.2"
- p-retry "4"
- uuid "^10.0.0"
- zod "^3.25.32"
- zod-to-json-schema "^3.22.3"
+ zod "^3.25.76 || ^4"
-"@nevermined-io/payments@^1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@nevermined-io/payments/-/payments-1.1.0.tgz#5257c4c870a77915ecef7f7687955177298bcd21"
- integrity sha512-grRz660Ds15n9+hamI6ZfvOp3CvLXrUBRdc0kSa9XuZiFCwmDQcErXGvrvyB0UUtAVJ51I7sKpBgS3Heq88CLw==
+"@nevermined-io/payments@1.11.2":
+ version "1.11.2"
+ resolved "https://registry.yarnpkg.com/@nevermined-io/payments/-/payments-1.11.2.tgz#9d803db4ef630085c0ecd02383cd0e7ebea0d04b"
+ integrity sha512-BdD3zErRzri3/++KHl7YdpbImH2UEpsJvCQGZIATwwbI9ApvTxoIWjAR3HabMyU9VkA6PxzE0T50d1WrB++LKQ==
dependencies:
- "@a2a-js/sdk" "^0.3.4"
+ "@a2a-js/sdk" "^0.3.13"
"@helicone/helpers" "^1.6.0"
"@opentelemetry/api" "^1.9.0"
- "@opentelemetry/exporter-trace-otlp-http" "^0.203.0"
- "@traceloop/node-server-sdk" "^0.14.6"
+ "@opentelemetry/exporter-trace-otlp-http" "^0.215.0"
+ "@traceloop/node-server-sdk" "^0.26.0"
axios "^1.13.1"
express "4.21.2"
jose "^5.2.4"
@@ -225,6 +246,13 @@
dependencies:
"@opentelemetry/api" "^1.3.0"
+"@opentelemetry/api-logs@0.215.0":
+ version "0.215.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.215.0.tgz#4670ee4ac65ad386bb2d955af9e96e6766aa1195"
+ integrity sha512-xrFlqhdhUyO8wSRn6DjE0145/HPWSJ5Nm0C7vWua6TdL/FSEAZvEyvdsa9CRXuxo9ebb7j/NEPhEcO62IJ0qUA==
+ dependencies:
+ "@opentelemetry/api" "^1.3.0"
+
"@opentelemetry/api@^1.3.0", "@opentelemetry/api@^1.9.0":
version "1.9.0"
resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe"
@@ -254,6 +282,13 @@
dependencies:
"@opentelemetry/semantic-conventions" "^1.29.0"
+"@opentelemetry/core@2.7.0":
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-2.7.0.tgz#41ebcd3033f69e48e719266524877f8fef75bc03"
+ integrity sha512-DT12SXVwV2eoJrGf4nnsvZojxxeQo+LlNAsoYGRRObPWTeN6APiqZ2+nqDCQDvQX40eLi1AePONS0onoASp3yQ==
+ dependencies:
+ "@opentelemetry/semantic-conventions" "^1.29.0"
+
"@opentelemetry/exporter-logs-otlp-grpc@0.203.0":
version "0.203.0"
resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.203.0.tgz#2f1254bea8f0dab0c974d791af23e0a8e9f5eecc"
@@ -349,7 +384,7 @@
"@opentelemetry/resources" "2.0.1"
"@opentelemetry/sdk-trace-base" "2.0.1"
-"@opentelemetry/exporter-trace-otlp-http@0.203.0", "@opentelemetry/exporter-trace-otlp-http@^0.203.0":
+"@opentelemetry/exporter-trace-otlp-http@0.203.0":
version "0.203.0"
resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.203.0.tgz#29908aac3ee4d085a17bb653dcee2778a9ba3bb9"
integrity sha512-ZDiaswNYo0yq/cy1bBLJFe691izEJ6IgNmkjm4C6kE9ub/OMQqDXORx2D2j8fzTBTxONyzusbaZlqtfmyqURPw==
@@ -360,6 +395,17 @@
"@opentelemetry/resources" "2.0.1"
"@opentelemetry/sdk-trace-base" "2.0.1"
+"@opentelemetry/exporter-trace-otlp-http@^0.215.0":
+ version "0.215.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.215.0.tgz#e4c40ae641f33216826a4550836ec3967c5d3084"
+ integrity sha512-k4J9ISeGpb0Bm/wCrlcrbroMFTkiWMrdhNxQGrlktxLy127Yzd4/7nrTawn5d/ApktYTknvdixsE6++34Qfi1w==
+ dependencies:
+ "@opentelemetry/core" "2.7.0"
+ "@opentelemetry/otlp-exporter-base" "0.215.0"
+ "@opentelemetry/otlp-transformer" "0.215.0"
+ "@opentelemetry/resources" "2.7.0"
+ "@opentelemetry/sdk-trace-base" "2.7.0"
+
"@opentelemetry/exporter-trace-otlp-proto@0.203.0", "@opentelemetry/exporter-trace-otlp-proto@^0.203.0":
version "0.203.0"
resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.203.0.tgz#c8b15b7a9088e2580a8dd2c3e057845dfe990100"
@@ -398,6 +444,14 @@
"@opentelemetry/core" "2.0.1"
"@opentelemetry/otlp-transformer" "0.203.0"
+"@opentelemetry/otlp-exporter-base@0.215.0":
+ version "0.215.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.215.0.tgz#a42eb76242dcc08bb472f4b16477f6f30d6daa5a"
+ integrity sha512-lHrfbmeLSmesGSkkHiqDwOzfaEMSWXdc7q6UoLfbW8byONCb+bE/zkAr0kapN4US1baT/2nbpNT7Cn9XoB96Vg==
+ dependencies:
+ "@opentelemetry/core" "2.7.0"
+ "@opentelemetry/otlp-transformer" "0.215.0"
+
"@opentelemetry/otlp-grpc-exporter-base@0.203.0":
version "0.203.0"
resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.203.0.tgz#0600151f3eb70f05923f621afaf9ac72ae213261"
@@ -421,6 +475,19 @@
"@opentelemetry/sdk-trace-base" "2.0.1"
protobufjs "^7.3.0"
+"@opentelemetry/otlp-transformer@0.215.0":
+ version "0.215.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-transformer/-/otlp-transformer-0.215.0.tgz#69de6ae54d1db685a8cf85472be36d9099919fff"
+ integrity sha512-cWwBvaV+vkXHkSoTYR8hGw+AW03UlgTr6xtrUKOMeum3T+8vffYXIfXu6KY5MLu8O9QtoBKqaKWw9I5xoOepng==
+ dependencies:
+ "@opentelemetry/api-logs" "0.215.0"
+ "@opentelemetry/core" "2.7.0"
+ "@opentelemetry/resources" "2.7.0"
+ "@opentelemetry/sdk-logs" "0.215.0"
+ "@opentelemetry/sdk-metrics" "2.7.0"
+ "@opentelemetry/sdk-trace-base" "2.7.0"
+ protobufjs "^8.0.1"
+
"@opentelemetry/propagator-b3@2.0.1":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@opentelemetry/propagator-b3/-/propagator-b3-2.0.1.tgz#0b2875724a9c3f8353366e05cc2f701763faa940"
@@ -451,6 +518,14 @@
"@opentelemetry/core" "2.3.0"
"@opentelemetry/semantic-conventions" "^1.29.0"
+"@opentelemetry/resources@2.7.0":
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-2.7.0.tgz#82abff22253c06a73bd392e218645d1ccf197c91"
+ integrity sha512-K+oi0hNMv94EpZbnW3eyu2X6SGVpD3O5DhG2NIp65Hc7lhAj9brRXTAVzh3wB82+q3ThakEf7Zd7RsFUqcTc7A==
+ dependencies:
+ "@opentelemetry/core" "2.7.0"
+ "@opentelemetry/semantic-conventions" "^1.29.0"
+
"@opentelemetry/sdk-logs@0.203.0":
version "0.203.0"
resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-logs/-/sdk-logs-0.203.0.tgz#01bc7c0549929d2864af2ab0ba23fd5ce02b5b0a"
@@ -460,6 +535,16 @@
"@opentelemetry/core" "2.0.1"
"@opentelemetry/resources" "2.0.1"
+"@opentelemetry/sdk-logs@0.215.0":
+ version "0.215.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-logs/-/sdk-logs-0.215.0.tgz#cf8ca6fd558484eb4b2366d604b9e1a2a77775f2"
+ integrity sha512-y3ucOmphzc4vgBTyIGchs+N/1rkACmoka8QalT2z1LBNM232Z17zMYayHcMl+dgMoOadZ0b72UZv7mDtqy1cFA==
+ dependencies:
+ "@opentelemetry/api-logs" "0.215.0"
+ "@opentelemetry/core" "2.7.0"
+ "@opentelemetry/resources" "2.7.0"
+ "@opentelemetry/semantic-conventions" "^1.29.0"
+
"@opentelemetry/sdk-metrics@2.0.1":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-metrics/-/sdk-metrics-2.0.1.tgz#efb6e9349e8a9038ac622e172692bfcdcad8010b"
@@ -468,6 +553,14 @@
"@opentelemetry/core" "2.0.1"
"@opentelemetry/resources" "2.0.1"
+"@opentelemetry/sdk-metrics@2.7.0":
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-metrics/-/sdk-metrics-2.7.0.tgz#0bcfa214e85eb78c882d109fda3c2f09eb9e051c"
+ integrity sha512-Vd7h95av/LYRsAVN7wbprvvJnHkq7swMXAo7Uad0Uxf9jl6NSReLa0JNivrcc5BVIx/vl2t+cgdVQQbnVhsR9w==
+ dependencies:
+ "@opentelemetry/core" "2.7.0"
+ "@opentelemetry/resources" "2.7.0"
+
"@opentelemetry/sdk-node@^0.203.0":
version "0.203.0"
resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-node/-/sdk-node-0.203.0.tgz#16f4a77031834c32ff1b6864873db7169791fd14"
@@ -514,6 +607,15 @@
"@opentelemetry/resources" "2.3.0"
"@opentelemetry/semantic-conventions" "^1.29.0"
+"@opentelemetry/sdk-trace-base@2.7.0":
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.0.tgz#b2290b43fe9252f85fc37a243852a14bff110a85"
+ integrity sha512-Yg9zEXJB50DLVLpsKPk7NmNqlPlS+OvqhJGh0A8oawIOTPOwlm4eXs9BMJV7L79lvEwI+dWtAj+YjTyddV336A==
+ dependencies:
+ "@opentelemetry/core" "2.7.0"
+ "@opentelemetry/resources" "2.7.0"
+ "@opentelemetry/semantic-conventions" "^1.29.0"
+
"@opentelemetry/sdk-trace-node@2.0.1":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-node/-/sdk-trace-node-2.0.1.tgz#bbb9bdb4985d7930941b3d4023e1661ba46f60c1"
@@ -532,18 +634,16 @@
"@opentelemetry/core" "2.3.0"
"@opentelemetry/sdk-trace-base" "2.3.0"
-"@opentelemetry/semantic-conventions@^1.29.0", "@opentelemetry/semantic-conventions@^1.36.0":
+"@opentelemetry/semantic-conventions@^1.22.0", "@opentelemetry/semantic-conventions@^1.38.0", "@opentelemetry/semantic-conventions@^1.40.0":
+ version "1.43.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz#f3f467e36c27332f0e735ec86cdcd78dd6f27865"
+ integrity sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==
+
+"@opentelemetry/semantic-conventions@^1.29.0":
version "1.38.0"
resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.38.0.tgz#8b5f415395a7ddb7c8e0c7932171deb9278df1a3"
integrity sha512-kocjix+/sSggfJhwXqClZ3i9Y/MI0fp7b+g7kCRm6psy2dsf8uApTRclwG18h8Avm7C9+fnt+O36PspJ/OzoWg==
-"@posthog/core@1.9.1":
- version "1.9.1"
- resolved "https://registry.yarnpkg.com/@posthog/core/-/core-1.9.1.tgz#bcc5392359b8413c2de19181c081fcc0475ab784"
- integrity sha512-kRb1ch2dhQjsAapZmu6V66551IF2LnCbc1rnrQqnR7ArooVyJN9KOPXre16AJ3ObJz2eTfuP7x25BMyS2Y5Exw==
- dependencies:
- cross-spawn "^7.0.6"
-
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
@@ -597,159 +697,203 @@
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==
+"@standard-schema/spec@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@standard-schema/spec/-/spec-1.1.0.tgz#a79b55dbaf8604812f52d140b2c9ab41bc150bb8"
+ integrity sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==
+
"@tootallnate/once@2":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
-"@traceloop/ai-semantic-conventions@0.14.0":
- version "0.14.0"
- resolved "https://registry.yarnpkg.com/@traceloop/ai-semantic-conventions/-/ai-semantic-conventions-0.14.0.tgz#1bb37b72fba84d8cacc14a34c5d82974c47f629e"
- integrity sha512-0hpu19rwFNXeYp7B3s0s+9Jo4TqYiDvbQYpzIU5Xu0tx4HUhbocaJEVwWrLJMwFDx7PMPkMu2M1Vte09OtipWw==
+"@traceloop/ai-semantic-conventions@0.26.0":
+ version "0.26.0"
+ resolved "https://registry.yarnpkg.com/@traceloop/ai-semantic-conventions/-/ai-semantic-conventions-0.26.0.tgz#b5d106ef4639e311872037e689a6205c27d9c014"
+ integrity sha512-Ict2OXBDw58Ij3WgHZqtloHkDsjVmm6MRsrehsfPfSg4rJk5HQc1ZIRwssFsjSbly6k6WXE//1U9lA61tZj4mg==
dependencies:
"@opentelemetry/api" "^1.9.0"
+ "@opentelemetry/semantic-conventions" "^1.40.0"
-"@traceloop/instrumentation-anthropic@0.14.6":
- version "0.14.6"
- resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-anthropic/-/instrumentation-anthropic-0.14.6.tgz#4931a2a8ddb15fc3905b69531faf017f0a908fbd"
- integrity sha512-7AmPZJVh2THCumGjCq8FcVDw1YQR3K0xM6woTODZlfxRwnr3bdMtbTkZs7IwFFxF1932n47cIFl6AfX3cTwSSA==
+"@traceloop/instrumentation-anthropic@0.26.0":
+ version "0.26.0"
+ resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-anthropic/-/instrumentation-anthropic-0.26.0.tgz#003af80304ecbb7071567af6fde29cbaf4b380ce"
+ integrity sha512-esZbo2F3uEanIs6SU6hyt1sRlHRUnWIuTu29b72QXWT7XzS8l2TAY1usMNUT86W7CGVWZOHR4BT0B/tdoIijVA==
dependencies:
"@opentelemetry/api" "^1.9.0"
"@opentelemetry/core" "^2.0.1"
"@opentelemetry/instrumentation" "^0.203.0"
- "@opentelemetry/semantic-conventions" "^1.36.0"
- "@traceloop/ai-semantic-conventions" "0.14.0"
+ "@opentelemetry/semantic-conventions" "^1.40.0"
+ "@traceloop/ai-semantic-conventions" "0.26.0"
+ "@traceloop/instrumentation-utils" "0.26.0"
tslib "^2.8.1"
-"@traceloop/instrumentation-bedrock@0.14.6":
- version "0.14.6"
- resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-bedrock/-/instrumentation-bedrock-0.14.6.tgz#c5597f69c45f1b54c7b041f733359dc023be0eb2"
- integrity sha512-1vQj0moJZjrwk6h6GU17OgjN9MFLmO0jMV2uaaBJAUT9dZuNTBbwhQN20zQssWXI5vPHCtok+JQM1DG2rI14cg==
+"@traceloop/instrumentation-bedrock@0.26.0":
+ version "0.26.0"
+ resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-bedrock/-/instrumentation-bedrock-0.26.0.tgz#8fbf6f5b5c5406741ada63762ea05922272c895d"
+ integrity sha512-SNTRyqmQHpH2CN7R3m3+aanYOqOzAhr0Orbbzx+mOonsUuXY+Yo7IiejwOu0exPudx+7czbUV1JbvDC1hjYZKQ==
dependencies:
"@opentelemetry/api" "^1.9.0"
"@opentelemetry/core" "^2.0.1"
"@opentelemetry/instrumentation" "^0.203.0"
- "@opentelemetry/semantic-conventions" "^1.36.0"
- "@traceloop/ai-semantic-conventions" "0.14.0"
+ "@opentelemetry/semantic-conventions" "^1.40.0"
+ "@traceloop/ai-semantic-conventions" "0.26.0"
+ "@traceloop/instrumentation-utils" "0.26.0"
tslib "^2.8.1"
-"@traceloop/instrumentation-chromadb@0.14.6":
- version "0.14.6"
- resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-chromadb/-/instrumentation-chromadb-0.14.6.tgz#1f1c14250c9a7b66f98e8178402723bbb7c588ec"
- integrity sha512-/GfMEIOaz+Za1E2Ef0lhMmBADnZdDZgY16uescNxole4IKjPV7/VYIzd6ZZcDq5/YebpHCXyJWeg6cAbFrfRUw==
+"@traceloop/instrumentation-chromadb@0.26.0":
+ version "0.26.0"
+ resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-chromadb/-/instrumentation-chromadb-0.26.0.tgz#55511620d0b7ebcd828e12b361b7e3498cec1f1b"
+ integrity sha512-eFu/Zwj5IblMRWzQblXO0mtUXWSylB08RSJzfj0gM2zU7TlHk7iz+NZHhvldTee39+wIqHIVPc6//d0UwB8+kQ==
dependencies:
"@opentelemetry/api" "^1.9.0"
"@opentelemetry/core" "^2.0.1"
"@opentelemetry/instrumentation" "^0.203.0"
- "@opentelemetry/semantic-conventions" "^1.36.0"
- "@traceloop/ai-semantic-conventions" "0.14.0"
+ "@opentelemetry/semantic-conventions" "^1.38.0"
+ "@traceloop/ai-semantic-conventions" "0.26.0"
tslib "^2.8.1"
-"@traceloop/instrumentation-cohere@0.14.6":
- version "0.14.6"
- resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-cohere/-/instrumentation-cohere-0.14.6.tgz#be0e6ea88e78aa43cdae36c89ff6763bff001395"
- integrity sha512-y9cjDZDS2o0yL7ei1H+wzl8ZgzjxDyzuUrAW18O5KXvX9W2we7RrJAyqdLQ48q5pb2uK9+W9qwTsdv8PkHBHkQ==
+"@traceloop/instrumentation-cohere@0.26.0":
+ version "0.26.0"
+ resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-cohere/-/instrumentation-cohere-0.26.0.tgz#19abacc417fe883b8200ab449b30e2b4cd0e2d70"
+ integrity sha512-fdPq8kiL2gzHzJIwJXF2Ffw6J3jm5V9L1m6gqNHCQ8tSBT5WPwzHmN+OPCknq1/oaBaymWyepSYRn/8wOzov6g==
dependencies:
"@opentelemetry/api" "^1.9.0"
"@opentelemetry/core" "^2.0.1"
"@opentelemetry/instrumentation" "^0.203.0"
- "@opentelemetry/semantic-conventions" "^1.36.0"
- "@traceloop/ai-semantic-conventions" "0.14.0"
+ "@opentelemetry/semantic-conventions" "^1.38.0"
+ "@traceloop/ai-semantic-conventions" "0.26.0"
tslib "^2.8.1"
-"@traceloop/instrumentation-langchain@0.14.6":
- version "0.14.6"
- resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-langchain/-/instrumentation-langchain-0.14.6.tgz#322ec1e0417dfb2f6f7abeef1d0069b7f70bb944"
- integrity sha512-yxtpLsYCE+hqeV3J3F7HvBls4OZ3XUzhISXQK1gMzXKRPwn8hB0frPivZ3mNtnqI4i+Lq6hALO3jl/Pqel7hMA==
+"@traceloop/instrumentation-google-generativeai@0.26.0":
+ version "0.26.0"
+ resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-google-generativeai/-/instrumentation-google-generativeai-0.26.0.tgz#8f1ab4dccea0a2d4efda97525cb8697b0964fd2b"
+ integrity sha512-26aiuE+e7hMol/vJDYVEynB86PFPZVdAdHHwxNZdEba6ASGo7EZvJYcvjHImP8dJVgOVP2en7YquJ0+TXUd0Yg==
dependencies:
- "@langchain/core" "^0.3.58"
"@opentelemetry/api" "^1.9.0"
"@opentelemetry/core" "^2.0.1"
"@opentelemetry/instrumentation" "^0.203.0"
- "@opentelemetry/semantic-conventions" "^1.36.0"
- "@traceloop/ai-semantic-conventions" "0.14.0"
+ "@opentelemetry/semantic-conventions" "^1.40.0"
+ "@traceloop/ai-semantic-conventions" "0.26.0"
+ "@traceloop/instrumentation-utils" "0.26.0"
tslib "^2.8.1"
-"@traceloop/instrumentation-llamaindex@0.14.6":
- version "0.14.6"
- resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-llamaindex/-/instrumentation-llamaindex-0.14.6.tgz#80c739702056ec2bfdca39127d0f89fc743cbae2"
- integrity sha512-Pp519YHEilHjMJviNxS6NTlN9aZGXNQgDCpbaWv0cPp116arR6LlMB+K57wwaDDRmk7QzYsQgtEN0BuuuOjCnQ==
+"@traceloop/instrumentation-langchain@0.26.0":
+ version "0.26.0"
+ resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-langchain/-/instrumentation-langchain-0.26.0.tgz#d6c8f3c20b34bfa6b04bf9b7d0cddd57381b9918"
+ integrity sha512-WY8ZUXP51ZM0NwYiCupzEYyA/D2lw4LZi3bQ3NQRGjNTCaj/BEF1Ho9R8HpYSvBn/kJnbwsnGsxqgu1+fex6ig==
dependencies:
+ "@langchain/core" ">=1.0.0 <2.0.0"
"@opentelemetry/api" "^1.9.0"
"@opentelemetry/core" "^2.0.1"
"@opentelemetry/instrumentation" "^0.203.0"
- "@opentelemetry/semantic-conventions" "^1.36.0"
- "@traceloop/ai-semantic-conventions" "0.14.0"
+ "@opentelemetry/semantic-conventions" "^1.40.0"
+ "@traceloop/ai-semantic-conventions" "0.26.0"
+ tslib "^2.8.1"
+
+"@traceloop/instrumentation-llamaindex@0.26.0":
+ version "0.26.0"
+ resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-llamaindex/-/instrumentation-llamaindex-0.26.0.tgz#8355e798ec064be9084ee1fff4f56f06f82ee202"
+ integrity sha512-hT9eB288hyhNmNoxXT7C+jzGq9W/nKe4qAZw8tsWZoxvNUapUda1ppd9aacVhJky2sW9++rSgxZPmoCVgqzpWA==
+ dependencies:
+ "@opentelemetry/api" "^1.9.0"
+ "@opentelemetry/core" "^2.0.1"
+ "@opentelemetry/instrumentation" "^0.203.0"
+ "@opentelemetry/semantic-conventions" "^1.40.0"
+ "@traceloop/ai-semantic-conventions" "0.26.0"
+ "@traceloop/instrumentation-utils" "0.26.0"
lodash "^4.17.21"
tslib "^2.8.1"
-"@traceloop/instrumentation-openai@0.14.6":
- version "0.14.6"
- resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-openai/-/instrumentation-openai-0.14.6.tgz#35e8c77ab31fb9cf45335cc531115b6cb4de81de"
- integrity sha512-WGFxbRf1Rn6+Pl+sOuLSJVGSyD/g7XhRFJ2X9qdapu+XRThcPboxwFMYaG7j6rLj5fxXDLqfuzwZJ0IRzmdIYA==
+"@traceloop/instrumentation-mcp@0.26.0":
+ version "0.26.0"
+ resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-mcp/-/instrumentation-mcp-0.26.0.tgz#9f930c01b85ef15620099ca74429c596cec4796d"
+ integrity sha512-1xZZvAryZU/lWhagpnqQ+PULfpRnUc0mupp1BVso2fqJaISxBbJnUtWSUxHSZwcsHaWMz4nQ9NeZue/dnPBswQ==
dependencies:
"@opentelemetry/api" "^1.9.0"
"@opentelemetry/core" "^2.0.1"
"@opentelemetry/instrumentation" "^0.203.0"
- "@opentelemetry/semantic-conventions" "^1.36.0"
- "@traceloop/ai-semantic-conventions" "0.14.0"
+ "@opentelemetry/semantic-conventions" "^1.38.0"
+ "@traceloop/ai-semantic-conventions" "0.26.0"
+ tslib "^2.8.1"
+
+"@traceloop/instrumentation-openai@0.26.0":
+ version "0.26.0"
+ resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-openai/-/instrumentation-openai-0.26.0.tgz#4c36dff3460a358f98f4005f826b9c24c4e02b4a"
+ integrity sha512-ekFOgNLlb6VlxD30nCEH0dl2OgiWTWovZzMJJP80hH5hOgU9N20RJ468OtxVjlyw3PoU6iPVtU9UBsDsLhTfgQ==
+ dependencies:
+ "@opentelemetry/api" "^1.9.0"
+ "@opentelemetry/core" "^2.0.1"
+ "@opentelemetry/instrumentation" "^0.203.0"
+ "@opentelemetry/semantic-conventions" "^1.40.0"
+ "@traceloop/ai-semantic-conventions" "0.26.0"
+ "@traceloop/instrumentation-utils" "0.26.0"
js-tiktoken "^1.0.20"
tslib "^2.8.1"
-"@traceloop/instrumentation-pinecone@0.14.6":
- version "0.14.6"
- resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-pinecone/-/instrumentation-pinecone-0.14.6.tgz#027fd6386998deea15e257fb2fbf86ac711e165c"
- integrity sha512-ztEbjSGcaiRL56QXknJoBSCts19fNXzuMvRpb5eMgNxzMif0kCqZnurrjky6dqDJxtxI0rzQ5mCOpXLqd+D9mA==
+"@traceloop/instrumentation-pinecone@0.26.0":
+ version "0.26.0"
+ resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-pinecone/-/instrumentation-pinecone-0.26.0.tgz#2ad6c0890a4055212016e4eb92b48ae8ef2d188a"
+ integrity sha512-2Dbhf1RvWFb/9gTf76c4bSbgTVP6yZBAb5qiIujfvIm3YTRC7coLfxKxzXaHGH3RF2fCdPxV6IIVFVHOAtCO/w==
dependencies:
"@opentelemetry/api" "^1.9.0"
"@opentelemetry/core" "^2.0.1"
"@opentelemetry/instrumentation" "^0.203.0"
- "@opentelemetry/semantic-conventions" "^1.36.0"
- "@traceloop/ai-semantic-conventions" "0.14.0"
+ "@opentelemetry/semantic-conventions" "^1.38.0"
+ "@traceloop/ai-semantic-conventions" "0.26.0"
tslib "^2.8.1"
-"@traceloop/instrumentation-qdrant@0.14.6":
- version "0.14.6"
- resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-qdrant/-/instrumentation-qdrant-0.14.6.tgz#660ebe2c23fc5305f06caf1edc86a6f5f021b75a"
- integrity sha512-jdi9BW4O9Yjc79T4UJBnsp041xS6QbgQssmvRZ3LlZ4g1jfk+QBGM6FFBGbgx9m4lWV0tys4SP5q7p9aFENtqw==
+"@traceloop/instrumentation-qdrant@0.26.0":
+ version "0.26.0"
+ resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-qdrant/-/instrumentation-qdrant-0.26.0.tgz#63e7d8567a3af232448df1e6daf20360c45596d5"
+ integrity sha512-ZDU8C1wNrYhIVaAcwcm/ukDUSgLWvfZjYhCZxtXlOjeWMjodBUGR2/OrtYgjN68IbfM8dJukXHXj6uzS2S2/tw==
dependencies:
"@opentelemetry/api" "^1.9.0"
"@opentelemetry/core" "^2.0.1"
"@opentelemetry/instrumentation" "^0.203.0"
- "@traceloop/ai-semantic-conventions" "0.14.0"
+ "@traceloop/ai-semantic-conventions" "0.26.0"
tslib "^2.8.1"
-"@traceloop/instrumentation-together@0.14.6":
- version "0.14.6"
- resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-together/-/instrumentation-together-0.14.6.tgz#4312878d6265f51080bf54146b994ec07614910e"
- integrity sha512-P/YtcIT8c8Ua26ksL3Vn5/a3KgYBCx6aUonWdzR5bkDWyJClLAxmbgrbj+Qx/Pad19U9BlpiZBhGCdT8upOpcg==
+"@traceloop/instrumentation-together@0.26.0":
+ version "0.26.0"
+ resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-together/-/instrumentation-together-0.26.0.tgz#4311fccc5e2c739c5c0d9d8236c6d09cbb30bc63"
+ integrity sha512-pLkQI8WUAEeJmWxILhZNGpn6NBtfrFqXzIa+TWxJVlxdUtUCQ1XLbc2f5KOHuwGCATlmCO1uFs+GlVur8mqcDw==
dependencies:
"@opentelemetry/api" "^1.9.0"
"@opentelemetry/core" "^2.0.1"
"@opentelemetry/instrumentation" "^0.203.0"
- "@opentelemetry/semantic-conventions" "^1.36.0"
- "@traceloop/ai-semantic-conventions" "0.14.0"
+ "@opentelemetry/semantic-conventions" "^1.38.0"
+ "@traceloop/ai-semantic-conventions" "0.26.0"
js-tiktoken "^1.0.20"
tslib "^2.8.1"
-"@traceloop/instrumentation-vertexai@0.14.6":
- version "0.14.6"
- resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-vertexai/-/instrumentation-vertexai-0.14.6.tgz#61813187f9596a68ad731974eb31529d414bad0b"
- integrity sha512-OsxAsAz8+068M1N3CAdKxS2RkizcdKFaKagIP+lE94ANeWdlD7M7IIZ/d7yP/wdDWlQg6l5IodybnQVEyzTD/A==
+"@traceloop/instrumentation-utils@0.26.0":
+ version "0.26.0"
+ resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-utils/-/instrumentation-utils-0.26.0.tgz#e858162c4f902c0ae9e19dff910897fde5bfaa4a"
+ integrity sha512-9uPCUVeZzJ0xh9DogLWKXd+bZsjwh/XJfYeLG3fkoUgmj/4XaTVf3W3F/z3yjDBcUI0vHwOwe2vpg+nWBHXZFQ==
+ dependencies:
+ "@opentelemetry/semantic-conventions" "^1.40.0"
+ tslib "^2.8.1"
+
+"@traceloop/instrumentation-vertexai@0.26.0":
+ version "0.26.0"
+ resolved "https://registry.yarnpkg.com/@traceloop/instrumentation-vertexai/-/instrumentation-vertexai-0.26.0.tgz#7a2203f7ab3fa502366346a671daef04230c263f"
+ integrity sha512-ithoN+3GuVVgue1Dgaj3fad0lxMj9JZqirvrjgHaI92L1rrJhlsYghX4ak965/4Jd3Uc9VGjnJm+Pz+OENPeBw==
dependencies:
"@opentelemetry/api" "^1.9.0"
"@opentelemetry/core" "^2.0.1"
"@opentelemetry/instrumentation" "^0.203.0"
- "@opentelemetry/semantic-conventions" "^1.36.0"
- "@traceloop/ai-semantic-conventions" "0.14.0"
+ "@opentelemetry/semantic-conventions" "^1.38.0"
+ "@traceloop/ai-semantic-conventions" "0.26.0"
google-gax "^4.0.0"
tslib "^2.8.1"
-"@traceloop/node-server-sdk@^0.14.6":
- version "0.14.6"
- resolved "https://registry.yarnpkg.com/@traceloop/node-server-sdk/-/node-server-sdk-0.14.6.tgz#a7f3210c887c17f6f32b7e2620e6c02541776175"
- integrity sha512-RRNsXCh+3Qy4lE/e7b3LmXpyeVASBUkWw5TTm4HxWJu9pHsyEcEKFV7EAmkh+s6gQomB03ZA4ifT9Pem6bR+vA==
+"@traceloop/node-server-sdk@^0.26.0":
+ version "0.26.0"
+ resolved "https://registry.yarnpkg.com/@traceloop/node-server-sdk/-/node-server-sdk-0.26.0.tgz#74f247760d7050e6611d8846e6070dad7ecbc08c"
+ integrity sha512-0m1fD58kl73n62IodjOx8rjz3hE5mOyy/kv5S7Fq/DS09lyrH7N7VcR2PCQpzDXKLm2Mv0PnYNqVBaVTK2WRfA==
dependencies:
+ "@google-cloud/opentelemetry-cloud-trace-exporter" "^3.0.0"
"@opentelemetry/api" "^1.9.0"
"@opentelemetry/core" "^2.0.1"
"@opentelemetry/exporter-trace-otlp-proto" "^0.203.0"
@@ -758,25 +902,31 @@
"@opentelemetry/sdk-node" "^0.203.0"
"@opentelemetry/sdk-trace-base" "^2.0.1"
"@opentelemetry/sdk-trace-node" "^2.0.1"
- "@opentelemetry/semantic-conventions" "^1.36.0"
- "@traceloop/ai-semantic-conventions" "0.14.0"
- "@traceloop/instrumentation-anthropic" "0.14.6"
- "@traceloop/instrumentation-bedrock" "0.14.6"
- "@traceloop/instrumentation-chromadb" "0.14.6"
- "@traceloop/instrumentation-cohere" "0.14.6"
- "@traceloop/instrumentation-langchain" "0.14.6"
- "@traceloop/instrumentation-llamaindex" "0.14.6"
- "@traceloop/instrumentation-openai" "0.14.6"
- "@traceloop/instrumentation-pinecone" "0.14.6"
- "@traceloop/instrumentation-qdrant" "0.14.6"
- "@traceloop/instrumentation-together" "0.14.6"
- "@traceloop/instrumentation-vertexai" "0.14.6"
+ "@opentelemetry/semantic-conventions" "^1.40.0"
+ "@traceloop/ai-semantic-conventions" "0.26.0"
+ "@traceloop/instrumentation-anthropic" "0.26.0"
+ "@traceloop/instrumentation-bedrock" "0.26.0"
+ "@traceloop/instrumentation-chromadb" "0.26.0"
+ "@traceloop/instrumentation-cohere" "0.26.0"
+ "@traceloop/instrumentation-google-generativeai" "0.26.0"
+ "@traceloop/instrumentation-langchain" "0.26.0"
+ "@traceloop/instrumentation-llamaindex" "0.26.0"
+ "@traceloop/instrumentation-mcp" "0.26.0"
+ "@traceloop/instrumentation-openai" "0.26.0"
+ "@traceloop/instrumentation-pinecone" "0.26.0"
+ "@traceloop/instrumentation-qdrant" "0.26.0"
+ "@traceloop/instrumentation-together" "0.26.0"
+ "@traceloop/instrumentation-utils" "0.26.0"
+ "@traceloop/instrumentation-vertexai" "0.26.0"
"@types/nunjucks" "^3.2.6"
cross-fetch "^4.1.0"
+ eventsource "^3.0.2"
fetch-retry "^6.0.0"
+ mime-types "^3.0.2"
nunjucks "^3.2.4"
- posthog-node "^5.5.1"
+ papaparse "^5.5.3"
supports-color "^10.0.0"
+ tslib "^2.8.1"
uuid "^11.1.0"
"@types/body-parser@*":
@@ -834,14 +984,6 @@
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690"
integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==
-"@types/node-fetch@^2.6.4":
- version "2.6.13"
- resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.13.tgz#e0c9b7b5edbdb1b50ce32c127e85e880872d56ee"
- integrity sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==
- dependencies:
- "@types/node" "*"
- form-data "^4.0.4"
-
"@types/node@*", "@types/node@>=13.7.0":
version "25.0.8"
resolved "https://registry.yarnpkg.com/@types/node/-/node-25.0.8.tgz#e54e00f94fe1db2497b3e42d292b8376a2678c8d"
@@ -849,13 +991,6 @@
dependencies:
undici-types "~7.16.0"
-"@types/node@^18.11.18":
- version "18.19.130"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.130.tgz#da4c6324793a79defb7a62cba3947ec5add00d59"
- integrity sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==
- dependencies:
- undici-types "~5.26.4"
-
"@types/node@^22.7.4":
version "22.19.6"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.19.6.tgz#0e9d80ebcd2dfce03265768c17a1212d4eb07e82"
@@ -888,11 +1023,6 @@
"@types/tough-cookie" "*"
form-data "^2.5.5"
-"@types/retry@0.12.0":
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d"
- integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==
-
"@types/send@*":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@types/send/-/send-1.2.1.tgz#6a784e45543c18c774c049bff6d3dbaf045c9c74"
@@ -922,11 +1052,6 @@
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304"
integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==
-"@types/uuid@^10.0.0":
- version "10.0.0"
- resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-10.0.0.tgz#e9c07fe50da0f53dc24970cca94d619ff03f6f6d"
- integrity sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==
-
a-sync-waterfall@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz#75b6b6aa72598b497a125e7a2770f14f4c8a1fa7"
@@ -969,30 +1094,18 @@ agent-base@^7.1.2:
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8"
integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==
-agentkeepalive@^4.2.1:
- version "4.6.0"
- resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.6.0.tgz#35f73e94b3f40bf65f105219c623ad19c136ea6a"
- integrity sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==
- dependencies:
- humanize-ms "^1.2.1"
-
ansi-regex@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
-ansi-styles@^4.0.0, ansi-styles@^4.1.0:
+ansi-styles@^4.0.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
dependencies:
color-convert "^2.0.1"
-ansi-styles@^5.0.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b"
- integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==
-
array-flatten@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
@@ -1089,19 +1202,6 @@ call-bound@^1.0.2:
call-bind-apply-helpers "^1.0.2"
get-intrinsic "^1.3.0"
-camelcase@6:
- version "6.3.0"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
- integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
-
-chalk@^4.1.2:
- version "4.1.2"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
- integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
- dependencies:
- ansi-styles "^4.1.0"
- supports-color "^7.1.0"
-
cjs-module-lexer@^1.2.2:
version "1.4.3"
resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz#0f79731eb8cfe1ec72acd4066efac9d61991b00d"
@@ -1140,13 +1240,6 @@ commander@^5.1.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
-console-table-printer@^2.12.1:
- version "2.15.0"
- resolved "https://registry.yarnpkg.com/console-table-printer/-/console-table-printer-2.15.0.tgz#5c808204640b8f024d545bde8aabe5d344dfadc1"
- integrity sha512-SrhBq4hYVjLCkBVOWaTzceJalvn5K1Zq5aQA6wXC/cYjI3frKWNPEMK3sZsJfNNQApvCQmgBcc13ZKmFj8qExw==
- dependencies:
- simple-wcswidth "^1.1.2"
-
content-disposition@0.5.4, content-disposition@~0.5.4:
version "0.5.4"
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe"
@@ -1186,14 +1279,10 @@ cross-fetch@^4.1.0:
dependencies:
node-fetch "^2.7.0"
-cross-spawn@^7.0.6:
- version "7.0.6"
- resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
- integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
- dependencies:
- path-key "^3.1.0"
- shebang-command "^2.0.0"
- which "^2.0.1"
+data-uri-to-buffer@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e"
+ integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==
debug@2.6.9:
version "2.6.9"
@@ -1209,11 +1298,6 @@ debug@4, debug@^4.3.5:
dependencies:
ms "^2.1.3"
-decamelize@1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
- integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==
-
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
@@ -1371,6 +1455,18 @@ eventemitter3@^4.0.4:
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
+eventsource-parser@^3.0.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/eventsource-parser/-/eventsource-parser-3.1.1.tgz#b96cbb7dace4f3774f58a9e3b1ae9a4a524872e2"
+ integrity sha512-EKN1vKAMcZ8MlYMpaNuxN6R9yakzH6uajHcHVTqWJzvu5pWw9DyhbP35HH8MVBQ+dZjAfDxk+A8NiR9KWaXiyQ==
+
+eventsource@^3.0.2:
+ version "3.0.7"
+ resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-3.0.7.tgz#1157622e2f5377bb6aef2114372728ba0c156989"
+ integrity sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==
+ dependencies:
+ eventsource-parser "^3.0.1"
+
express@4.21.2:
version "4.21.2"
resolved "https://registry.yarnpkg.com/express/-/express-4.21.2.tgz#cf250e48362174ead6cea4a566abef0162c1ec32"
@@ -1450,6 +1546,14 @@ extend@^3.0.2:
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
+fetch-blob@^3.1.2, fetch-blob@^3.1.4:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9"
+ integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==
+ dependencies:
+ node-domexception "^1.0.0"
+ web-streams-polyfill "^3.0.3"
+
fetch-retry@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/fetch-retry/-/fetch-retry-6.0.0.tgz#4ffdf92c834d72ae819e42a4ee2a63f1e9454426"
@@ -1486,11 +1590,6 @@ follow-redirects@^1.15.6:
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.11.tgz#777d73d72a92f8ec4d2e410eb47352a56b8e8340"
integrity sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==
-form-data-encoder@1.7.2:
- version "1.7.2"
- resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-1.7.2.tgz#1f1ae3dccf58ed4690b86d87e4f57c654fbab040"
- integrity sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==
-
form-data@^2.5.5:
version "2.5.5"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.5.tgz#a5f6364ad7e4e67e95b4a07e2d8c6f711c74f624"
@@ -1514,13 +1613,12 @@ form-data@^4.0.4:
hasown "^2.0.2"
mime-types "^2.1.12"
-formdata-node@^4.3.2:
- version "4.4.1"
- resolved "https://registry.yarnpkg.com/formdata-node/-/formdata-node-4.4.1.tgz#23f6a5cb9cb55315912cbec4ff7b0f59bbd191e2"
- integrity sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==
+formdata-polyfill@^4.0.10:
+ version "4.0.10"
+ resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423"
+ integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==
dependencies:
- node-domexception "1.0.0"
- web-streams-polyfill "4.0.0-beta.3"
+ fetch-blob "^3.1.2"
forwarded@0.2.0:
version "0.2.0"
@@ -1553,6 +1651,24 @@ gaxios@^6.0.0, gaxios@^6.1.1:
node-fetch "^2.6.9"
uuid "^9.0.1"
+gaxios@^7.0.0, gaxios@^7.1.3, gaxios@^7.1.4:
+ version "7.3.1"
+ resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-7.3.1.tgz#b26223db05856dfa5e2393ea376abad00e479c62"
+ integrity sha512-kB3rzJV7d9juLZh8/56QTXCwQfxyhdOMdyYk1HdQKFtF8TJTDTZQJtixWIwXdE9Jji91mC41DUNpjleo4L4eAQ==
+ dependencies:
+ extend "^3.0.2"
+ https-proxy-agent "^7.0.1"
+ node-fetch "^3.3.2"
+
+gcp-metadata@8.1.2:
+ version "8.1.2"
+ resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-8.1.2.tgz#e62e3373ddf41fc727ccc31c55c687b798bee898"
+ integrity sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==
+ dependencies:
+ gaxios "^7.0.0"
+ google-logging-utils "^1.0.0"
+ json-bigint "^1.0.0"
+
gcp-metadata@^6.1.0:
version "6.1.1"
resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-6.1.1.tgz#f65aa69f546bc56e116061d137d3f5f90bdec494"
@@ -1562,6 +1678,15 @@ gcp-metadata@^6.1.0:
google-logging-utils "^0.0.2"
json-bigint "^1.0.0"
+gcp-metadata@^9.0.0:
+ version "9.0.3"
+ resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-9.0.3.tgz#d8ed78f75b3c842d8cf5c2b8e73e28e2fd80f17f"
+ integrity sha512-2YYnIlHaKBGT2IPg3G2M57hia9Galz15zsEOvw9T3oRf0lSn6KN6VcHQLqby7x8ksYKnjXvp3rp2KJyLCN6zfQ==
+ dependencies:
+ gaxios "^7.1.3"
+ google-logging-utils "^2.0.0"
+ json-bigint "^1.0.0"
+
get-caller-file@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
@@ -1598,6 +1723,18 @@ get-tsconfig@^4.7.5:
dependencies:
resolve-pkg-maps "^1.0.0"
+google-auth-library@^10.0.0:
+ version "10.9.1"
+ resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-10.9.1.tgz#af9852a328a6077e8ffbe776681b4ca9420a1714"
+ integrity sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw==
+ dependencies:
+ base64-js "^1.3.0"
+ ecdsa-sig-formatter "^1.0.11"
+ gaxios "^7.1.4"
+ gcp-metadata "8.1.2"
+ google-logging-utils "1.1.3"
+ jws "^4.0.0"
+
google-auth-library@^9.3.0:
version "9.15.1"
resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-9.15.1.tgz#0c5d84ed1890b2375f1cd74f03ac7b806b392928"
@@ -1628,11 +1765,26 @@ google-gax@^4.0.0:
retry-request "^7.0.0"
uuid "^9.0.1"
+google-logging-utils@1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/google-logging-utils/-/google-logging-utils-1.1.3.tgz#17b71f1f95d266d2ddd356b8f00178433f041b17"
+ integrity sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==
+
google-logging-utils@^0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/google-logging-utils/-/google-logging-utils-0.0.2.tgz#5fd837e06fa334da450433b9e3e1870c1594466a"
integrity sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==
+google-logging-utils@^1.0.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/google-logging-utils/-/google-logging-utils-1.2.0.tgz#89dd643f986c765e61bfa2d01cada2292fe5bfd7"
+ integrity sha512-WE9av4wKDZgRjBwgVUabocx8T6/7o3Ca1Fat46FXDhXVAFibzNadedcOXrdgd1Kzmk8tsk/9ZH89Wyf/SqeZ3A==
+
+google-logging-utils@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/google-logging-utils/-/google-logging-utils-2.0.1.tgz#d78b34f4250db9ee816f29fee3321939296bcb8a"
+ integrity sha512-HMhaQghlOTvbcb3c4T5jmmOMtG3JUF1iOQMezaJXL86CDS+Tm2vHd0IeLFRAx3+ewd+bo9E1HFHoy17X5aJa9A==
+
gopd@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1"
@@ -1646,11 +1798,6 @@ gtoken@^7.0.0:
gaxios "^6.0.0"
jws "^4.0.0"
-has-flag@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
- integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
-
has-symbols@^1.0.3, has-symbols@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338"
@@ -1717,13 +1864,6 @@ https-proxy-agent@^7.0.1:
agent-base "^7.1.2"
debug "4"
-humanize-ms@^1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed"
- integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==
- dependencies:
- ms "^2.0.0"
-
iconv-lite@0.4.24, iconv-lite@~0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
@@ -1768,11 +1908,6 @@ is-stream@^2.0.0:
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
-isexe@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
- integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
-
jose@^5.2.4:
version "5.10.0"
resolved "https://registry.yarnpkg.com/jose/-/jose-5.10.0.tgz#c37346a099d6467c401351a9a0c2161e0f52c4be"
@@ -1814,17 +1949,12 @@ jws@^4.0.0:
jwa "^2.0.1"
safe-buffer "^5.0.1"
-langsmith@^0.3.67:
- version "0.3.87"
- resolved "https://registry.yarnpkg.com/langsmith/-/langsmith-0.3.87.tgz#f1c991c93a5d4d226a31671be7e4443b4b8673b1"
- integrity sha512-XXR1+9INH8YX96FKWc5tie0QixWz6tOqAsAKfcJyPkE0xPep+NDz0IQLR32q4bn10QK3LqD2HN6T3n6z1YLW7Q==
+"langsmith@>=0.5.0 <1.0.0":
+ version "0.10.1"
+ resolved "https://registry.yarnpkg.com/langsmith/-/langsmith-0.10.1.tgz#944d16ee0e43d621f11449c0deb6ee0edab0efce"
+ integrity sha512-zRDCnLznGdzx1VottX4CWr8v9ZZLRoSql2pbjEXYA1Jeg+NMDdq87x/v0Dk4GNkNZYhE+ZxFX3vTxwWq6W6gVA==
dependencies:
- "@types/uuid" "^10.0.0"
- chalk "^4.1.2"
- console-table-printer "^2.12.1"
- p-queue "^6.6.2"
- semver "^7.6.3"
- uuid "^10.0.0"
+ p-queue "6.6.2"
lodash.camelcase@^4.3.0:
version "4.3.0"
@@ -1836,7 +1966,7 @@ lodash@^4.17.21:
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
-long@^5.0.0:
+long@^5.0.0, long@^5.3.2:
version "5.3.2"
resolved "https://registry.yarnpkg.com/long/-/long-5.3.2.tgz#1d84463095999262d7d7b7f8bfd4a8cc55167f83"
integrity sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==
@@ -1866,6 +1996,11 @@ mime-db@1.52.0:
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
+mime-db@^1.54.0:
+ version "1.54.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5"
+ integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==
+
mime-types@^2.1.12, mime-types@^2.1.35, mime-types@~2.1.24, mime-types@~2.1.34:
version "2.1.35"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
@@ -1873,6 +2008,13 @@ mime-types@^2.1.12, mime-types@^2.1.35, mime-types@~2.1.24, mime-types@~2.1.34:
dependencies:
mime-db "1.52.0"
+mime-types@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-3.0.2.tgz#39002d4182575d5af036ffa118100f2524b2e2ab"
+ integrity sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==
+ dependencies:
+ mime-db "^1.54.0"
+
mime@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
@@ -1888,7 +2030,7 @@ ms@2.0.0:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
-ms@2.1.3, ms@^2.0.0, ms@^2.1.3:
+ms@2.1.3, ms@^2.1.3:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
@@ -1903,18 +2045,27 @@ negotiator@0.6.3:
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
-node-domexception@1.0.0:
+node-domexception@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5"
integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==
-node-fetch@^2.6.7, node-fetch@^2.6.9, node-fetch@^2.7.0:
+node-fetch@^2.6.9, node-fetch@^2.7.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
dependencies:
whatwg-url "^5.0.0"
+node-fetch@^3.3.2:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b"
+ integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==
+ dependencies:
+ data-uri-to-buffer "^4.0.0"
+ fetch-blob "^3.1.4"
+ formdata-polyfill "^4.0.10"
+
nunjucks@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/nunjucks/-/nunjucks-3.2.4.tgz#f0878eef528ce7b0aa35d67cc6898635fd74649e"
@@ -1948,25 +2099,12 @@ once@^1.4.0:
dependencies:
wrappy "1"
-openai@^4.77.0:
- version "4.104.0"
- resolved "https://registry.yarnpkg.com/openai/-/openai-4.104.0.tgz#c489765dc051b95019845dab64b0e5207cae4d30"
- integrity sha512-p99EFNsA/yX6UhVO93f5kJsDRLAg+CTA2RBqdHK4RtK8u5IJw32Hyb2dTGKbnnFmnuoBv5r7Z2CURI9sGZpSuA==
- dependencies:
- "@types/node" "^18.11.18"
- "@types/node-fetch" "^2.6.4"
- abort-controller "^3.0.0"
- agentkeepalive "^4.2.1"
- form-data-encoder "1.7.2"
- formdata-node "^4.3.2"
- node-fetch "^2.6.7"
-
p-finally@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==
-p-queue@^6.6.2:
+p-queue@6.6.2, p-queue@^6.6.2:
version "6.6.2"
resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-6.6.2.tgz#2068a9dcf8e67dd0ec3e7a2bcb76810faa85e426"
integrity sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==
@@ -1974,14 +2112,6 @@ p-queue@^6.6.2:
eventemitter3 "^4.0.4"
p-timeout "^3.2.0"
-p-retry@4:
- version "4.6.2"
- resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16"
- integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==
- dependencies:
- "@types/retry" "0.12.0"
- retry "^0.13.1"
-
p-timeout@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe"
@@ -1989,16 +2119,16 @@ p-timeout@^3.2.0:
dependencies:
p-finally "^1.0.0"
+papaparse@^5.5.3:
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/papaparse/-/papaparse-5.7.0.tgz#791209b95dd3a0ca0b6ed9b64f853bc491a45a65"
+ integrity sha512-qBGxg/7Q3Kl9Wfhrz2Z74UnvnHTXLNG6jmKJFeBvP2+y4lV7So+7SR62+Zd47JvdrCkX+nDcnr0ObPzek/+6RA==
+
parseurl@~1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
-path-key@^3.1.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
- integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
-
path-parse@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
@@ -2009,13 +2139,6 @@ path-to-regexp@0.1.12, path-to-regexp@~0.1.12:
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz#d5e1a12e478a976d432ef3c58d534b9923164bb7"
integrity sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==
-posthog-node@^5.5.1:
- version "5.20.0"
- resolved "https://registry.yarnpkg.com/posthog-node/-/posthog-node-5.20.0.tgz#9244a270ccf6a64db26a64fab65499990356f307"
- integrity sha512-LkR5KfrvEQTnUtNKN97VxFB00KcYG1Iz8iKg8r0e/i7f1eQhg1WSZO+Jp1B4bvtHCmdpIE4HwYbvCCzFoCyjVg==
- dependencies:
- "@posthog/core" "1.9.1"
-
proto3-json-serializer@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/proto3-json-serializer/-/proto3-json-serializer-2.0.2.tgz#5b705203b4d58f3880596c95fad64902617529dd"
@@ -2041,6 +2164,13 @@ protobufjs@^7.2.5, protobufjs@^7.3.0, protobufjs@^7.3.2, protobufjs@^7.5.3:
"@types/node" ">=13.7.0"
long "^5.0.0"
+protobufjs@^8.0.1:
+ version "8.8.0"
+ resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-8.8.0.tgz#7ed071d94b6755f63cc9936ecd82e4deac7cf624"
+ integrity sha512-N3xhQ5yyBx3vQq4gubBfASzYhJGNzeDbjqBpu61g7UVylsN/qyffU96TKWD3GbbLOKF82VGNRNvv1+BFgE31Eg==
+ dependencies:
+ long "^5.3.2"
+
proxy-addr@~2.0.7:
version "2.0.7"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
@@ -2139,11 +2269,6 @@ retry-request@^7.0.0:
extend "^3.0.2"
teeny-request "^9.0.0"
-retry@^0.13.1:
- version "0.13.1"
- resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658"
- integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==
-
safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.2.1, safe-buffer@~5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
@@ -2154,11 +2279,6 @@ safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.2.1, safe-buffer@~5.2.0:
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-semver@^7.6.3:
- version "7.7.3"
- resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946"
- integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==
-
send@0.19.0:
version "0.19.0"
resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8"
@@ -2222,18 +2342,6 @@ setprototypeof@1.2.0, setprototypeof@~1.2.0:
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
-shebang-command@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
- integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
- dependencies:
- shebang-regex "^3.0.0"
-
-shebang-regex@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
- integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
-
side-channel-list@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad"
@@ -2274,11 +2382,6 @@ side-channel@^1.0.6, side-channel@^1.1.0:
side-channel-map "^1.0.1"
side-channel-weakmap "^1.0.2"
-simple-wcswidth@^1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/simple-wcswidth/-/simple-wcswidth-1.1.2.tgz#66722f37629d5203f9b47c5477b1225b85d6525b"
- integrity sha512-j7piyCjAeTDSjzTSQ7DokZtMNwNlEAyxqSZeCS+CXH7fJ4jx3FuJ/mTW3mE+6JLs4VJBbcll0Kjn+KXI5t21Iw==
-
statuses@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
@@ -2334,13 +2437,6 @@ supports-color@^10.0.0:
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-10.2.2.tgz#466c2978cc5cd0052d542a0b576461c2b802ebb4"
integrity sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==
-supports-color@^7.1.0:
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
- integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
- dependencies:
- has-flag "^4.0.0"
-
supports-preserve-symlinks-flag@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
@@ -2395,11 +2491,6 @@ typescript@^5.6.2:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f"
integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==
-undici-types@~5.26.4:
- version "5.26.5"
- resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
- integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
-
undici-types@~6.21.0:
version "6.21.0"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb"
@@ -2445,10 +2536,10 @@ vary@~1.1.2:
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
-web-streams-polyfill@4.0.0-beta.3:
- version "4.0.0-beta.3"
- resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz#2898486b74f5156095e473efe989dcf185047a38"
- integrity sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==
+web-streams-polyfill@^3.0.3:
+ version "3.3.3"
+ resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b"
+ integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==
webidl-conversions@^3.0.0:
version "3.0.1"
@@ -2463,13 +2554,6 @@ whatwg-url@^5.0.0:
tr46 "~0.0.3"
webidl-conversions "^3.0.0"
-which@^2.0.1:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
- integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
- dependencies:
- isexe "^2.0.0"
-
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
@@ -2507,15 +2591,15 @@ yargs@^17.7.2:
y18n "^5.0.5"
yargs-parser "^21.1.1"
-zod-to-json-schema@^3.22.3, zod-to-json-schema@^3.25.0:
+zod-to-json-schema@^3.25.0:
version "3.25.1"
resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz#7f24962101a439ddade2bf1aeab3c3bfec7d84ba"
integrity sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==
-zod@^3.25.32:
- version "3.25.76"
- resolved "https://registry.yarnpkg.com/zod/-/zod-3.25.76.tgz#26841c3f6fd22a6a2760e7ccb719179768471e34"
- integrity sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==
+"zod@^3.25.76 || ^4":
+ version "4.5.4"
+ resolved "https://registry.yarnpkg.com/zod/-/zod-4.5.4.tgz#e215c62420c528dd7951e31fb52c5438f1fd184a"
+ integrity sha512-sC95tT5iHHH9gtpj6A81kh+NEaRAUFN+qlUPDUbRfOMvNf5QCBqsb3WgvnpVtK5Y+4UfA6KqufotuTvMGiTlsA==
zod@^4.0.17:
version "4.3.5"
From 052ba423ecbe5c4d99c53e16729030625e737578 Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 17:19:52 +0200
Subject: [PATCH 02/24] feat(http-ts): keyless weather service + pay-as-you-go
pricing fn
---
http-simple-agent-ts/src/pricing.selfcheck.ts | 12 +
http-simple-agent-ts/src/pricing.ts | 7 +
.../src/services/weather.service.ts | 238 ++++++++++++++++++
3 files changed, 257 insertions(+)
create mode 100644 http-simple-agent-ts/src/pricing.selfcheck.ts
create mode 100644 http-simple-agent-ts/src/pricing.ts
create mode 100644 http-simple-agent-ts/src/services/weather.service.ts
diff --git a/http-simple-agent-ts/src/pricing.selfcheck.ts b/http-simple-agent-ts/src/pricing.selfcheck.ts
new file mode 100644
index 00000000..8c64b4c8
--- /dev/null
+++ b/http-simple-agent-ts/src/pricing.selfcheck.ts
@@ -0,0 +1,12 @@
+import { priceForRequest } from "./pricing.js";
+
+const assert = (c: boolean, m: string) => { if (!c) throw new Error("FAIL: " + m); };
+
+assert(priceForRequest({ city: "Lisbon" }) === 1, "no days → 1 credit");
+assert(priceForRequest({ city: "Lisbon", days: 1 }) === 1, "1 day → 1 credit");
+assert(priceForRequest({ city: "Lisbon", days: 7 }) === 7, "7 days → 7 credits");
+assert(priceForRequest({ city: "Lisbon", days: 99 }) === 7, "days capped at 7");
+assert(priceForRequest({ city: "Lisbon", days: 0 }) === 1, "days floored at 1");
+assert(priceForRequest({ city: "Lisbon", days: "3" as any }) === 3, "numeric string coerced");
+assert(priceForRequest({}) === 1, "empty body → 1 credit");
+console.log("✓ pricing self-check passed");
diff --git a/http-simple-agent-ts/src/pricing.ts b/http-simple-agent-ts/src/pricing.ts
new file mode 100644
index 00000000..c2db43fa
--- /dev/null
+++ b/http-simple-agent-ts/src/pricing.ts
@@ -0,0 +1,7 @@
+/** Pay-as-you-go price: 1 credit for current weather, `days` credits (1..7) for a forecast. */
+export function priceForRequest(body: unknown): number {
+ const raw = (body as { days?: unknown } | null | undefined)?.days;
+ const n = typeof raw === "number" ? raw : typeof raw === "string" ? Number(raw) : NaN;
+ if (!Number.isFinite(n)) return 1;
+ return Math.max(1, Math.min(7, Math.trunc(n)));
+}
diff --git a/http-simple-agent-ts/src/services/weather.service.ts b/http-simple-agent-ts/src/services/weather.service.ts
new file mode 100644
index 00000000..4a669861
--- /dev/null
+++ b/http-simple-agent-ts/src/services/weather.service.ts
@@ -0,0 +1,238 @@
+/**
+ * Weather service: geocoding and current forecast using Open-Meteo.
+ * All functions use the built-in fetch available in Node.js >= 18.
+ */
+
+export type TodayWeather = {
+ city: string;
+ country: string | null;
+ latitude: number;
+ longitude: number;
+ timezone: string;
+ updatedAt: string;
+ tmaxC: number | null;
+ tminC: number | null;
+ precipitationMm: number | null;
+ weatherCode: number | null;
+ weatherText: string | null;
+};
+
+export class CityNotFoundError extends Error {
+ constructor(public readonly city: string) {
+ super(`City not found: ${city}`);
+ this.name = "CityNotFoundError";
+ }
+}
+
+export class DownstreamError extends Error {
+ constructor(message: string) {
+ super(message);
+ this.name = "DownstreamError";
+ }
+}
+
+export function sanitizeCity(rawCity: string): string {
+ const trimmed = rawCity.trim();
+ if (trimmed.length < 2 || trimmed.length > 80) {
+ throw new Error("City must be between 2 and 80 characters long");
+ }
+ return trimmed;
+}
+
+export async function geocodeCity(city: string): Promise<{
+ name: string;
+ country: string | null;
+ latitude: number;
+ longitude: number;
+ timezone: string | null;
+}> {
+ const q = sanitizeCity(city);
+ const url = new URL("https://geocoding-api.open-meteo.com/v1/search");
+ url.searchParams.set("name", q);
+ url.searchParams.set("count", "1");
+ url.searchParams.set("language", "en");
+
+ let res: Response;
+ try {
+ res = await fetch(url);
+ } catch (err) {
+ throw new DownstreamError("Failed to reach Open-Meteo geocoding API");
+ }
+
+ if (!res.ok) {
+ throw new DownstreamError(`Geocoding API returned HTTP ${res.status}`);
+ }
+
+ const data = (await res.json()) as any;
+ if (!data || !Array.isArray(data.results) || data.results.length === 0) {
+ throw new CityNotFoundError(q);
+ }
+ const first = data.results[0];
+ return {
+ name: String(first.name),
+ country: first.country ? String(first.country) : null,
+ latitude: Number(first.latitude),
+ longitude: Number(first.longitude),
+ timezone: first.timezone ? String(first.timezone) : null,
+ };
+}
+
+export function weatherCodeToText(
+ code: number | null | undefined
+): string | null {
+ if (code === null || code === undefined || Number.isNaN(code)) return null;
+ const mapping: Record = {
+ 0: "Clear sky",
+ 1: "Mainly clear",
+ 2: "Partly cloudy",
+ 3: "Overcast",
+ 45: "Fog",
+ 48: "Depositing rime fog",
+ 51: "Light drizzle",
+ 53: "Moderate drizzle",
+ 55: "Dense drizzle",
+ 56: "Light freezing drizzle",
+ 57: "Dense freezing drizzle",
+ 61: "Slight rain",
+ 63: "Moderate rain",
+ 65: "Heavy rain",
+ 66: "Light freezing rain",
+ 67: "Heavy freezing rain",
+ 71: "Slight snow fall",
+ 73: "Moderate snow fall",
+ 75: "Heavy snow fall",
+ 77: "Snow grains",
+ 80: "Slight rain showers",
+ 81: "Moderate rain showers",
+ 82: "Violent rain showers",
+ 85: "Slight snow showers",
+ 86: "Heavy snow showers",
+ 95: "Thunderstorm",
+ 96: "Thunderstorm with slight hail",
+ 99: "Thunderstorm with heavy hail",
+ };
+ return mapping[code] ?? "Unknown";
+}
+
+export async function getTodayWeather(city: string): Promise {
+ const geo = await geocodeCity(city);
+
+ const url = new URL("https://api.open-meteo.com/v1/forecast");
+ url.searchParams.set("latitude", String(geo.latitude));
+ url.searchParams.set("longitude", String(geo.longitude));
+ url.searchParams.set("current_weather", "true");
+ url.searchParams.set("timezone", "auto");
+ url.searchParams.set(
+ "daily",
+ "temperature_2m_max,temperature_2m_min,precipitation_sum"
+ );
+
+ let res: Response;
+ try {
+ res = await fetch(url);
+ } catch (err) {
+ throw new DownstreamError("Failed to reach Open-Meteo forecast API");
+ }
+
+ if (!res.ok) {
+ throw new DownstreamError(`Forecast API returned HTTP ${res.status}`);
+ }
+
+ const data = (await res.json()) as any;
+ const tz: string = data.timezone ?? geo.timezone ?? "unknown";
+ const daily = data.daily ?? {};
+ const tmax: number | null =
+ Array.isArray(daily.temperature_2m_max) &&
+ daily.temperature_2m_max.length > 0
+ ? Number(daily.temperature_2m_max[0])
+ : null;
+ const tmin: number | null =
+ Array.isArray(daily.temperature_2m_min) &&
+ daily.temperature_2m_min.length > 0
+ ? Number(daily.temperature_2m_min[0])
+ : null;
+ const precip: number | null =
+ Array.isArray(daily.precipitation_sum) && daily.precipitation_sum.length > 0
+ ? Number(daily.precipitation_sum[0])
+ : null;
+ const current = data.current_weather ?? {};
+ const code: number | null =
+ typeof current.weathercode === "number"
+ ? Number(current.weathercode)
+ : null;
+
+ const result: TodayWeather = {
+ city: geo.name,
+ country: geo.country,
+ latitude: geo.latitude,
+ longitude: geo.longitude,
+ timezone: tz,
+ updatedAt: new Date().toISOString(),
+ tmaxC: tmax,
+ tminC: tmin,
+ precipitationMm: precip,
+ weatherCode: code,
+ weatherText: weatherCodeToText(code),
+ };
+
+ return result;
+}
+
+export type ForecastDay = {
+ date: string;
+ tmaxC: number | null;
+ tminC: number | null;
+ precipitationMm: number | null;
+ weatherCode: number | null;
+ weatherText: string | null;
+};
+
+export type ForecastWeather = {
+ city: string;
+ country: string | null;
+ timezone: string;
+ updatedAt: string;
+ days: ForecastDay[];
+};
+
+export async function getForecast(city: string, days: number): Promise {
+ const n = Math.max(1, Math.min(7, Math.trunc(days)));
+ const geo = await geocodeCity(city);
+ const url = new URL("https://api.open-meteo.com/v1/forecast");
+ url.searchParams.set("latitude", String(geo.latitude));
+ url.searchParams.set("longitude", String(geo.longitude));
+ url.searchParams.set("forecast_days", String(n));
+ url.searchParams.set("timezone", "auto");
+ url.searchParams.set("daily", "temperature_2m_max,temperature_2m_min,precipitation_sum,weathercode");
+
+ let res: Response;
+ try {
+ res = await fetch(url);
+ } catch {
+ throw new DownstreamError("Failed to reach Open-Meteo forecast API");
+ }
+ if (!res.ok) throw new DownstreamError(`Forecast API returned HTTP ${res.status}`);
+
+ const data = (await res.json()) as any;
+ const d = data.daily ?? {};
+ const time: string[] = Array.isArray(d.time) ? d.time : [];
+ const daysOut: ForecastDay[] = time.map((date: string, i: number) => {
+ const code = Array.isArray(d.weathercode) ? Number(d.weathercode[i]) : null;
+ return {
+ date,
+ tmaxC: Array.isArray(d.temperature_2m_max) ? Number(d.temperature_2m_max[i]) : null,
+ tminC: Array.isArray(d.temperature_2m_min) ? Number(d.temperature_2m_min[i]) : null,
+ precipitationMm: Array.isArray(d.precipitation_sum) ? Number(d.precipitation_sum[i]) : null,
+ weatherCode: code,
+ weatherText: weatherCodeToText(code),
+ };
+ });
+
+ return {
+ city: geo.name,
+ country: geo.country,
+ timezone: data.timezone ?? geo.timezone ?? "unknown",
+ updatedAt: new Date().toISOString(),
+ days: daysOut,
+ };
+}
From e3de591f533fea5eaec83128435c70757fc8865e Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 17:25:26 +0200
Subject: [PATCH 03/24] feat(http-ts): dual-protocol weather routes over three
plans
---
http-simple-agent-ts/src/agent.ts | 127 ++++++++++++++---------------
http-simple-agent-ts/tsconfig.json | 2 +-
2 files changed, 61 insertions(+), 68 deletions(-)
diff --git a/http-simple-agent-ts/src/agent.ts b/http-simple-agent-ts/src/agent.ts
index 3c9bee92..0041362e 100644
--- a/http-simple-agent-ts/src/agent.ts
+++ b/http-simple-agent-ts/src/agent.ts
@@ -1,100 +1,93 @@
/**
- * Protected HTTP Agent - Express server with Nevermined payment middleware.
+ * Weather HTTP Agent - Express server with dual-protocol Nevermined payment middleware.
*
- * This demonstrates how to protect an endpoint using the x402 protocol.
- * The /ask endpoint requires a valid x402 access token and burns credits.
+ * Three plans, three routes, both protocols. `mpp: true` on every paid route makes
+ * each 402 advertise x402 AND MPP, so either buyer works against the same URL.
*
* x402 HTTP Transport Headers:
* - Client sends token in: `payment-signature` header
* - Server returns 402 with: `payment-required` header (base64-encoded)
+ *
+ * MPP HTTP Transport Headers:
+ * - Client sends credential in: `authorization` header
+ * - Server returns 402 with: `www-authenticate` header
*/
import "dotenv/config";
import express, { Request, Response, RequestHandler } from "express";
-import OpenAI from "openai";
import { Payments, EnvironmentName } from "@nevermined-io/payments";
-import { paymentMiddleware, X402_HEADERS } from "@nevermined-io/payments/express";
-
-const app = express();
-app.use(express.json());
+import { paymentMiddleware, X402_HEADERS, MPP_HEADERS } from "@nevermined-io/payments/express";
+import { getTodayWeather, getForecast, CityNotFoundError } from "./services/weather.service.js";
+import { priceForRequest } from "./pricing.js";
const PORT = process.env.PORT ? Number(process.env.PORT) : 3000;
-const OPENAI_API_KEY = process.env.OPENAI_API_KEY ?? "";
const NVM_API_KEY = process.env.NVM_API_KEY ?? "";
-const NVM_ENVIRONMENT = (process.env.NVM_ENVIRONMENT || "testing") as EnvironmentName;
-const NVM_PLAN_ID = process.env.NVM_PLAN_ID ?? "";
+const NVM_ENVIRONMENT = (process.env.NVM_ENVIRONMENT || "sandbox") as EnvironmentName;
+const PLAN_ID_CREDITS = process.env.PLAN_ID_CREDITS ?? "";
+const PLAN_ID_TIME = process.env.PLAN_ID_TIME ?? "";
+const PLAN_ID_PAYG = process.env.PLAN_ID_PAYG ?? "";
-if (!OPENAI_API_KEY) {
- console.error("OPENAI_API_KEY is required. Set it in .env file.");
+if (!NVM_API_KEY || !PLAN_ID_CREDITS || !PLAN_ID_TIME || !PLAN_ID_PAYG) {
+ console.error("NVM_API_KEY, PLAN_ID_CREDITS, PLAN_ID_TIME and PLAN_ID_PAYG are required.");
process.exit(1);
}
-if (!NVM_API_KEY || !NVM_PLAN_ID) {
- console.error("NVM_API_KEY and NVM_PLAN_ID are required for payment protection.");
- process.exit(1);
-}
+const payments = Payments.getInstance({ nvmApiKey: NVM_API_KEY, environment: NVM_ENVIRONMENT });
-const openai = new OpenAI({ apiKey: OPENAI_API_KEY });
+const app = express();
+app.use(express.json());
-// Initialize Nevermined Payments SDK
-const payments = Payments.getInstance({
- nvmApiKey: NVM_API_KEY,
- environment: NVM_ENVIRONMENT,
-});
+// /health stays unprotected — mount it before the paywall.
+app.get("/health", (_req: Request, res: Response) => res.json({ ok: true }));
-// Apply payment middleware to protect the /ask endpoint
-// x402-compliant: expects `payment-signature` header with access token
-// Note: Type cast needed due to Express type overload resolution
+// One middleware, three plans, both protocols. `mpp: true` makes each 402 advertise
+// x402 AND MPP, so either buyer works against the same URL.
app.use(
- paymentMiddleware(payments, {
- "POST /ask": {
- planId: NVM_PLAN_ID,
- credits: 1,
+ paymentMiddleware(
+ payments,
+ {
+ "POST /weather/credits": { planId: PLAN_ID_CREDITS, credits: 1, mpp: true },
+ "POST /weather/subscription": { planId: PLAN_ID_TIME, credits: 1, mpp: true },
+ "POST /weather/payg": {
+ planId: PLAN_ID_PAYG,
+ credits: (req: Request) => priceForRequest(req.body),
+ mpp: true,
+ },
},
- }, {
- onBeforeVerify: (req) => {
- console.log(`[Payment] Verifying request to ${req.path}`);
+ {
+ onBeforeVerify: (req) => console.log(`[pay] verify ${req.method} ${req.path}`),
+ onAfterSettle: (req, credits) => console.log(`[pay] settled ${credits} on ${req.path}`),
},
- onAfterSettle: (req, creditsUsed) => {
- console.log(`[Payment] Settled ${creditsUsed} credits for ${req.path}`);
- },
- }) as RequestHandler
+ ) as RequestHandler,
);
-/**
- * POST /ask - Send a query to the AI (protected by payment middleware)
- */
-app.post("/ask", async (req: Request, res: Response) => {
+async function handleToday(req: Request, res: Response) {
try {
- const { query } = req.body as { query?: string };
-
- if (!query || typeof query !== "string") {
- return res.status(400).json({ error: "Missing or invalid 'query' field" });
- }
-
- const completion = await openai.chat.completions.create({
- model: "gpt-4o-mini",
- messages: [
- {
- role: "system",
- content: "You are a helpful assistant. Be concise and informative.",
- },
- { role: "user", content: query },
- ],
- max_tokens: 500,
- });
+ const { city } = req.body as { city?: string };
+ if (!city) return res.status(400).json({ error: "Missing 'city'" });
+ return res.json(await getTodayWeather(city));
+ } catch (err) {
+ if (err instanceof CityNotFoundError) return res.status(404).json({ error: err.message });
+ console.error(err);
+ return res.status(502).json({ error: "weather upstream failed" });
+ }
+}
- const response = completion.choices[0]?.message?.content ?? "No response generated";
+app.post("/weather/credits", handleToday);
+app.post("/weather/subscription", handleToday);
- res.json({ response });
- } catch (error) {
- console.error("Error in /ask:", error);
- res.status(500).json({ error: "Internal server error" });
+app.post("/weather/payg", async (req: Request, res: Response) => {
+ try {
+ const { city, days } = req.body as { city?: string; days?: number };
+ if (!city) return res.status(400).json({ error: "Missing 'city'" });
+ return res.json(days && days > 1 ? await getForecast(city, days) : await getTodayWeather(city));
+ } catch (err) {
+ if (err instanceof CityNotFoundError) return res.status(404).json({ error: err.message });
+ console.error(err);
+ return res.status(502).json({ error: "weather upstream failed" });
}
});
app.listen(PORT, () => {
- console.log(`Protected HTTP Agent running on http://localhost:${PORT}`);
- console.log(`\nPayment protection enabled for POST /ask`);
- console.log(`Plan ID: ${NVM_PLAN_ID}`);
- console.log(`\nTo test, send requests with x402 token in '${X402_HEADERS.PAYMENT_SIGNATURE}' header.`);
+ console.log(`weather-x402 agent on http://localhost:${PORT}`);
+ console.log(`x402 header: ${X402_HEADERS.PAYMENT_SIGNATURE} · MPP header: ${MPP_HEADERS.CREDENTIAL}`);
});
diff --git a/http-simple-agent-ts/tsconfig.json b/http-simple-agent-ts/tsconfig.json
index 3fc4e6ff..783df977 100644
--- a/http-simple-agent-ts/tsconfig.json
+++ b/http-simple-agent-ts/tsconfig.json
@@ -10,5 +10,5 @@
"rootDir": "src"
},
"include": ["src/**/*"],
- "exclude": ["node_modules", "dist", "src/agent-observability.ts"]
+ "exclude": ["node_modules", "dist", "src/agent-observability.ts", "src/client.ts"]
}
From cb4e01eeaae9d511ba4e23986d254f5bde6eeffd Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 17:36:04 +0200
Subject: [PATCH 04/24] fix(http-ts): 400 on invalid weather request input
(boundary validation)
---
http-simple-agent-ts/package.json | 1 +
http-simple-agent-ts/src/agent.ts | 9 +++++----
http-simple-agent-ts/src/request.selfcheck.ts | 20 +++++++++++++++++++
http-simple-agent-ts/src/request.ts | 19 ++++++++++++++++++
4 files changed, 45 insertions(+), 4 deletions(-)
create mode 100644 http-simple-agent-ts/src/request.selfcheck.ts
create mode 100644 http-simple-agent-ts/src/request.ts
diff --git a/http-simple-agent-ts/package.json b/http-simple-agent-ts/package.json
index 0579fe26..e4f84341 100644
--- a/http-simple-agent-ts/package.json
+++ b/http-simple-agent-ts/package.json
@@ -11,6 +11,7 @@
"register-plans": "tsx scripts/register-plans.ts",
"smoke": "tsx scripts/smoke.ts",
"pricing:selfcheck": "tsx src/pricing.selfcheck.ts",
+ "request:selfcheck": "tsx src/request.selfcheck.ts",
"build": "tsc",
"start": "node dist/agent.js"
},
diff --git a/http-simple-agent-ts/src/agent.ts b/http-simple-agent-ts/src/agent.ts
index 0041362e..2eade80a 100644
--- a/http-simple-agent-ts/src/agent.ts
+++ b/http-simple-agent-ts/src/agent.ts
@@ -18,6 +18,7 @@ import { Payments, EnvironmentName } from "@nevermined-io/payments";
import { paymentMiddleware, X402_HEADERS, MPP_HEADERS } from "@nevermined-io/payments/express";
import { getTodayWeather, getForecast, CityNotFoundError } from "./services/weather.service.js";
import { priceForRequest } from "./pricing.js";
+import { parseWeatherRequest, BadRequestError } from "./request.js";
const PORT = process.env.PORT ? Number(process.env.PORT) : 3000;
const NVM_API_KEY = process.env.NVM_API_KEY ?? "";
@@ -62,10 +63,10 @@ app.use(
async function handleToday(req: Request, res: Response) {
try {
- const { city } = req.body as { city?: string };
- if (!city) return res.status(400).json({ error: "Missing 'city'" });
+ const { city } = parseWeatherRequest(req.body);
return res.json(await getTodayWeather(city));
} catch (err) {
+ if (err instanceof BadRequestError) return res.status(400).json({ error: err.message });
if (err instanceof CityNotFoundError) return res.status(404).json({ error: err.message });
console.error(err);
return res.status(502).json({ error: "weather upstream failed" });
@@ -77,10 +78,10 @@ app.post("/weather/subscription", handleToday);
app.post("/weather/payg", async (req: Request, res: Response) => {
try {
- const { city, days } = req.body as { city?: string; days?: number };
- if (!city) return res.status(400).json({ error: "Missing 'city'" });
+ const { city, days } = parseWeatherRequest(req.body);
return res.json(days && days > 1 ? await getForecast(city, days) : await getTodayWeather(city));
} catch (err) {
+ if (err instanceof BadRequestError) return res.status(400).json({ error: err.message });
if (err instanceof CityNotFoundError) return res.status(404).json({ error: err.message });
console.error(err);
return res.status(502).json({ error: "weather upstream failed" });
diff --git a/http-simple-agent-ts/src/request.selfcheck.ts b/http-simple-agent-ts/src/request.selfcheck.ts
new file mode 100644
index 00000000..7fd6b6e9
--- /dev/null
+++ b/http-simple-agent-ts/src/request.selfcheck.ts
@@ -0,0 +1,20 @@
+import { parseWeatherRequest, BadRequestError } from "./request.js";
+
+const assert = (c: boolean, m: string) => { if (!c) throw new Error("FAIL: " + m); };
+const assertThrows = (fn: () => unknown, m: string) => {
+ try {
+ fn();
+ throw new Error("FAIL: " + m + " (did not throw)");
+ } catch (err) {
+ if (!(err instanceof BadRequestError)) throw new Error("FAIL: " + m + " (wrong error type)");
+ }
+};
+
+assert(parseWeatherRequest({ city: "Lisbon" }).city === "Lisbon", "valid city passes through");
+assert(parseWeatherRequest({ city: "Lisbon", days: "7" }).days === 7, "numeric string days coerced");
+assertThrows(() => parseWeatherRequest({}), "missing city throws");
+assertThrows(() => parseWeatherRequest({ city: "x" }), "too-short city throws");
+assertThrows(() => parseWeatherRequest({ city: 123 }), "non-string city throws");
+assertThrows(() => parseWeatherRequest({ city: "Lisbon", days: "abc" }), "non-numeric days throws");
+
+console.log("✓ request self-check passed");
diff --git a/http-simple-agent-ts/src/request.ts b/http-simple-agent-ts/src/request.ts
new file mode 100644
index 00000000..d8172c4e
--- /dev/null
+++ b/http-simple-agent-ts/src/request.ts
@@ -0,0 +1,19 @@
+export class BadRequestError extends Error {
+ constructor(message: string) { super(message); this.name = "BadRequestError"; }
+}
+
+/** Validate the weather request body at the trust boundary. Throws BadRequestError on invalid input. */
+export function parseWeatherRequest(body: unknown): { city: string; days?: number } {
+ const b = (body ?? {}) as Record;
+ const city = b.city;
+ if (typeof city !== "string" || city.trim().length < 2 || city.trim().length > 80) {
+ throw new BadRequestError("'city' must be a string between 2 and 80 characters");
+ }
+ let days: number | undefined;
+ if (b.days !== undefined) {
+ const n = typeof b.days === "number" ? b.days : typeof b.days === "string" ? Number(b.days) : NaN;
+ if (!Number.isFinite(n)) throw new BadRequestError("'days' must be a number");
+ days = n; // getForecast already clamps to 1..7
+ }
+ return { city: city.trim(), days };
+}
From b1a71ebd09d480093082a174a8d301edf066039a Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 17:39:52 +0200
Subject: [PATCH 05/24] feat(http-ts): plan registration script
(credits/time/payg)
---
.../scripts/register-plans.ts | 33 +++++++++++++++++++
1 file changed, 33 insertions(+)
create mode 100644 http-simple-agent-ts/scripts/register-plans.ts
diff --git a/http-simple-agent-ts/scripts/register-plans.ts b/http-simple-agent-ts/scripts/register-plans.ts
new file mode 100644
index 00000000..698cf0ed
--- /dev/null
+++ b/http-simple-agent-ts/scripts/register-plans.ts
@@ -0,0 +1,33 @@
+import "dotenv/config";
+import { Payments, EnvironmentName } from "@nevermined-io/payments";
+
+const payments = Payments.getInstance({
+ nvmApiKey: process.env.NVM_API_KEY!,
+ environment: (process.env.NVM_ENVIRONMENT || "sandbox") as EnvironmentName,
+});
+const plans = payments.plans;
+
+// Crypto price so BOTH x402 (erc4337) and MPP can pay. Needs the builder's receiver wallet.
+// If NVM_RECEIVER is unset, fall back to a free plan so the script still runs for a demo.
+const receiver = process.env.NVM_RECEIVER ?? "";
+const amount = BigInt(process.env.PLAN_PRICE_WEI ?? "0");
+const price = receiver
+ ? plans.getCryptoPriceConfig(amount, receiver as `0x${string}`)
+ : plans.getFreePriceConfig();
+
+async function main() {
+ const { planId: credits } = await plans.registerCreditsPlan(
+ { name: "Weather — Fixed Credits", description: "100 weather calls, 1 credit each" },
+ price, plans.getFixedCreditsConfig(100n, 1n));
+ const { planId: time } = await plans.registerTimePlan(
+ { name: "Weather — Day Pass", description: "24h of weather access" },
+ price, plans.getExpirableDurationConfig(86400n)); // 86400n = ONE_DAY (const not importable)
+ const { planId: payg } = await plans.registerPlan(
+ { name: "Weather — Pay As You Go", description: "1 credit current, up to 7 for a forecast" },
+ price, plans.getDynamicCreditsConfig(1000n, 1n, 7n));
+
+ console.log("PLAN_ID_CREDITS=" + credits);
+ console.log("PLAN_ID_TIME=" + time);
+ console.log("PLAN_ID_PAYG=" + payg);
+}
+main().catch((e) => { console.error(e); process.exit(1); });
From 045ba883ce6a6ce682bf2079bef49ce7af6f61b5 Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 17:40:20 +0200
Subject: [PATCH 06/24] test(http-ts): x402 + MPP smoke e2e
---
http-simple-agent-ts/scripts/smoke.ts | 48 +++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
create mode 100644 http-simple-agent-ts/scripts/smoke.ts
diff --git a/http-simple-agent-ts/scripts/smoke.ts b/http-simple-agent-ts/scripts/smoke.ts
new file mode 100644
index 00000000..ea72aaf8
--- /dev/null
+++ b/http-simple-agent-ts/scripts/smoke.ts
@@ -0,0 +1,48 @@
+import "dotenv/config";
+import { Payments, EnvironmentName } from "@nevermined-io/payments";
+import { X402_HEADERS } from "@nevermined-io/payments/express";
+
+const BASE = process.env.SERVER_URL || "http://localhost:3000";
+const PLAN = process.env.PLAN_ID_CREDITS!;
+const payments = Payments.getInstance({
+ nvmApiKey: process.env.NVM_API_KEY!,
+ environment: (process.env.NVM_ENVIRONMENT || "sandbox") as EnvironmentName,
+});
+const assert = (c: boolean, m: string) => { if (!c) throw new Error("FAIL: " + m); };
+
+async function main() {
+ // 1) Unpaid → 402 advertising BOTH protocols
+ const r0 = await fetch(`${BASE}/weather/credits`, {
+ method: "POST", headers: { "content-type": "application/json" },
+ body: JSON.stringify({ city: "Lisbon" }),
+ });
+ assert(r0.status === 402, "unpaid → 402");
+ assert(!!r0.headers.get(X402_HEADERS.PAYMENT_REQUIRED), "x402 challenge present");
+ assert(!!r0.headers.get("www-authenticate"), "MPP WWW-Authenticate present");
+
+ // 2) x402 buyer → 200
+ const { accessToken } = await payments.x402.getX402AccessToken(PLAN);
+ const r1 = await fetch(`${BASE}/weather/credits`, {
+ method: "POST",
+ headers: { "content-type": "application/json", [X402_HEADERS.PAYMENT_SIGNATURE]: accessToken },
+ body: JSON.stringify({ city: "Lisbon" }),
+ });
+ assert(r1.status === 200, `x402 paid → 200 (got ${r1.status})`);
+ const w = await r1.json();
+ assert(typeof w.city === "string", "x402 returned real weather");
+
+ // 3) MPP buyer → 200 + receipt
+ const { delegationId } = await payments.delegation.createDelegation({
+ provider: "erc4337", spendingLimitCents: 10000, durationSecs: 604800, currency: "usdc",
+ });
+ const { response, receipt, paid } = await payments.mpp.fetch(
+ `${BASE}/weather/credits`,
+ { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ city: "Berlin" }) },
+ { delegationConfig: { delegationId }, planId: PLAN },
+ );
+ assert(response.status === 200, `MPP paid → 200 (got ${response.status})`);
+ assert(paid && !!receipt, "MPP settled with a receipt");
+
+ console.log("✓ smoke: x402 + MPP both paid a real weather response");
+}
+main().catch((e) => { console.error(e); process.exit(1); });
From 0c6b64e4034a6d141ac469633241f94ed2dc8221 Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 17:44:33 +0200
Subject: [PATCH 07/24] build(http-ts): Dockerfile for weather-x402 service
---
http-simple-agent-ts/Dockerfile | 11 +++++++++++
1 file changed, 11 insertions(+)
create mode 100644 http-simple-agent-ts/Dockerfile
diff --git a/http-simple-agent-ts/Dockerfile b/http-simple-agent-ts/Dockerfile
new file mode 100644
index 00000000..1114f844
--- /dev/null
+++ b/http-simple-agent-ts/Dockerfile
@@ -0,0 +1,11 @@
+FROM node:20-alpine
+LABEL maintainer="Nevermined "
+RUN apk add --no-cache libc6-compat yarn
+WORKDIR /app
+COPY package.json yarn.lock ./
+RUN yarn install --frozen-lockfile --non-interactive --ignore-engines
+COPY src ./src
+COPY tsconfig.json ./
+RUN yarn build
+EXPOSE 3000
+ENTRYPOINT ["yarn", "start"]
From 41c962f19d81f14e96b59e929330242f9b551ab0 Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 17:45:22 +0200
Subject: [PATCH 08/24] ci: build & push weather-x402 image to Artifact
Registry
---
.github/workflows/weather-x402-image.yml | 146 +++++++++++++++++++++++
1 file changed, 146 insertions(+)
create mode 100644 .github/workflows/weather-x402-image.yml
diff --git a/.github/workflows/weather-x402-image.yml b/.github/workflows/weather-x402-image.yml
new file mode 100644
index 00000000..bc46be0e
--- /dev/null
+++ b/.github/workflows/weather-x402-image.yml
@@ -0,0 +1,146 @@
+name: Weather x402 image
+
+# Builds the weather-x402 agent (http-simple-agent-ts/Dockerfile) and pushes it
+# to Google Artifact Registry so ArgoCD can deploy it. Keyless auth via Workload
+# Identity Federation (same SA/provider the other Nevermined repos use — no
+# secrets).
+#
+# pull_request → verify only (install, self-checks, build); no credentials, no push.
+# push to main → verify, then build & push.
+# dispatch → verify, then build & push (optional extra semver tag).
+#
+# Versioning (immutable-first — the AR repo has immutableTags=true, so a moving
+# `latest` tag would be rejected on the second build; we don't publish one):
+# - sha- every build — the immutable tag ArgoCD should pin in production
+# - optional, when run manually with a version input (e.g. 1.0.0)
+
+on:
+ pull_request:
+ paths:
+ - "http-simple-agent-ts/**"
+ - ".github/workflows/weather-x402-image.yml"
+ push:
+ branches: [main]
+ paths:
+ - "http-simple-agent-ts/**"
+ - ".github/workflows/weather-x402-image.yml"
+ workflow_dispatch:
+ inputs:
+ version:
+ description: "Optional explicit semver tag to also publish (e.g. 1.0.0)"
+ required: false
+ type: string
+
+# Superseded PR pushes shouldn't keep burning a runner. Cancel only in-flight PR
+# runs (grouped per ref, so distinct PRs don't cancel each other); never cancel a
+# push/dispatch run — those publish the immutable image and must finish.
+concurrency:
+ group: weather-x402-image-${{ github.ref }}
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
+
+env:
+ IMAGE: europe-west3-docker.pkg.dev/nevermined-eu-dev/nevermined-io/tutorials-weather-x402
+ AR_LOCATION: europe-west3
+ PROJECT_ID: nevermined-eu-dev
+ SERVICE_ACCOUNT: github-actions-service-account@nevermined-eu-dev.iam.gserviceaccount.com
+ WORKLOAD_IDENTITY_PROVIDER: projects/112425687177/locations/global/workloadIdentityPools/github/providers/github-actions
+
+permissions:
+ contents: read
+ id-token: write
+
+jobs:
+ # Runs on every PR and every push. `tsc` type-checks the agent, and the pure
+ # self-checks cover the pricing/request-validation logic — neither needs
+ # credentials, so a broken PR fails here instead of on main.
+ verify:
+ name: Verify (install + self-checks + build)
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: http-simple-agent-ts
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Set up Node
+ uses: actions/setup-node@v4
+ with:
+ node-version: "20"
+ cache: yarn
+ cache-dependency-path: http-simple-agent-ts/yarn.lock
+
+ - name: Install
+ run: yarn install --frozen-lockfile
+
+ - name: Pricing self-check
+ run: yarn pricing:selfcheck
+
+ - name: Request validation self-check
+ run: yarn request:selfcheck
+
+ - name: Build (type-checks the agent)
+ run: yarn build
+
+ # Only publishes on main / dispatch — never on a pull request.
+ build-push:
+ name: Build & push weather-x402 image
+ runs-on: ubuntu-latest
+ needs: verify
+ if: github.event_name != 'pull_request'
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Docker metadata (tags + labels)
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ images: ${{ env.IMAGE }}
+ tags: |
+ type=sha,prefix=sha-,format=short
+ type=raw,value=${{ inputs.version }},enable=${{ inputs.version != '' }}
+
+ - name: Authenticate to Google Cloud
+ id: auth
+ uses: google-github-actions/auth@v2
+ with:
+ token_format: access_token
+ project_id: ${{ env.PROJECT_ID }}
+ service_account: ${{ env.SERVICE_ACCOUNT }}
+ workload_identity_provider: ${{ env.WORKLOAD_IDENTITY_PROVIDER }}
+
+ - name: Log in to Artifact Registry
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.AR_LOCATION }}-docker.pkg.dev
+ username: oauth2accesstoken
+ password: ${{ steps.auth.outputs.access_token }}
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Build & push
+ uses: docker/build-push-action@v5
+ with:
+ context: ./http-simple-agent-ts
+ file: ./http-simple-agent-ts/Dockerfile
+ push: true
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
+ provenance: false
+ sbom: false
+
+ - name: Summary
+ env:
+ TAGS: ${{ steps.meta.outputs.tags }}
+ run: |
+ {
+ echo "### Pushed tutorials-weather-x402 image"
+ echo '```'
+ echo "$TAGS"
+ echo '```'
+ echo "Pin the immutable sha-* tag in ArgoCD for production."
+ } >> "$GITHUB_STEP_SUMMARY"
From eb3276515c80e33111b3ff599217e9983e02efd3 Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 17:51:34 +0200
Subject: [PATCH 09/24] fix(http-ts): build on Node 22 to satisfy gcp-metadata
engine, drop --ignore-engines
---
.github/workflows/weather-x402-image.yml | 2 +-
http-simple-agent-ts/Dockerfile | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/weather-x402-image.yml b/.github/workflows/weather-x402-image.yml
index bc46be0e..c764cf4f 100644
--- a/.github/workflows/weather-x402-image.yml
+++ b/.github/workflows/weather-x402-image.yml
@@ -66,7 +66,7 @@ jobs:
- name: Set up Node
uses: actions/setup-node@v4
with:
- node-version: "20"
+ node-version: "22"
cache: yarn
cache-dependency-path: http-simple-agent-ts/yarn.lock
diff --git a/http-simple-agent-ts/Dockerfile b/http-simple-agent-ts/Dockerfile
index 1114f844..0d1ff842 100644
--- a/http-simple-agent-ts/Dockerfile
+++ b/http-simple-agent-ts/Dockerfile
@@ -1,9 +1,9 @@
-FROM node:20-alpine
+FROM node:22-alpine
LABEL maintainer="Nevermined "
RUN apk add --no-cache libc6-compat yarn
WORKDIR /app
COPY package.json yarn.lock ./
-RUN yarn install --frozen-lockfile --non-interactive --ignore-engines
+RUN yarn install --frozen-lockfile --non-interactive
COPY src ./src
COPY tsconfig.json ./
RUN yarn build
From fe7943debabaef51e918b09e73887943ee937a62 Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 17:56:15 +0200
Subject: [PATCH 10/24] docs(http-ts): ArgoCD deploy manifests for
weather-x402-agent (agents ns)
---
http-simple-agent-ts/deploy/argocd/README.md | 172 ++++++++++++++++++
.../argocd/weather-x402-agent-staging.yaml | 66 +++++++
.../deploy/argocd/weather-x402-agent.yaml | 66 +++++++
3 files changed, 304 insertions(+)
create mode 100644 http-simple-agent-ts/deploy/argocd/README.md
create mode 100644 http-simple-agent-ts/deploy/argocd/weather-x402-agent-staging.yaml
create mode 100644 http-simple-agent-ts/deploy/argocd/weather-x402-agent.yaml
diff --git a/http-simple-agent-ts/deploy/argocd/README.md b/http-simple-agent-ts/deploy/argocd/README.md
new file mode 100644
index 00000000..0ebdf6ff
--- /dev/null
+++ b/http-simple-agent-ts/deploy/argocd/README.md
@@ -0,0 +1,172 @@
+# ArgoCD deploy manifests — weather-x402-agent
+
+Reference manifests for deploying the `http-simple-agent-ts` weather x402/MPP
+service to the `agents` namespace. **This directory is a reference only** —
+these files are not consumed by ArgoCD from here. A human must copy them into
+the separate `argocd` repo and open a PR there.
+
+## Where each file goes
+
+| This directory | Target in `nevermined-io/argocd` |
+|---|---|
+| `weather-x402-agent.yaml` | `eu/dev/argocd-apps/agents/weather-x402-agent.yaml` |
+| `weather-x402-agent-staging.yaml` | `eu/dev/argocd-apps/agents/weather-x402-agent-staging.yaml` |
+
+Modeled on `eu/dev/argocd-apps/agents/demo-finance-agent.yaml` and the shared
+chart `helm-charts/agent/v1.0.0/`.
+
+## Chart env-key finding (REQUIRED reading before deploying)
+
+`helm-charts/agent/v1.0.0/templates/deployment.yaml` renders the container's
+`env:` block as a **fixed, hardcoded list** of `- name: X / value:
+{{ .Values.env.X }}` lines — there is no generic `env.*` passthrough. Verified
+by rendering the chart with `--set env.PLAN_ID_CREDITS=...` etc.: the values
+land in `.Values` but **do not appear anywhere in the rendered Deployment**,
+because the template has no line for them.
+
+- **`NVM_API_KEY` needs no chart change.** The chart already has a
+ `- name: NVM_API_KEY / value: {{ .Values.env.NVM_API_KEY }}` line, so the
+ `helm.parameters` entry `env.NVM_API_KEY: gcp:secretmanager:...` in both
+ manifests here renders straight through and is resolved at container start
+ by the `secrets-init` init container/wrapper (the same mechanism the
+ template uses for `secrets.openaiApiKey` → `OPENAI_API_KEY` on
+ demo-finance-agent — any env value matching the `gcp:secretmanager:...`
+ form is fetched and substituted before `initCommand` runs, regardless of
+ which `.Values` path it came from). Confirmed in the `helm template` output
+ below.
+- **`PLAN_ID_CREDITS`, `PLAN_ID_TIME`, `PLAN_ID_PAYG` need a chart patch.**
+ These three names don't exist anywhere in `templates/deployment.yaml`, so
+ no `helm.parameters` value can make them appear as container env vars.
+ **Required precondition before merging either Application manifest**: add
+ three lines to `helm-charts/agent/v1.0.0/templates/deployment.yaml`, in the
+ `env:` block of the container spec (next to the existing `NVM_PLAN_ID` /
+ `PLAN_ID` lines is a natural spot):
+
+ ```yaml
+ - name: PLAN_ID_CREDITS
+ value: "{{ .Values.env.PLAN_ID_CREDITS }}"
+ - name: PLAN_ID_TIME
+ value: "{{ .Values.env.PLAN_ID_TIME }}"
+ - name: PLAN_ID_PAYG
+ value: "{{ .Values.env.PLAN_ID_PAYG }}"
+ ```
+
+ This is additive only — it doesn't touch any existing line, so it's safe
+ for the other apps using this chart version. Ship it as its own tiny PR (or
+ as the first commit of the same PR that adds the two Application files),
+ merged *before* the Applications sync, otherwise the pods will start with
+ empty plan IDs and `agent.ts`'s startup check
+ (`if (!NVM_API_KEY || !PLAN_ID_CREDITS || !PLAN_ID_TIME || !PLAN_ID_PAYG)`)
+ will crash-loop the container.
+
+## `replicaCount: "1"` — required, not just default
+
+`values.yaml` already defaults `replicaCount: 1`, and it *is* a settable Helm
+param (`{{ .Values.replicaCount }}` is used directly in `deployment.yaml`
+when `autoscaling.enabled` is false, which is also the default). Both
+manifests set it explicitly anyway for visibility: **do not raise it and do
+not enable `autoscaling`**. The MPP single-use-token guard in `agent.ts` is
+an in-process in-memory set; a second replica (or HPA scale-out) would let
+the same MPP token be redeemed twice, defeating the guard.
+
+## `helm template` render summary (validated locally, no cluster contact)
+
+```
+cd ~/Projects/Nevermined/argocd/helm-charts/agent/v1.0.0
+helm template weather-x402-agent . -n agents \
+ --set image.repository=europe-west3-docker.pkg.dev/nevermined-eu-dev/nevermined-io/tutorials-weather-x402 \
+ --set image.tag=sha-testsha \
+ --set image.pullPolicy=Always \
+ --set service.hostname=weather-x402-agent.nevermined.app \
+ --set service.ports.port=3000 \
+ --set service.ports.targetPort=3000 \
+ --set service.ports.containerPort=3000 \
+ --set replicaCount=1 \
+ --set initCommand="yarn start" \
+ --set ingress.rateLimitEnabled=true \
+ --set env.NVM_ENVIRONMENT=sandbox \
+ --set env.NVM_API_KEY="gcp:secretmanager:projects/112425687177/secrets/tutorials-weather-nvm-api-key"
+```
+
+Rendered (helm v3.10.1), no template errors, four resources:
+
+- **ServiceAccount** `weather-x402-agent`, namespace `agents`, GKE Workload
+ Identity annotation present.
+- **Service** `weather-x402-agent`, namespace `agents`, `ClusterIP`, port
+ `3000` → targetPort `3000`.
+- **Deployment** `weather-x402-agent`, namespace `agents`, `replicas: 1`,
+ image `europe-west3-docker.pkg.dev/nevermined-eu-dev/nevermined-io/tutorials-weather-x402:sha-testsha`,
+ `imagePullPolicy: Always`, command wrapped by `/secrets/secrets-init`,
+ `initCommand` = `yarn start`. Rendered env block (fixed list — this is what
+ confirms finding (b) above):
+ ```
+ - name: NVM_API_KEY
+ value: gcp:secretmanager:projects/112425687177/secrets/tutorials-weather-nvm-api-key
+ - name: OPENAI_API_KEY
+ value:
+ - name: NVM_ENVIRONMENT
+ value: sandbox
+ - name: AGENT_DID
+ value:
+ ... (unrelated fixed keys for other agents, all empty here) ...
+ - name: BASE_URL
+ value: https://weather-x402-agent.nevermined.app
+ ```
+ `PLAN_ID_CREDITS` / `PLAN_ID_TIME` / `PLAN_ID_PAYG` are **absent** from this
+ list, confirming the chart patch above is required.
+- **Ingress** `weather-x402-agent`, host `weather-x402-agent.nevermined.app`,
+ rate-limit annotations present (`rateLimitEnabled=true`), TLS via
+ `letsencrypt-prod` cluster issuer, backend service port `3000`.
+
+`helm` was available locally (`v3.10.1`); no cluster contact was made — this
+is template rendering only.
+
+## Human deploy steps (gated — not run by the agent that authored this)
+
+1. **Patch the chart** (see above): add the three `PLAN_ID_*` env lines to
+ `helm-charts/agent/v1.0.0/templates/deployment.yaml` in the `argocd` repo.
+ Bump the chart's `Chart.yaml` `version`/`appVersion` if that repo's
+ convention expects it for template-only changes (check recent chart
+ commits for precedent).
+2. **Create the GCP Secret Manager secret** referenced by both manifests:
+ `projects/112425687177/secrets/tutorials-weather-nvm-api-key`, containing
+ the builder's `NVM_API_KEY` (the same key created in Task 4 /
+ `register-plans.ts`). Grant the GKE node/Workload Identity service account
+ (`112425687177-compute@developer.gserviceaccount.com`, per the rendered
+ ServiceAccount annotation above) `roles/secretmanager.secretAccessor` on
+ it, matching how `openai-api-key` is already granted for
+ demo-finance-agent.
+ - Prod and staging manifests point at the **same** secret path here
+ (single sandbox builder key). Split into a second secret first if the
+ two environments should not share credentials/spending.
+3. **Run `yarn register-plans`** in `http-simple-agent-ts/` against the
+ target environment to obtain the three real plan IDs, then replace
+ `REPLACE_WITH_PLAN_ID` for `env.PLAN_ID_CREDITS` / `PLAN_ID_TIME` /
+ `PLAN_ID_PAYG` in both manifests (staging can reuse the same plan IDs or
+ register its own — decide based on whether staging spend should be
+ isolated).
+4. **Replace the image tag.** After the first CI build on `main` (see
+ `.github/workflows/weather-x402-image.yml`), copy the printed `sha-`
+ tag into `image.tag` in both manifests, replacing
+ `sha-REPLACE_AFTER_FIRST_CI_BUILD`.
+5. **Copy the two Application files** from this directory into
+ `eu/dev/argocd-apps/agents/` in the `argocd` repo (paths in the table
+ above), alongside the chart patch from step 1, in one PR.
+6. **Commit, push, open the PR** in the `argocd` repo, get it reviewed, merge
+ to `main`.
+7. **ArgoCD auto-syncs** the `agents` namespace (`syncPolicy.automated` with
+ `prune`/`selfHeal`) — no manual `kubectl apply` needed once merged.
+8. **Verify the deployment is live**:
+ ```bash
+ curl -fsS https://weather-x402-agent.nevermined.app/health
+ kubectl -n agents get deploy weather-x402-agent
+ ```
+ Expect `{"ok":true}` and `1/1` ready. Then re-run Task 5's `smoke.ts` with
+ `SERVER_URL=https://weather-x402-agent.nevermined.app` so both protocols
+ pay against the live service. Repeat steps 3, 4 and 8 (with the `-staging`
+ names/hostname) for the staging Application.
+
+None of the above (chart patch, secret creation, plan registration against a
+real deployment target, `argocd` repo commit/push/PR, `kubectl`) was
+performed by the agent that authored these files — this task is gated to
+author + validate only.
diff --git a/http-simple-agent-ts/deploy/argocd/weather-x402-agent-staging.yaml b/http-simple-agent-ts/deploy/argocd/weather-x402-agent-staging.yaml
new file mode 100644
index 00000000..11f722b4
--- /dev/null
+++ b/http-simple-agent-ts/deploy/argocd/weather-x402-agent-staging.yaml
@@ -0,0 +1,66 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: weather-x402-agent-staging
+ namespace: argocd
+ finalizers:
+ - resources-finalizer.argocd.argoproj.io
+ # No argocd-image-updater.* annotations: the image tag is pinned to an
+ # immutable `sha-` tag printed by CI on push to main (Artifact
+ # Registry has immutableTags=true), not a moving semver tag. Bump
+ # image.tag below by hand (or via PR) after each build you want deployed.
+spec:
+ project: default
+ source:
+ path: helm-charts/agent/v1.0.0
+ repoURL: git@github.com:nevermined-io/argocd.git
+ targetRevision: main
+ helm:
+ parameters:
+ - name: image.repository
+ value: europe-west3-docker.pkg.dev/nevermined-eu-dev/nevermined-io/tutorials-weather-x402
+ - name: image.tag
+ value: sha-REPLACE_AFTER_FIRST_CI_BUILD
+ - name: image.pullPolicy
+ value: Always
+ - name: replicaCount
+ value: "1"
+ - name: env.NVM_ENVIRONMENT
+ value: sandbox
+ - name: env.NVM_API_KEY
+ value: gcp:secretmanager:projects/112425687177/secrets/tutorials-weather-nvm-api-key
+ - name: env.PLAN_ID_CREDITS
+ value: REPLACE_WITH_PLAN_ID
+ - name: env.PLAN_ID_TIME
+ value: REPLACE_WITH_PLAN_ID
+ - name: env.PLAN_ID_PAYG
+ value: REPLACE_WITH_PLAN_ID
+ - name: service.hostname
+ value: weather-x402-agent-staging.nevermined.app
+ - name: service.ports.port
+ value: "3000"
+ - name: service.ports.targetPort
+ value: "3000"
+ - name: service.ports.containerPort
+ value: "3000"
+ - name: initCommand
+ value: yarn start
+ - name: ingress.rateLimitEnabled
+ value: "true"
+ destination:
+ namespace: agents
+ server: https://kubernetes.default.svc
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - PrunePropagationPolicy=foreground
+ - PruneLast=true
+ retry:
+ limit: 5
+ backoff:
+ duration: 5s
+ factor: 2
+ maxDuration: 3m
diff --git a/http-simple-agent-ts/deploy/argocd/weather-x402-agent.yaml b/http-simple-agent-ts/deploy/argocd/weather-x402-agent.yaml
new file mode 100644
index 00000000..578de7ed
--- /dev/null
+++ b/http-simple-agent-ts/deploy/argocd/weather-x402-agent.yaml
@@ -0,0 +1,66 @@
+apiVersion: argoproj.io/v1alpha1
+kind: Application
+metadata:
+ name: weather-x402-agent
+ namespace: argocd
+ finalizers:
+ - resources-finalizer.argocd.argoproj.io
+ # No argocd-image-updater.* annotations: the image tag is pinned to an
+ # immutable `sha-` tag printed by CI on push to main (Artifact
+ # Registry has immutableTags=true), not a moving semver tag. Bump
+ # image.tag below by hand (or via PR) after each build you want deployed.
+spec:
+ project: default
+ source:
+ path: helm-charts/agent/v1.0.0
+ repoURL: git@github.com:nevermined-io/argocd.git
+ targetRevision: main
+ helm:
+ parameters:
+ - name: image.repository
+ value: europe-west3-docker.pkg.dev/nevermined-eu-dev/nevermined-io/tutorials-weather-x402
+ - name: image.tag
+ value: sha-REPLACE_AFTER_FIRST_CI_BUILD
+ - name: image.pullPolicy
+ value: Always
+ - name: replicaCount
+ value: "1"
+ - name: env.NVM_ENVIRONMENT
+ value: sandbox
+ - name: env.NVM_API_KEY
+ value: gcp:secretmanager:projects/112425687177/secrets/tutorials-weather-nvm-api-key
+ - name: env.PLAN_ID_CREDITS
+ value: REPLACE_WITH_PLAN_ID
+ - name: env.PLAN_ID_TIME
+ value: REPLACE_WITH_PLAN_ID
+ - name: env.PLAN_ID_PAYG
+ value: REPLACE_WITH_PLAN_ID
+ - name: service.hostname
+ value: weather-x402-agent.nevermined.app
+ - name: service.ports.port
+ value: "3000"
+ - name: service.ports.targetPort
+ value: "3000"
+ - name: service.ports.containerPort
+ value: "3000"
+ - name: initCommand
+ value: yarn start
+ - name: ingress.rateLimitEnabled
+ value: "true"
+ destination:
+ namespace: agents
+ server: https://kubernetes.default.svc
+ syncPolicy:
+ automated:
+ prune: true
+ selfHeal: true
+ syncOptions:
+ - CreateNamespace=true
+ - PrunePropagationPolicy=foreground
+ - PruneLast=true
+ retry:
+ limit: 5
+ backoff:
+ duration: 5s
+ factor: 2
+ maxDuration: 3m
From a74504742de85e4670ed250e39b645e952d409e3 Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 18:04:35 +0200
Subject: [PATCH 11/24] docs: implementation plan for weather-x402
dual-protocol backend
---
.../2026-09-04-weather-x402-mpp-backend.md | 597 ++++++++++++++++++
1 file changed, 597 insertions(+)
create mode 100644 docs/superpowers/plans/2026-09-04-weather-x402-mpp-backend.md
diff --git a/docs/superpowers/plans/2026-09-04-weather-x402-mpp-backend.md b/docs/superpowers/plans/2026-09-04-weather-x402-mpp-backend.md
new file mode 100644
index 00000000..7c7332b0
--- /dev/null
+++ b/docs/superpowers/plans/2026-09-04-weather-x402-mpp-backend.md
@@ -0,0 +1,597 @@
+# Weather x402 + MPP Backend — Implementation Plan
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** Turn `http-simple-agent-ts` into a keyless weather service that exposes three payment-plan routes (fixed-credits, time-based, pay-as-you-go), each speaking **both** x402 and MPP, then containerize it and deploy it to the `agents` namespace as `weather-x402-agent.nevermined.app`.
+
+**Architecture:** One Express app, one `paymentMiddleware(payments, routes)` call. Each route names a different plan and sets `mpp: true`, so a single 402 advertises x402 *and* MPP and either buyer works against the same URL. Weather comes from Open-Meteo (no API key). Plans are registered once by a script; the service reads their IDs from env. The image builds from `http-simple-agent-ts/` and deploys through the shared `helm-charts/agent` chart, mirroring the existing `demo-finance-agent` / `tutorials-showcase` deploy paths.
+
+**Tech Stack:** TypeScript, Express 4, `@nevermined-io/payments` (x402 + MPP), Open-Meteo REST, Docker (node:20-alpine), GitHub Actions + GCP Artifact Registry + WIF, ArgoCD + Helm.
+
+**Spec:** in-conversation spec dated 2026-09-04 ("weather-x402 — a live dual-protocol paid backend for the tutorials"). Read it alongside this plan.
+
+## Global Constraints
+
+- **Language is TypeScript, not Python.** MPP exists only in the TS SDK + backend; `payments-py` has x402 only. A dual-protocol service must be TS.
+- **`@nevermined-io/payments` must be bumped from `^1.1.0` to a version that ships `payments.mpp` and the `mpp` route option, and pinned to an exact version** (the SDK doc labels the `payments.mpp.*` buyer surface `@experimental` and says fields may move in a minor release — pin so a redeploy can't drift). Resolve the exact version from `~/Projects/Nevermined/payments/package.json`.
+- **MPP single-use guards are in-process (in-memory), not shared across replicas.** The Deployment MUST stay `replicaCount: 1`. Horizontal scaling would require a shared store (Redis) and is out of scope.
+- **Plans use a crypto (erc4337-payable) price**, because `payments.mpp.fetch` mints `nvm:erc4337` only this release. A fiat/card plan would be payable by x402 card-delegation but **not** by MPP — so one plan payable by both protocols must be crypto-priced.
+- **Environment is `sandbox`.** No real money.
+- **No OpenAI dependency.** Weather is keyless; the service must run with no `OPENAI_API_KEY`.
+- Match the surrounding tutorial style: plain `tsx` scripts, assert-based self-checks (as in `showcase/lib/demo-agent.mjs`), no test framework unless one already exists in the dir.
+
+---
+
+## File Structure
+
+Everything lives in `http-simple-agent-ts/` (the deployed image builds from here) except the deploy manifests, which live in the separate `argocd` repo.
+
+- `http-simple-agent-ts/src/agent.ts` — **modify**. The Express server: 3 dual-protocol weather routes + `/health`. This is the deployed entrypoint.
+- `http-simple-agent-ts/src/services/weather.service.ts` — **create** (copied from `mcp-examples/weather-mcp/src/services/weather.service.ts`), extended with `getForecast(city, days)`.
+- `http-simple-agent-ts/src/pricing.ts` — **create**. Pure `priceForRequest(body)` → credits, so pay-as-you-go pricing is unit-testable without HTTP or payments.
+- `http-simple-agent-ts/src/pricing.selfcheck.ts` — **create**. Assert-based `node`/`tsx` self-check for `priceForRequest`.
+- `http-simple-agent-ts/scripts/register-plans.ts` — **create**. One-shot: registers the three plans, prints their IDs.
+- `http-simple-agent-ts/scripts/smoke.ts` — **create**. Runnable e2e: exercises x402 and MPP against a running server; the Plan 1 verification.
+- `http-simple-agent-ts/package.json` — **modify**. Bump payments, add `start` + script entries, drop the OpenAI-only assumptions.
+- `http-simple-agent-ts/.env.example` — **modify**. New env surface (plan IDs, no OpenAI).
+- `http-simple-agent-ts/Dockerfile` — **create** (from `mcp-examples/weather-mcp/Dockerfile`), entrypoint fixed to run the server.
+- `.github/workflows/weather-x402-image.yml` — **create** (from `.github/workflows/showcase-image.yml`).
+- `argocd: eu/dev/argocd-apps/agents/weather-x402-agent.yaml` (+ `-staging.yaml`) — **create** (from `demo-finance-agent.yaml`).
+- `argocd: helm-charts/agent/v1.0.0/.argocd-source-weather-x402-agent.yaml` — **create** (image-updater mirror; only if image-updater is used).
+
+---
+
+## Phase A — Keyless weather foundation
+
+### Task 1: Dependencies, scripts, env surface
+
+**Files:**
+- Modify: `http-simple-agent-ts/package.json`
+- Modify: `http-simple-agent-ts/.env.example`
+
+**Interfaces:**
+- Produces: a `yarn start` script (`node dist/agent.js`) that the Dockerfile entrypoint relies on; env vars `NVM_API_KEY`, `NVM_ENVIRONMENT`, `PLAN_ID_CREDITS`, `PLAN_ID_TIME`, `PLAN_ID_PAYG`, `PORT`.
+
+- [ ] **Step 1: Bump payments and add scripts.** In `package.json`, set `@nevermined-io/payments` to the exact version resolved from `~/Projects/Nevermined/payments/package.json` (e.g. `"1.19.0"` — verify, no caret), and add scripts:
+
+```json
+"scripts": {
+ "agent": "tsx src/agent.ts",
+ "client": "tsx src/client.ts",
+ "register-plans": "tsx scripts/register-plans.ts",
+ "smoke": "tsx scripts/smoke.ts",
+ "pricing:selfcheck": "tsx src/pricing.selfcheck.ts",
+ "build": "tsc",
+ "start": "node dist/agent.js"
+}
+```
+
+Remove `openai` from `dependencies` (the service no longer calls an LLM). Leave `agent-observability.ts` alone for now — it is out of scope; if `tsc` fails on it because it still imports `openai`, exclude it in `tsconfig.json` (`"exclude": ["node_modules","dist","src/agent-observability.ts"]`) rather than fixing it here.
+
+- [ ] **Step 2: Rewrite `.env.example`:**
+
+```bash
+# Nevermined (required)
+NVM_API_KEY=nvm:your-api-key
+NVM_ENVIRONMENT=sandbox
+
+# Plan IDs — created by `yarn register-plans` (see scripts/register-plans.ts)
+PLAN_ID_CREDITS=
+PLAN_ID_TIME=
+PLAN_ID_PAYG=
+
+# Server
+PORT=3000
+```
+
+- [ ] **Step 3: Install and verify it resolves.**
+
+Run: `cd http-simple-agent-ts && yarn install`
+Expected: installs without error; `yarn list @nevermined-io/payments` shows the pinned version.
+
+- [ ] **Step 4: Verify MPP is present in the installed SDK.**
+
+Run: `node -e "const p=require('@nevermined-io/payments'); console.log(typeof require('@nevermined-io/payments/express').paymentMiddleware, Object.keys(require('@nevermined-io/payments/express')))"`
+Expected: prints `function` and the export list includes `MPP_HEADERS` and `X402_HEADERS`. If `MPP_HEADERS` is absent, the version is too old — raise it.
+
+- [ ] **Step 5: Commit.**
+
+```bash
+git add http-simple-agent-ts/package.json http-simple-agent-ts/.env.example http-simple-agent-ts/yarn.lock
+git commit -m "chore(http-ts): bump payments for MPP, drop OpenAI, add plan-id env"
+```
+
+### Task 2: Weather service + pure pricing function
+
+**Files:**
+- Create: `http-simple-agent-ts/src/services/weather.service.ts`
+- Create: `http-simple-agent-ts/src/pricing.ts`
+- Create: `http-simple-agent-ts/src/pricing.selfcheck.ts`
+
+**Interfaces:**
+- Produces:
+ - `getTodayWeather(city: string): Promise` and `getForecast(city: string, days: number): Promise` from `weather.service.ts`.
+ - `priceForRequest(body: unknown): number` from `pricing.ts` — 1 credit for a current-weather/single-day request, `days` credits (capped 1..7) for a multi-day forecast.
+
+- [ ] **Step 1: Copy the weather service verbatim, then extend it.** Copy `mcp-examples/weather-mcp/src/services/weather.service.ts` to `http-simple-agent-ts/src/services/weather.service.ts`. Drop the `console.log` latency line (repo style forbids `console.log` in production code). Append a multi-day forecast reader:
+
+```typescript
+export type ForecastDay = {
+ date: string;
+ tmaxC: number | null;
+ tminC: number | null;
+ precipitationMm: number | null;
+ weatherCode: number | null;
+ weatherText: string | null;
+};
+
+export type ForecastWeather = {
+ city: string;
+ country: string | null;
+ timezone: string;
+ updatedAt: string;
+ days: ForecastDay[];
+};
+
+export async function getForecast(city: string, days: number): Promise {
+ const n = Math.max(1, Math.min(7, Math.trunc(days)));
+ const geo = await geocodeCity(city);
+ const url = new URL("https://api.open-meteo.com/v1/forecast");
+ url.searchParams.set("latitude", String(geo.latitude));
+ url.searchParams.set("longitude", String(geo.longitude));
+ url.searchParams.set("forecast_days", String(n));
+ url.searchParams.set("timezone", "auto");
+ url.searchParams.set("daily", "temperature_2m_max,temperature_2m_min,precipitation_sum,weathercode");
+
+ let res: Response;
+ try {
+ res = await fetch(url);
+ } catch {
+ throw new DownstreamError("Failed to reach Open-Meteo forecast API");
+ }
+ if (!res.ok) throw new DownstreamError(`Forecast API returned HTTP ${res.status}`);
+
+ const data = (await res.json()) as any;
+ const d = data.daily ?? {};
+ const time: string[] = Array.isArray(d.time) ? d.time : [];
+ const daysOut: ForecastDay[] = time.map((date: string, i: number) => {
+ const code = Array.isArray(d.weathercode) ? Number(d.weathercode[i]) : null;
+ return {
+ date,
+ tmaxC: Array.isArray(d.temperature_2m_max) ? Number(d.temperature_2m_max[i]) : null,
+ tminC: Array.isArray(d.temperature_2m_min) ? Number(d.temperature_2m_min[i]) : null,
+ precipitationMm: Array.isArray(d.precipitation_sum) ? Number(d.precipitation_sum[i]) : null,
+ weatherCode: code,
+ weatherText: weatherCodeToText(code),
+ };
+ });
+
+ return {
+ city: geo.name,
+ country: geo.country,
+ timezone: data.timezone ?? geo.timezone ?? "unknown",
+ updatedAt: new Date().toISOString(),
+ days: daysOut,
+ };
+}
+```
+
+- [ ] **Step 2: Write the failing pricing self-check first.** Create `src/pricing.selfcheck.ts`:
+
+```typescript
+import { priceForRequest } from "./pricing.js";
+
+const assert = (c: boolean, m: string) => { if (!c) throw new Error("FAIL: " + m); };
+
+assert(priceForRequest({ city: "Lisbon" }) === 1, "no days → 1 credit");
+assert(priceForRequest({ city: "Lisbon", days: 1 }) === 1, "1 day → 1 credit");
+assert(priceForRequest({ city: "Lisbon", days: 7 }) === 7, "7 days → 7 credits");
+assert(priceForRequest({ city: "Lisbon", days: 99 }) === 7, "days capped at 7");
+assert(priceForRequest({ city: "Lisbon", days: 0 }) === 1, "days floored at 1");
+assert(priceForRequest({ city: "Lisbon", days: "3" as any }) === 3, "numeric string coerced");
+assert(priceForRequest({}) === 1, "empty body → 1 credit");
+console.log("✓ pricing self-check passed");
+```
+
+- [ ] **Step 3: Run it — must fail (module missing).**
+
+Run: `cd http-simple-agent-ts && yarn pricing:selfcheck`
+Expected: FAIL — cannot find `./pricing.js` / `priceForRequest` is not a function.
+
+- [ ] **Step 4: Implement `src/pricing.ts` minimally.**
+
+```typescript
+/** Pay-as-you-go price: 1 credit for current weather, `days` credits (1..7) for a forecast. */
+export function priceForRequest(body: unknown): number {
+ const raw = (body as { days?: unknown } | null | undefined)?.days;
+ const n = typeof raw === "number" ? raw : typeof raw === "string" ? Number(raw) : NaN;
+ if (!Number.isFinite(n)) return 1;
+ return Math.max(1, Math.min(7, Math.trunc(n)));
+}
+```
+
+- [ ] **Step 5: Run the self-check — must pass.**
+
+Run: `cd http-simple-agent-ts && yarn pricing:selfcheck`
+Expected: `✓ pricing self-check passed`
+
+- [ ] **Step 6: Commit.**
+
+```bash
+git add http-simple-agent-ts/src/services/weather.service.ts http-simple-agent-ts/src/pricing.ts http-simple-agent-ts/src/pricing.selfcheck.ts
+git commit -m "feat(http-ts): keyless weather service + pay-as-you-go pricing fn"
+```
+
+---
+
+## Phase B — Dual-protocol routes over three plans
+
+### Task 3: Rewrite `agent.ts` as the dual-protocol weather server
+
+**Files:**
+- Modify: `http-simple-agent-ts/src/agent.ts` (full rewrite)
+
+**Interfaces:**
+- Consumes: `getTodayWeather`, `getForecast` (Task 2); `priceForRequest` (Task 2); `paymentMiddleware`, `X402_HEADERS`, `MPP_HEADERS` from `@nevermined-io/payments/express`.
+- Produces: routes `POST /weather/credits`, `POST /weather/subscription`, `POST /weather/payg`, `GET /health` on `PORT`.
+
+- [ ] **Step 1: Replace the file body.** Note the route→plan→credits mapping and that `mpp: true` is set on every paid route.
+
+```typescript
+import "dotenv/config";
+import express, { Request, Response, RequestHandler } from "express";
+import { Payments, EnvironmentName } from "@nevermined-io/payments";
+import { paymentMiddleware, X402_HEADERS, MPP_HEADERS } from "@nevermined-io/payments/express";
+import { getTodayWeather, getForecast, CityNotFoundError } from "./services/weather.service.js";
+import { priceForRequest } from "./pricing.js";
+
+const PORT = process.env.PORT ? Number(process.env.PORT) : 3000;
+const NVM_API_KEY = process.env.NVM_API_KEY ?? "";
+const NVM_ENVIRONMENT = (process.env.NVM_ENVIRONMENT || "sandbox") as EnvironmentName;
+const PLAN_ID_CREDITS = process.env.PLAN_ID_CREDITS ?? "";
+const PLAN_ID_TIME = process.env.PLAN_ID_TIME ?? "";
+const PLAN_ID_PAYG = process.env.PLAN_ID_PAYG ?? "";
+
+if (!NVM_API_KEY || !PLAN_ID_CREDITS || !PLAN_ID_TIME || !PLAN_ID_PAYG) {
+ console.error("NVM_API_KEY, PLAN_ID_CREDITS, PLAN_ID_TIME and PLAN_ID_PAYG are required.");
+ process.exit(1);
+}
+
+const payments = Payments.getInstance({ nvmApiKey: NVM_API_KEY, environment: NVM_ENVIRONMENT });
+
+const app = express();
+app.use(express.json());
+
+// /health stays unprotected — mount it before the paywall.
+app.get("/health", (_req: Request, res: Response) => res.json({ ok: true }));
+
+// One middleware, three plans, both protocols. `mpp: true` makes each 402 advertise
+// x402 AND MPP, so either buyer works against the same URL.
+app.use(
+ paymentMiddleware(
+ payments,
+ {
+ "POST /weather/credits": { planId: PLAN_ID_CREDITS, credits: 1, mpp: true },
+ "POST /weather/subscription": { planId: PLAN_ID_TIME, credits: 1, mpp: true },
+ "POST /weather/payg": {
+ planId: PLAN_ID_PAYG,
+ credits: (req: Request) => priceForRequest(req.body),
+ mpp: true,
+ },
+ },
+ {
+ onBeforeVerify: (req) => console.log(`[pay] verify ${req.method} ${req.path}`),
+ onAfterSettle: (req, credits) => console.log(`[pay] settled ${credits} on ${req.path}`),
+ },
+ ) as RequestHandler,
+);
+
+async function handleToday(req: Request, res: Response) {
+ try {
+ const { city } = req.body as { city?: string };
+ if (!city) return res.status(400).json({ error: "Missing 'city'" });
+ return res.json(await getTodayWeather(city));
+ } catch (err) {
+ if (err instanceof CityNotFoundError) return res.status(404).json({ error: err.message });
+ console.error(err);
+ return res.status(502).json({ error: "weather upstream failed" });
+ }
+}
+
+app.post("/weather/credits", handleToday);
+app.post("/weather/subscription", handleToday);
+
+app.post("/weather/payg", async (req: Request, res: Response) => {
+ try {
+ const { city, days } = req.body as { city?: string; days?: number };
+ if (!city) return res.status(400).json({ error: "Missing 'city'" });
+ return res.json(days && days > 1 ? await getForecast(city, days) : await getTodayWeather(city));
+ } catch (err) {
+ if (err instanceof CityNotFoundError) return res.status(404).json({ error: err.message });
+ console.error(err);
+ return res.status(502).json({ error: "weather upstream failed" });
+ }
+});
+
+app.listen(PORT, () => {
+ console.log(`weather-x402 agent on http://localhost:${PORT}`);
+ console.log(`x402 header: ${X402_HEADERS.PAYMENT_SIGNATURE} · MPP header: ${MPP_HEADERS.AUTHORIZATION}`);
+});
+```
+
+> If `MPP_HEADERS`'s field for the `Authorization` credential is named differently in the installed SDK, adjust the log line — read the export from `node_modules/@nevermined-io/payments/dist/.../express`. Do not invent a name.
+
+- [ ] **Step 2: Type-check.**
+
+Run: `cd http-simple-agent-ts && yarn build`
+Expected: `tsc` exits 0. (If it fails on `agent-observability.ts`, confirm Task 1 Step 1's exclude is in place.)
+
+- [ ] **Step 3: Boot with dummy env to confirm the guard.**
+
+Run: `cd http-simple-agent-ts && NVM_API_KEY=x PLAN_ID_CREDITS=x PLAN_ID_TIME=x PLAN_ID_PAYG=x PORT=3999 timeout 5 yarn start || true` (after `yarn build`)
+Expected: prints the boot banner (SDK init may warn on the fake key — acceptable; we only assert it reaches `listen`).
+
+- [ ] **Step 4: Commit.**
+
+```bash
+git add http-simple-agent-ts/src/agent.ts http-simple-agent-ts/tsconfig.json
+git commit -m "feat(http-ts): dual-protocol weather routes over three plans"
+```
+
+---
+
+## Phase C — Plan registration
+
+### Task 4: `register-plans.ts`
+
+**Files:**
+- Create: `http-simple-agent-ts/scripts/register-plans.ts`
+
+**Interfaces:**
+- Produces: three plan IDs printed to stdout, to be pasted into `.env` / stored in Secret Manager.
+
+> Verify every builder/register name against `~/Projects/Nevermined/payments/src/plans.ts` and `src/api/plans-api.ts` before running — the SDK is the source of truth. The shape below matches the surface documented in the spec's evidence table.
+
+- [ ] **Step 1: Write the script.**
+
+```typescript
+import "dotenv/config";
+import { Payments, EnvironmentName } from "@nevermined-io/payments";
+import {
+ getFixedCreditsConfig,
+ getExpirableDurationConfig,
+ getDynamicCreditsConfig,
+ getCryptoPriceConfig,
+ ONE_DAY_DURATION,
+} from "@nevermined-io/payments";
+
+const payments = Payments.getInstance({
+ nvmApiKey: process.env.NVM_API_KEY!,
+ environment: (process.env.NVM_ENVIRONMENT || "sandbox") as EnvironmentName,
+});
+
+// Crypto price so BOTH x402 (erc4337) and MPP can pay it. Use the builder's
+// signature from the SDK; `receivers` is the builder's wallet address.
+const price = getCryptoPriceConfig(/* amount */ 0n, /* receiver */ process.env.NVM_RECEIVER ?? "");
+
+async function main() {
+ const credits = await payments.plans.registerCreditsPlan(
+ { name: "Weather — Fixed Credits", description: "100 weather calls, 1 credit each" },
+ price,
+ getFixedCreditsConfig(100n, 1n),
+ );
+ const time = await payments.plans.registerTimePlan(
+ { name: "Weather — Day Pass", description: "24h of weather access" },
+ price,
+ getExpirableDurationConfig(ONE_DAY_DURATION),
+ );
+ const payg = await payments.plans.registerPlan(
+ { name: "Weather — Pay As You Go", description: "1 credit current, up to 7 for a forecast" },
+ price,
+ getDynamicCreditsConfig(1000n, 1n, 7n),
+ );
+
+ console.log("PLAN_ID_CREDITS=" + (credits.planId ?? credits));
+ console.log("PLAN_ID_TIME=" + (time.planId ?? time));
+ console.log("PLAN_ID_PAYG=" + (payg.planId ?? payg));
+}
+
+main().catch((e) => { console.error(e); process.exit(1); });
+```
+
+- [ ] **Step 2: Run against sandbox with a real builder key.**
+
+Run: `cd http-simple-agent-ts && NVM_API_KEY= NVM_RECEIVER= yarn register-plans`
+Expected: three `PLAN_ID_*=...` lines. If a builder name/signature mismatches, fix against `plans.ts` (this is the one task that can't be dry-run).
+
+- [ ] **Step 3: Record the IDs** in `.env` locally, and note them for the Secret Manager step (Task 8). Do **not** commit real IDs into `.env.example`.
+
+- [ ] **Step 4: Commit the script only.**
+
+```bash
+git add http-simple-agent-ts/scripts/register-plans.ts
+git commit -m "feat(http-ts): plan registration script (credits/time/payg)"
+```
+
+---
+
+## Phase D — Local end-to-end verification
+
+### Task 5: `smoke.ts` — x402 and MPP round-trips
+
+**Files:**
+- Create: `http-simple-agent-ts/scripts/smoke.ts`
+
+**Interfaces:**
+- Consumes: a running server (Task 3) and the three plan IDs (Task 4); a **funded sandbox buyer** `NVM_API_KEY` with an `erc4337` delegation.
+
+- [ ] **Step 1: Write the smoke test.** It asserts: no-token → 402 advertising both protocols; x402 token → 200; MPP fetch → 200 + receipt.
+
+```typescript
+import "dotenv/config";
+import { Payments, EnvironmentName } from "@nevermined-io/payments";
+import { X402_HEADERS } from "@nevermined-io/payments/express";
+
+const BASE = process.env.SERVER_URL || "http://localhost:3000";
+const PLAN = process.env.PLAN_ID_CREDITS!;
+const payments = Payments.getInstance({
+ nvmApiKey: process.env.NVM_API_KEY!,
+ environment: (process.env.NVM_ENVIRONMENT || "sandbox") as EnvironmentName,
+});
+const assert = (c: boolean, m: string) => { if (!c) throw new Error("FAIL: " + m); };
+
+async function main() {
+ // 1) Unpaid → 402 advertising BOTH protocols
+ const r0 = await fetch(`${BASE}/weather/credits`, {
+ method: "POST", headers: { "content-type": "application/json" },
+ body: JSON.stringify({ city: "Lisbon" }),
+ });
+ assert(r0.status === 402, "unpaid → 402");
+ assert(!!r0.headers.get(X402_HEADERS.PAYMENT_REQUIRED), "x402 challenge present");
+ assert(!!r0.headers.get("www-authenticate"), "MPP WWW-Authenticate present");
+
+ // 2) x402 buyer → 200
+ const { accessToken } = await payments.x402.getX402AccessToken(PLAN);
+ const r1 = await fetch(`${BASE}/weather/credits`, {
+ method: "POST",
+ headers: { "content-type": "application/json", [X402_HEADERS.PAYMENT_SIGNATURE]: accessToken },
+ body: JSON.stringify({ city: "Lisbon" }),
+ });
+ assert(r1.status === 200, `x402 paid → 200 (got ${r1.status})`);
+ const w = await r1.json();
+ assert(typeof w.city === "string", "x402 returned real weather");
+
+ // 3) MPP buyer → 200 + receipt
+ const { delegationId } = await payments.delegation.createDelegation({
+ provider: "erc4337", spendingLimitCents: 10000, durationSecs: 604800, currency: "usdc",
+ });
+ const { response, receipt, paid } = await payments.mpp.fetch(
+ `${BASE}/weather/credits`,
+ { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ city: "Berlin" }) },
+ { delegationConfig: { delegationId }, planId: PLAN },
+ );
+ assert(response.status === 200, `MPP paid → 200 (got ${response.status})`);
+ assert(paid && !!receipt, "MPP settled with a receipt");
+
+ console.log("✓ smoke: x402 + MPP both paid a real weather response");
+}
+main().catch((e) => { console.error(e); process.exit(1); });
+```
+
+- [ ] **Step 2: Run it against a locally running server.**
+
+Run (two shells): `yarn start` in one; `SERVER_URL=http://localhost:3000 NVM_API_KEY= PLAN_ID_CREDITS= yarn smoke` in the other.
+Expected: `✓ smoke: x402 + MPP both paid a real weather response`. A `402` on step 2/3 usually means the buyer wallet is unfunded on sandbox — fund it, don't change the assert.
+
+- [ ] **Step 3: Commit.**
+
+```bash
+git add http-simple-agent-ts/scripts/smoke.ts
+git commit -m "test(http-ts): x402 + MPP smoke e2e"
+```
+
+---
+
+## Phase E — Containerize and deploy
+
+### Task 6: Dockerfile
+
+**Files:**
+- Create: `http-simple-agent-ts/Dockerfile`
+
+- [ ] **Step 1: Write it** (from the weather-mcp Dockerfile; entrypoint runs the server via the new `start` script, and the build needs `tsconfig.json`):
+
+```dockerfile
+FROM node:20-alpine
+LABEL maintainer="Nevermined "
+RUN apk add --no-cache libc6-compat yarn
+WORKDIR /app
+COPY package.json yarn.lock ./
+RUN yarn install --frozen-lockfile --non-interactive
+COPY src ./src
+COPY tsconfig.json ./
+RUN yarn build
+EXPOSE 3000
+ENTRYPOINT ["yarn", "start"]
+```
+
+- [ ] **Step 2: Build and run locally.**
+
+Run: `cd http-simple-agent-ts && docker build -t weather-x402:dev . && docker run --rm -p 3000:3000 -e NVM_API_KEY=x -e PLAN_ID_CREDITS=x -e PLAN_ID_TIME=x -e PLAN_ID_PAYG=x weather-x402:dev &` then `sleep 4 && curl -fsS localhost:3000/health`
+Expected: `{"ok":true}`. Stop the container afterward.
+
+- [ ] **Step 3: Commit.**
+
+```bash
+git add http-simple-agent-ts/Dockerfile
+git commit -m "build(http-ts): Dockerfile for weather-x402 service"
+```
+
+### Task 7: CI workflow
+
+**Files:**
+- Create: `.github/workflows/weather-x402-image.yml`
+
+- [ ] **Step 1: Copy `showcase-image.yml`** and change only: workflow `name`; the `paths` filters to `http-simple-agent-ts/**` and this workflow file; `env.IMAGE` to `europe-west3-docker.pkg.dev/nevermined-eu-dev/nevermined-io/tutorials-weather-x402`; `defaults.run.working-directory` and the build `context`/`file` to `http-simple-agent-ts` / `http-simple-agent-ts/Dockerfile`. Keep the WIF `SERVICE_ACCOUNT` / `WORKLOAD_IDENTITY_PROVIDER` / `PROJECT_ID` blocks **unchanged** — this repo (`nevermined-io/tutorials`) is already allowlisted in the WIF pool (the showcase workflow proves it). Replace the `Sandbox agent self-check` step with `yarn pricing:selfcheck` (the smoke test needs live creds and does not run in CI).
+
+- [ ] **Step 2: Validate the YAML.**
+
+Run: `python3 -c "import yaml,sys; yaml.safe_load(open('.github/workflows/weather-x402-image.yml'))"` (or `actionlint` if installed)
+Expected: no error.
+
+- [ ] **Step 3: Commit.** (Push happens with the PR; the image builds on merge to `main`.)
+
+```bash
+git add .github/workflows/weather-x402-image.yml
+git commit -m "ci: build & push weather-x402 image to Artifact Registry"
+```
+
+### Task 8: ArgoCD Application + secrets (in the `argocd` repo)
+
+**Files (separate repo `~/Projects/Nevermined/argocd`, its own PR):**
+- Create: `eu/dev/argocd-apps/agents/weather-x402-agent.yaml`
+- Create: `eu/dev/argocd-apps/agents/weather-x402-agent-staging.yaml`
+- Create: `helm-charts/agent/v1.0.0/.argocd-source-weather-x402-agent.yaml` (only if using image-updater)
+
+- [ ] **Step 1: Copy `demo-finance-agent.yaml`** and set: `image.repository=europe-west3-docker.pkg.dev/nevermined-eu-dev/nevermined-io/tutorials-weather-x402`, `image.tag=sha-` (the immutable tag the CI prints), `service.hostname=weather-x402-agent.nevermined.app`, `service.ports.*=3000`, `initCommand=yarn start`, **`replicaCount: 1` (do not scale — MPP single-use is in-process)**, `ingress.rateLimitEnabled=true`. Set env params `NVM_ENVIRONMENT=sandbox` and the three `PLAN_ID_*`; set `secrets.nvmApiKey=gcp:secretmanager:projects/112425687177/secrets/` (create that Secret Manager secret first with the builder key from Task 4). Since the AR image is pinned by immutable `sha-*` tag, **prefer the pinned-tag path over image-updater** (drop the image-updater annotations and the `.argocd-source-*.yaml` mirror) — matches how the production apps pin AR tags. Repeat for `-staging` with `weather-x402-agent-staging.nevermined.app`.
+
+- [ ] **Step 2: Verify chart rendering locally.**
+
+Run: `helm template weather-x402-agent ~/Projects/Nevermined/argocd/helm-charts/agent/v1.0.0 --set image.repository=... --set service.hostname=weather-x402-agent.nevermined.app --set service.ports.port=3000 --set replicaCount=1`
+Expected: renders a Deployment (1 replica), Service, and Ingress for `weather-x402-agent.nevermined.app` with no template errors.
+
+- [ ] **Step 3: Open the argocd PR**, merge after review; ArgoCD auto-syncs the `agents` namespace.
+
+- [ ] **Step 4: Verify the deployment is live.**
+
+Run: `curl -fsS https://weather-x402-agent.nevermined.app/health` and `kubectl -n agents get deploy weather-x402-agent`
+Expected: `{"ok":true}`; deployment `1/1` ready. Then re-run Task 5's `smoke.ts` with `SERVER_URL=https://weather-x402-agent.nevermined.app` — both protocols pay against the live service.
+
+---
+
+## Self-review (done against the spec)
+
+- **Spec coverage:** dual-protocol on one route ✅ (Task 3 `mpp: true`); three plan types ✅ (Tasks 3–4); keyless weather ✅ (Tasks 1–2); Docker ✅ (Task 6); agents-namespace deploy ✅ (Tasks 7–8); acceptance criteria 1–7 map to Tasks 3/5/8 (criterion 8, showcase, is Plan 2). Not covered here by design: the frontend/tutorial rewrite (open question #5) → Plan 2 below.
+- **Consistency:** `priceForRequest` signature identical in Tasks 2/3/5; `PLAN_ID_*` names identical across `.env.example`, `agent.ts`, `register-plans.ts`, `smoke.ts`, and the Application.
+- **Known soft spots the implementer must confirm against the SDK, not invent:** exact pinned payments version; `MPP_HEADERS` field name; `getCryptoPriceConfig`/`registerPlan` signatures; the shape of the `registerPlan` return (`.planId` vs raw). All flagged inline.
+
+---
+
+## Roadmap: follow-on plans (2–4)
+
+Plan 1 delivers a live, dual-protocol, deployed backend. The remaining spec scope (open question #5 — "the frontend must be the tutorials") is a second plan, written once Plan 1's URL exists so its tasks can reference the real endpoint:
+
+- **Plan 2 — Tutorials consume the live backend.**
+ - Rewrite `http-simple-agent-ts/src/client.ts` to buy weather over x402 from the three routes (replaces the `/ask` + `{query}` flow).
+ - Rewrite `http-simple-agent-py` (server + client) as the **x402-only** weather service (Python has no MPP); its client can also target the deployed TS URL for x402, which is wire-compatible.
+ - New **MPP tutorial** (`http-mpp-agent-ts/` or an `mpp-client.ts` in the TS dir): the MPP buyer flow via `payments.mpp.fetch` against the same deployed dual-protocol server. TS-only; crypto (erc4337) delegation only — call this out, since `mpp.fetch` can't use card delegation this release.
+ - READMEs for each, kept in sync with code (repo rule).
+
+- **Plan 3 — Showcase live-run against the real backend.**
+ - Extend `showcase/app/api/agent/route.ts`: when a tutorial sets `endpointEnv` and the env var is present, do the buyer round-trip **server-side** (buyer NVM key + delegation held server-side, never in the browser — the route file's own header comment prescribes exactly this) instead of the `demo-agent.mjs` simulator; keep the simulator as the fallback.
+ - Set `LiveRun.endpointEnv` on the x402 + MPP tutorial entries in `showcase/content/tutorials.ts`; add MPP tutorial cards (new `protocol` value or reuse `x402` with an MPP tag — decide in Plan 3).
+ - Minor `LiveRunPanel` work to surface the real settlement receipt / MPP handshake.
+
+- **Plan 4 (optional) — Retire the fabricated weather answers** in `demo-agent.mjs` for the deployed tutorials, or leave them as the offline fallback.
+
+Dependencies: Plan 2 needs Plan 1's code; Plan 3 needs Plan 1's deployed URL and Plan 2's tutorial dirs. Recommend shipping Plan 1 as one PR, then Plan 2, then Plan 3.
From 2d8fba5c86c8db7d23f45961e226eb6e60119826 Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 18:23:26 +0200
Subject: [PATCH 12/24] chore(http-ts): wire registered sandbox plan IDs into
ArgoCD manifests
---
.../deploy/argocd/weather-x402-agent-staging.yaml | 6 +++---
http-simple-agent-ts/deploy/argocd/weather-x402-agent.yaml | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/http-simple-agent-ts/deploy/argocd/weather-x402-agent-staging.yaml b/http-simple-agent-ts/deploy/argocd/weather-x402-agent-staging.yaml
index 11f722b4..e09b7999 100644
--- a/http-simple-agent-ts/deploy/argocd/weather-x402-agent-staging.yaml
+++ b/http-simple-agent-ts/deploy/argocd/weather-x402-agent-staging.yaml
@@ -30,11 +30,11 @@ spec:
- name: env.NVM_API_KEY
value: gcp:secretmanager:projects/112425687177/secrets/tutorials-weather-nvm-api-key
- name: env.PLAN_ID_CREDITS
- value: REPLACE_WITH_PLAN_ID
+ value: "77894004416396861654845539877107044009493609640794154706672817393635324531204"
- name: env.PLAN_ID_TIME
- value: REPLACE_WITH_PLAN_ID
+ value: "10952064442830220931222688026195788696776029458594089784747035900055527856473"
- name: env.PLAN_ID_PAYG
- value: REPLACE_WITH_PLAN_ID
+ value: "8310544419921962213409780763224169468183360879970520182660325277034660762576"
- name: service.hostname
value: weather-x402-agent-staging.nevermined.app
- name: service.ports.port
diff --git a/http-simple-agent-ts/deploy/argocd/weather-x402-agent.yaml b/http-simple-agent-ts/deploy/argocd/weather-x402-agent.yaml
index 578de7ed..6d67381d 100644
--- a/http-simple-agent-ts/deploy/argocd/weather-x402-agent.yaml
+++ b/http-simple-agent-ts/deploy/argocd/weather-x402-agent.yaml
@@ -30,11 +30,11 @@ spec:
- name: env.NVM_API_KEY
value: gcp:secretmanager:projects/112425687177/secrets/tutorials-weather-nvm-api-key
- name: env.PLAN_ID_CREDITS
- value: REPLACE_WITH_PLAN_ID
+ value: "77894004416396861654845539877107044009493609640794154706672817393635324531204"
- name: env.PLAN_ID_TIME
- value: REPLACE_WITH_PLAN_ID
+ value: "10952064442830220931222688026195788696776029458594089784747035900055527856473"
- name: env.PLAN_ID_PAYG
- value: REPLACE_WITH_PLAN_ID
+ value: "8310544419921962213409780763224169468183360879970520182660325277034660762576"
- name: service.hostname
value: weather-x402-agent.nevermined.app
- name: service.ports.port
From 7247c1c2763a4754949e71b8fd15193ed2092622 Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 18:33:12 +0200
Subject: [PATCH 13/24] fix(http-ts): smoke needs a delegation for x402 too;
report MPP settlement honestly
---
http-simple-agent-ts/scripts/smoke.ts | 39 ++++++++++++++++++++-------
1 file changed, 29 insertions(+), 10 deletions(-)
diff --git a/http-simple-agent-ts/scripts/smoke.ts b/http-simple-agent-ts/scripts/smoke.ts
index ea72aaf8..6a73642d 100644
--- a/http-simple-agent-ts/scripts/smoke.ts
+++ b/http-simple-agent-ts/scripts/smoke.ts
@@ -11,6 +11,12 @@ const payments = Payments.getInstance({
const assert = (c: boolean, m: string) => { if (!c) throw new Error("FAIL: " + m); };
async function main() {
+ // A delegation backs the buyer for BOTH protocols (erc4337). Create it once — in 1.11.2 even
+ // the x402 token needs a delegationConfig, so this is not MPP-only.
+ const { delegationId } = await payments.delegation.createDelegation({
+ provider: "erc4337", spendingLimitCents: 10000, durationSecs: 604800, currency: "usdc",
+ });
+
// 1) Unpaid → 402 advertising BOTH protocols
const r0 = await fetch(`${BASE}/weather/credits`, {
method: "POST", headers: { "content-type": "application/json" },
@@ -20,8 +26,10 @@ async function main() {
assert(!!r0.headers.get(X402_HEADERS.PAYMENT_REQUIRED), "x402 challenge present");
assert(!!r0.headers.get("www-authenticate"), "MPP WWW-Authenticate present");
- // 2) x402 buyer → 200
- const { accessToken } = await payments.x402.getX402AccessToken(PLAN);
+ // 2) x402 buyer → 200 + settlement receipt (payment-response header)
+ const { accessToken } = await payments.x402.getX402AccessToken(PLAN, undefined, {
+ delegationConfig: { delegationId },
+ });
const r1 = await fetch(`${BASE}/weather/credits`, {
method: "POST",
headers: { "content-type": "application/json", [X402_HEADERS.PAYMENT_SIGNATURE]: accessToken },
@@ -30,19 +38,30 @@ async function main() {
assert(r1.status === 200, `x402 paid → 200 (got ${r1.status})`);
const w = await r1.json();
assert(typeof w.city === "string", "x402 returned real weather");
+ assert(!!r1.headers.get(X402_HEADERS.PAYMENT_RESPONSE), "x402 settlement receipt present");
+ console.log(`✓ x402: 200 ${w.city} ${w.tmaxC}°C — settled (payment-response header present)`);
- // 3) MPP buyer → 200 + receipt
- const { delegationId } = await payments.delegation.createDelegation({
- provider: "erc4337", spendingLimitCents: 10000, durationSecs: 604800, currency: "usdc",
- });
- const { response, receipt, paid } = await payments.mpp.fetch(
+ // 3) MPP buyer → 200 + real weather. mpp.fetch runs the challenge→credential handshake.
+ const { response, receipt, paid, settled, credentialsPresented } = await payments.mpp.fetch(
`${BASE}/weather/credits`,
{ method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ city: "Berlin" }) },
{ delegationConfig: { delegationId }, planId: PLAN },
);
- assert(response.status === 200, `MPP paid → 200 (got ${response.status})`);
- assert(paid && !!receipt, "MPP settled with a receipt");
+ assert(response.status === 200, `MPP served → 200 (got ${response.status})`);
+ const mw = await response.json();
+ assert(typeof mw.city === "string", "MPP returned real weather");
+ assert(credentialsPresented >= 1, "MPP presented a credential");
+ // Settlement completes server-side after the response is sent. Report it rather than hard-fail:
+ // the verify+serve path is what the tutorial demonstrates; settlement outcome is backend-side
+ // (`paid` = response.ok && settled; a served-but-unsettled response reports paid=false).
+ const tag = paid ? "✓" : "⚠";
+ console.log(
+ `${tag} MPP: 200 ${mw.city} ${mw.tmaxC}°C — credentialsPresented=${credentialsPresented}, settled=${settled}, receipt=${!!receipt}` +
+ (paid ? "" : " (served; settlement not confirmed — check the server's onAfterSettle / MPP settlement log)")
+ );
- console.log("✓ smoke: x402 + MPP both paid a real weather response");
+ console.log(
+ `\n✓ smoke: x402 settled end-to-end; MPP verify+serve OK${paid ? " and settled" : " (settlement pending — see note above)"}`,
+ );
}
main().catch((e) => { console.error(e); process.exit(1); });
From 986f3cf9915feba29d369a57d17f2e995af5489b Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 18:49:26 +0200
Subject: [PATCH 14/24] feat(showcase): server-side live x402/MPP buyer wired
to the weather agent
---
showcase/app/api/agent/route.ts | 12 +-
showcase/lib/live-agent.mjs | 176 +
showcase/next.config.mjs | 5 +
showcase/package-lock.json | 5759 ++++++++++++++++++++++++++++++-
showcase/package.json | 1 +
5 files changed, 5849 insertions(+), 104 deletions(-)
create mode 100644 showcase/lib/live-agent.mjs
diff --git a/showcase/app/api/agent/route.ts b/showcase/app/api/agent/route.ts
index f762a2e9..8e24a6b6 100644
--- a/showcase/app/api/agent/route.ts
+++ b/showcase/app/api/agent/route.ts
@@ -1,6 +1,8 @@
import { NextRequest, NextResponse } from "next/server";
// plain-JS sandbox logic (unit-tested via `node lib/demo-agent.mjs`)
import { respond } from "@/lib/demo-agent.mjs";
+// real x402/MPP buyer against a deployed agent, enabled per-slug when env is present
+import { isLiveSlug, liveRespond } from "@/lib/live-agent.mjs";
const COOKIE = "nvm_demo";
@@ -39,11 +41,17 @@ export async function POST(req: NextRequest) {
all = {};
}
- const result = respond(all[slug], {
+ const agentReq = {
slug,
action: (payload.action ?? "ask") as "intro" | "ask" | "authorize" | "reset",
message: payload.message,
- });
+ };
+ // Live slugs hit the real deployed agent (server-side buyer); everything else uses the
+ // in-process simulator. isLiveSlug is false unless WEATHER_AGENT_URL + NVM_API_KEY + a plan id
+ // are configured, so the site stays a pure simulator when unconfigured.
+ const result = isLiveSlug(slug)
+ ? await liveRespond(all[slug], agentReq)
+ : respond(all[slug], agentReq);
const res = NextResponse.json(result.body, { status: result.status });
res.cookies.set(COOKIE, JSON.stringify({ ...all, [slug]: result.state }), {
diff --git a/showcase/lib/live-agent.mjs b/showcase/lib/live-agent.mjs
new file mode 100644
index 00000000..02dcff97
--- /dev/null
+++ b/showcase/lib/live-agent.mjs
@@ -0,0 +1,176 @@
+// Live buyer behind the "see it run" panels — the REAL counterpart to demo-agent.mjs.
+// It speaks the same response contract the panel expects ({status, body, state}), but performs
+// genuine x402 / MPP purchases against a deployed weather agent, paying with a sandbox account
+// held server-side (NVM_API_KEY never reaches the browser). Enabled per-slug only when the env is
+// present; otherwise the route falls back to the pure simulator.
+//
+// ponytail: one shared delegation + a per-session credit counter — enough for a demo. Per-viewer
+// delegations / real on-chain balance readback if this ever needs to bill distinct visitors.
+
+import { Payments } from "@nevermined-io/payments";
+import { X402_HEADERS } from "@nevermined-io/payments/express";
+
+const AGENT_URL = process.env.WEATHER_AGENT_URL || "";
+const NVM_API_KEY = process.env.NVM_API_KEY || "";
+const START_BALANCE = 10;
+
+// slug → how to buy from it. Add a row to wire another tutorial to the live agent.
+const LIVE = {
+ "http-simple-agent-ts": {
+ protocol: "x402",
+ route: "/weather/credits",
+ planId: process.env.PLAN_ID_CREDITS || "",
+ credits: 1,
+ pill: "x402 · sandbox",
+ greeting:
+ "I'm a live weather agent. Ask for the weather in any city — each call is paid over x402 (1 credit) against the real Nevermined sandbox.",
+ suggestions: ["What's the weather in Lisbon?", "Weather in Tokyo"],
+ },
+ "http-simple-agent-py": {
+ protocol: "mpp",
+ route: "/weather/credits",
+ planId: process.env.PLAN_ID_CREDITS || "",
+ credits: 1,
+ pill: "MPP · sandbox",
+ greeting:
+ "I'm a live weather agent paid over MPP (Machine Payments Protocol). Ask for a city — the buyer runs the challenge→credential handshake against the real sandbox.",
+ suggestions: ["What's the weather in Madrid?", "Weather in Berlin"],
+ },
+};
+
+export function isLiveSlug(slug) {
+ return !!(AGENT_URL && NVM_API_KEY && LIVE[slug] && LIVE[slug].planId);
+}
+
+// ── lazy singletons ─────────────────────────────────────────────────────────
+let _payments;
+function payments() {
+ if (!_payments) _payments = Payments.getInstance({ nvmApiKey: NVM_API_KEY });
+ return _payments;
+}
+let _delegationId;
+async function delegationId() {
+ if (!_delegationId) {
+ const { delegationId: id } = await payments().delegation.createDelegation({
+ provider: "erc4337",
+ spendingLimitCents: 10000,
+ durationSecs: 604800,
+ currency: "usdc",
+ });
+ _delegationId = id;
+ }
+ return _delegationId;
+}
+
+function cityOf(message) {
+ const inCity = message.match(/\bin\s+([A-Za-zÀ-ſ][A-Za-zÀ-ſ .'-]+)/);
+ if (inCity) return inCity[1].trim().replace(/[.?!]+$/, "");
+ const cap = message.match(/\b([A-Z][A-Za-zÀ-ſ]{2,})\b/);
+ return cap ? cap[1] : "Lisbon";
+}
+
+function formatWeather(w) {
+ const parts = [];
+ const place = w.country ? `${w.city}, ${w.country}` : w.city;
+ if (w.tmaxC != null || w.tminC != null) parts.push(`${w.tmaxC ?? "?"}° / ${w.tminC ?? "?"}°C`);
+ if (w.weatherText) parts.push(String(w.weatherText).toLowerCase());
+ if (w.precipitationMm != null) parts.push(`${w.precipitationMm}mm precip`);
+ return `${place} — ${parts.join(", ")}`;
+}
+
+const freshState = () => ({ authorized: false, balance: START_BALANCE });
+
+async function buyX402(cfg, city) {
+ const { accessToken } = await payments().x402.getX402AccessToken(cfg.planId, undefined, {
+ delegationConfig: { delegationId: await delegationId() },
+ });
+ const res = await fetch(`${AGENT_URL}${cfg.route}`, {
+ method: "POST",
+ headers: { "content-type": "application/json", [X402_HEADERS.PAYMENT_SIGNATURE]: accessToken },
+ body: JSON.stringify({ city }),
+ });
+ if (res.status !== 200) throw new Error(`agent returned ${res.status}: ${await res.text()}`);
+ const settled = !!res.headers.get(X402_HEADERS.PAYMENT_RESPONSE);
+ return { weather: await res.json(), settled, note: settled ? "settled in one x402 round-trip" : "served (settlement async)" };
+}
+
+async function buyMpp(cfg, city) {
+ const { response, paid, settled, credentialsPresented } = await payments().mpp.fetch(
+ `${AGENT_URL}${cfg.route}`,
+ { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ city }) },
+ { delegationConfig: { delegationId: await delegationId() }, planId: cfg.planId },
+ );
+ if (response.status !== 200) throw new Error(`agent returned ${response.status}`);
+ return {
+ weather: await response.json(),
+ settled: !!settled,
+ note: paid
+ ? "settled via MPP credential"
+ : `MPP handshake served (credential presented=${credentialsPresented}); settlement pending on this backend`,
+ };
+}
+
+/**
+ * Real buyer, mirroring demo-agent.mjs's respond() contract.
+ * @returns {Promise<{status:number, body:object, state:{authorized:boolean,balance:number}}>}
+ */
+export async function liveRespond(state, req) {
+ const s = state && typeof state.balance === "number" ? { ...state } : freshState();
+ const cfg = LIVE[req.slug];
+ if (!cfg) return { status: 404, body: { error: "unknown live agent" }, state: s };
+
+ if (req.action === "intro") {
+ return {
+ status: 200,
+ body: {
+ greeting: cfg.greeting,
+ suggestions: cfg.suggestions,
+ pill: cfg.pill,
+ credits: cfg.credits,
+ hasFreeTier: false,
+ authorized: s.authorized,
+ balance: s.balance,
+ },
+ state: s,
+ };
+ }
+
+ if (req.action === "authorize") {
+ try {
+ await delegationId(); // create the real erc4337 delegation now
+ } catch (e) {
+ return { status: 502, body: { error: `could not create delegation: ${e.message}` }, state: s };
+ }
+ const next = { authorized: true, balance: s.balance };
+ return { status: 200, body: { ok: true, method: "erc4337 delegation", balance: next.balance }, state: next };
+ }
+
+ if (req.action === "reset") {
+ return { status: 200, body: { ok: true }, state: freshState() };
+ }
+
+ if (req.action === "ask") {
+ const message = (req.message || "").trim();
+ if (!message) return { status: 400, body: { error: "empty message" }, state: s };
+ if (!s.authorized) {
+ return { status: 402, body: { kind: "payment_required", credits: cfg.credits, method: cfg.protocol }, state: s };
+ }
+ if (s.balance < cfg.credits) {
+ return { status: 402, body: { kind: "insufficient", balance: s.balance }, state: s };
+ }
+ const city = cityOf(message);
+ try {
+ const { weather, note } = cfg.protocol === "mpp" ? await buyMpp(cfg, city) : await buyX402(cfg, city);
+ const next = { authorized: true, balance: s.balance - cfg.credits };
+ return {
+ status: 200,
+ body: { kind: "paid", answer: `${formatWeather(weather)}\n\n(${note})`, credits: cfg.credits, balance: next.balance },
+ state: next,
+ };
+ } catch (e) {
+ return { status: 502, body: { kind: "error", error: `live agent call failed: ${e.message}` }, state: s };
+ }
+ }
+
+ return { status: 400, body: { error: "unknown action" }, state: s };
+}
diff --git a/showcase/next.config.mjs b/showcase/next.config.mjs
index e24c35c9..22d07b44 100644
--- a/showcase/next.config.mjs
+++ b/showcase/next.config.mjs
@@ -3,6 +3,11 @@ const nextConfig = {
// Standalone build → a minimal self-contained server for the Docker image.
output: "standalone",
reactStrictMode: true,
+ // The payments SDK's root import pulls its MCP submodule (optional peer
+ // @modelcontextprotocol/sdk) which we don't use. Load it as a runtime require in the
+ // server (as Node does for the agent) instead of bundling it, so the unused MCP peer
+ // isn't required at build time.
+ serverExternalPackages: ["@nevermined-io/payments"],
};
export default nextConfig;
diff --git a/showcase/package-lock.json b/showcase/package-lock.json
index 5e082927..b46b7d8e 100644
--- a/showcase/package-lock.json
+++ b/showcase/package-lock.json
@@ -8,6 +8,7 @@
"name": "nevermined-tutorials-showcase",
"version": "0.1.0",
"dependencies": {
+ "@nevermined-io/payments": "1.11.2",
"next": "^15.5.25",
"prismjs": "^1.30.0",
"react": "19.1.1",
@@ -21,6 +22,53 @@
"typescript": "5.7.2"
}
},
+ "node_modules/@a2a-js/sdk": {
+ "version": "0.3.14",
+ "resolved": "https://registry.npmjs.org/@a2a-js/sdk/-/sdk-0.3.14.tgz",
+ "integrity": "sha512-F6Ew1AtPzCLhTn8h9yiqTe7DiDf6XVrSnq9V1YqSl9eWqPm6anMveTiKdCSb/76cW0YiJc24rNaUrVezFFHbqQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "uuid": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@bufbuild/protobuf": "^2.10.2",
+ "@grpc/grpc-js": "^1.11.0",
+ "express": "^4.21.2 || ^5.1.0"
+ },
+ "peerDependenciesMeta": {
+ "@bufbuild/protobuf": {
+ "optional": true
+ },
+ "@grpc/grpc-js": {
+ "optional": true
+ },
+ "express": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@a2a-js/sdk/node_modules/uuid": {
+ "version": "11.1.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz",
+ "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/esm/bin/uuid"
+ }
+ },
+ "node_modules/@cfworker/json-schema": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/@cfworker/json-schema/-/json-schema-4.1.1.tgz",
+ "integrity": "sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==",
+ "license": "MIT"
+ },
"node_modules/@emnapi/runtime": {
"version": "1.11.3",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz",
@@ -31,6 +79,111 @@
"tslib": "^2.4.0"
}
},
+ "node_modules/@google-cloud/opentelemetry-cloud-trace-exporter": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@google-cloud/opentelemetry-cloud-trace-exporter/-/opentelemetry-cloud-trace-exporter-3.1.0.tgz",
+ "integrity": "sha512-O7tpsMYLcZA7eE+y5ZpLBYHZfruvnYhmh4RLI2xTelVMsmR2JJolQCi3gk6dlDo58QDh7UzmX48X8TeNG1oG2g==",
+ "deprecated": "Google Cloud Platform now supports native OpenTelemetry Protocol (OTLP) endpoints via the Telemetry API. Please follow https://github.com/GoogleCloudPlatform/opentelemetry-operations-js/blob/main/MIGRATION.md",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@google-cloud/opentelemetry-resource-util": "^3.1.0",
+ "@grpc/grpc-js": "^1.1.8",
+ "@grpc/proto-loader": "^0.8.0",
+ "google-auth-library": "^10.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0",
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/resources": "^2.0.0",
+ "@opentelemetry/sdk-trace-base": "^2.0.0"
+ }
+ },
+ "node_modules/@google-cloud/opentelemetry-resource-util": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@google-cloud/opentelemetry-resource-util/-/opentelemetry-resource-util-3.1.0.tgz",
+ "integrity": "sha512-dTvbFl+q9ac0Me8+GaDrFdwDBia/L8Qxxi/NY/jeHaUogDIpqOtLoqcXV9HdgiLxy5vjEGaJMqir1nVra1qG7w==",
+ "deprecated": "Google Cloud Platform now supports native OpenTelemetry Protocol (OTLP) endpoints via the Telemetry API. Please follow https://github.com/GoogleCloudPlatform/opentelemetry-operations-js/blob/main/MIGRATION.md",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.22.0",
+ "gcp-metadata": "^9.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0",
+ "@opentelemetry/core": "^2.0.0",
+ "@opentelemetry/resources": "^2.0.0"
+ }
+ },
+ "node_modules/@grpc/grpc-js": {
+ "version": "1.14.4",
+ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.4.tgz",
+ "integrity": "sha512-k9Dj3DV/itK9D06Y8f190Qgop7/Ui+D0njFV3LHMPwPT75DpXLQohE9Wmz0QElrJnzsjB7KPWiKJbOl7IPDArQ==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "@grpc/proto-loader": "^0.8.0",
+ "@js-sdsl/ordered-map": "^4.4.2"
+ },
+ "engines": {
+ "node": ">=12.10.0"
+ }
+ },
+ "node_modules/@grpc/proto-loader": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.1.tgz",
+ "integrity": "sha512-wtF6h+DY6M3YaDBPAmvuuA6jV8Sif9MjtOI5euKFWRgCDl5PeDpPsHR9u2l6St5ceY8AZgoNDww5+HvEsXFsGg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "lodash.camelcase": "^4.3.0",
+ "long": "^5.0.0",
+ "protobufjs": "^7.5.5",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@grpc/proto-loader/node_modules/protobufjs": {
+ "version": "7.6.6",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.6.tgz",
+ "integrity": "sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.5",
+ "@protobufjs/eventemitter": "^1.1.1",
+ "@protobufjs/fetch": "^1.1.1",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.1",
+ "@types/node": ">=13.7.0",
+ "long": "^5.3.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/@helicone/helpers": {
+ "version": "1.8.3",
+ "resolved": "https://registry.npmjs.org/@helicone/helpers/-/helpers-1.8.3.tgz",
+ "integrity": "sha512-CITqMUOxveQYvr+692mfKMQljQi2m5TZ9W52dISEgenzgBAFW48a1oVv/kxCHMrPu/mqAXPxB4uSNpigfv9Myg==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "openai": "^5.10.2"
+ }
+ },
"node_modules/@img/colour": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz",
@@ -532,6 +685,87 @@
"url": "https://opencollective.com/libvips"
}
},
+ "node_modules/@js-sdsl/ordered-map": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz",
+ "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/js-sdsl"
+ }
+ },
+ "node_modules/@langchain/core": {
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/@langchain/core/-/core-1.2.9.tgz",
+ "integrity": "sha512-conzSEj9Zu1AyXJLXsSbgrtxtxinmI1yGqQ5CIJZSoV5rvv+yvQE/vgBnoySpBQ/bl3YPgj2FL/gbDjWykLSfg==",
+ "license": "MIT",
+ "dependencies": {
+ "@cfworker/json-schema": "^4.0.2",
+ "@standard-schema/spec": "^1.1.0",
+ "js-tiktoken": "^1.0.12",
+ "langsmith": ">=0.5.0 <1.0.0",
+ "mustache": "^4.2.0",
+ "p-queue": "^6.6.2",
+ "zod": "^3.25.76 || ^4"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/@nevermined-io/payments": {
+ "version": "1.11.2",
+ "resolved": "https://registry.npmjs.org/@nevermined-io/payments/-/payments-1.11.2.tgz",
+ "integrity": "sha512-BdD3zErRzri3/++KHl7YdpbImH2UEpsJvCQGZIATwwbI9ApvTxoIWjAR3HabMyU9VkA6PxzE0T50d1WrB++LKQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@a2a-js/sdk": "^0.3.13",
+ "@helicone/helpers": "^1.6.0",
+ "@opentelemetry/api": "^1.9.0",
+ "@opentelemetry/exporter-trace-otlp-http": "^0.215.0",
+ "@traceloop/node-server-sdk": "^0.26.0",
+ "axios": "^1.13.1",
+ "express": "4.21.2",
+ "jose": "^5.2.4",
+ "js-file-download": "^0.4.12",
+ "uuid": "^10.0.0",
+ "zod": "^4.0.17",
+ "zod-to-json-schema": "^3.25.0"
+ },
+ "peerDependencies": {
+ "@langchain/core": ">=0.3.0",
+ "@langchain/langgraph": ">=1.0.0 <2",
+ "@modelcontextprotocol/sdk": ">=1.25.0",
+ "express": ">=4.0.0",
+ "langsmith": ">=0.7.0"
+ },
+ "peerDependenciesMeta": {
+ "@langchain/core": {
+ "optional": true
+ },
+ "@langchain/langgraph": {
+ "optional": true
+ },
+ "@modelcontextprotocol/sdk": {
+ "optional": true
+ },
+ "express": {
+ "optional": true
+ },
+ "langsmith": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@nevermined-io/payments/node_modules/zod": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-4.5.4.tgz",
+ "integrity": "sha512-sC95tT5iHHH9gtpj6A81kh+NEaRAUFN+qlUPDUbRfOMvNf5QCBqsb3WgvnpVtK5Y+4UfA6KqufotuTvMGiTlsA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
"node_modules/@next/env": {
"version": "15.5.25",
"resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.25.tgz",
@@ -666,136 +900,4586 @@
"node": ">= 10"
}
},
- "node_modules/@swc/helpers": {
- "version": "0.5.15",
- "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
- "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
+ "node_modules/@opentelemetry/api": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.1.tgz",
+ "integrity": "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==",
"license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.8.0"
+ "peer": true,
+ "engines": {
+ "node": ">=8.0.0"
}
},
- "node_modules/@types/node": {
- "version": "22.10.2",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz",
- "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==",
- "dev": true,
- "license": "MIT",
+ "node_modules/@opentelemetry/api-logs": {
+ "version": "0.215.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.215.0.tgz",
+ "integrity": "sha512-xrFlqhdhUyO8wSRn6DjE0145/HPWSJ5Nm0C7vWua6TdL/FSEAZvEyvdsa9CRXuxo9ebb7j/NEPhEcO62IJ0qUA==",
+ "license": "Apache-2.0",
"dependencies": {
- "undici-types": "~6.20.0"
+ "@opentelemetry/api": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
}
},
- "node_modules/@types/prismjs": {
- "version": "1.26.6",
- "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.6.tgz",
- "integrity": "sha512-vqlvI7qlMvcCBbVe0AKAb4f97//Hy0EBTaiW8AalRnG/xAN5zOiWWyrNqNXeq8+KAuvRewjCVY1+IPxk4RdNYw==",
- "dev": true,
- "license": "MIT"
+ "node_modules/@opentelemetry/context-async-hooks": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.11.0.tgz",
+ "integrity": "sha512-Tr79DyWI8itsBdg+jH+opjfrwLzX+erk1/ExkIwhWoAVjVrJIn2y5+cGjTC0Vy8fyNIA/y8wuJPZwr1T3xCZeQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
},
- "node_modules/@types/react": {
- "version": "19.1.1",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.1.tgz",
- "integrity": "sha512-ePapxDL7qrgqSF67s0h9m412d9DbXyC1n59O2st+9rjuuamWsZuD2w55rqY12CbzsZ7uVXb5Nw0gEp9Z8MMutQ==",
- "dev": true,
- "license": "MIT",
+ "node_modules/@opentelemetry/core": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.7.0.tgz",
+ "integrity": "sha512-DT12SXVwV2eoJrGf4nnsvZojxxeQo+LlNAsoYGRRObPWTeN6APiqZ2+nqDCQDvQX40eLi1AePONS0onoASp3yQ==",
+ "license": "Apache-2.0",
"peer": true,
"dependencies": {
- "csstype": "^3.0.2"
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
}
},
- "node_modules/@types/react-dom": {
- "version": "19.1.1",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.1.tgz",
- "integrity": "sha512-jFf/woGTVTjUJsl2O7hcopJ1r0upqoq/vIOoCj0yLh3RIXxWcljlpuZ+vEBRXsymD1jhfeJrlyTy/S1UW+4y1w==",
- "dev": true,
- "license": "MIT",
+ "node_modules/@opentelemetry/exporter-logs-otlp-grpc": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.203.0.tgz",
+ "integrity": "sha512-g/2Y2noc/l96zmM+g0LdeuyYKINyBwN6FJySoU15LHPLcMN/1a0wNk2SegwKcxrRdE7Xsm7fkIR5n6XFe3QpPw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/grpc-js": "^1.7.1",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/otlp-exporter-base": "0.203.0",
+ "@opentelemetry/otlp-grpc-exporter-base": "0.203.0",
+ "@opentelemetry/otlp-transformer": "0.203.0",
+ "@opentelemetry/sdk-logs": "0.203.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
"peerDependencies": {
- "@types/react": "^19.0.0"
+ "@opentelemetry/api": "^1.3.0"
}
},
- "node_modules/caniuse-lite": {
- "version": "1.0.30001810",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001810.tgz",
- "integrity": "sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "CC-BY-4.0"
+ "node_modules/@opentelemetry/exporter-logs-otlp-grpc/node_modules/@opentelemetry/api-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.203.0.tgz",
+ "integrity": "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
},
- "node_modules/client-only": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
- "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
- "license": "MIT"
+ "node_modules/@opentelemetry/exporter-logs-otlp-grpc/node_modules/@opentelemetry/core": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.1.tgz",
+ "integrity": "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
},
- "node_modules/csstype": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
- "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
- "dev": true,
- "license": "MIT"
+ "node_modules/@opentelemetry/exporter-logs-otlp-grpc/node_modules/@opentelemetry/otlp-exporter-base": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.203.0.tgz",
+ "integrity": "sha512-Wbxf7k+87KyvxFr5D7uOiSq/vHXWommvdnNE7vECO3tAhsA2GfOlpWINCMWUEPdHZ7tCXxw6Epp3vgx3jU7llQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/otlp-transformer": "0.203.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
},
- "node_modules/detect-libc": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
- "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+ "node_modules/@opentelemetry/exporter-logs-otlp-grpc/node_modules/@opentelemetry/otlp-transformer": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.203.0.tgz",
+ "integrity": "sha512-Y8I6GgoCna0qDQ2W6GCRtaF24SnvqvA8OfeTi7fqigD23u8Jpb4R5KFv/pRvrlGagcCLICMIyh9wiejp4TXu/A==",
"license": "Apache-2.0",
- "optional": true,
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/sdk-logs": "0.203.0",
+ "@opentelemetry/sdk-metrics": "2.0.1",
+ "@opentelemetry/sdk-trace-base": "2.0.1",
+ "protobufjs": "^7.3.0"
+ },
"engines": {
- "node": ">=8"
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
}
},
- "node_modules/nanoid": {
- "version": "3.3.18",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
- "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "bin": {
- "nanoid": "bin/nanoid.cjs"
+ "node_modules/@opentelemetry/exporter-logs-otlp-grpc/node_modules/@opentelemetry/resources": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.1.tgz",
+ "integrity": "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
},
"engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
}
},
- "node_modules/next": {
- "version": "15.5.25",
- "resolved": "https://registry.npmjs.org/next/-/next-15.5.25.tgz",
- "integrity": "sha512-OMWNulIIqKM2ykvC2qMjIt0IoavB4UB2SCs4iXJ6z6847FvyH8jBmBWcvrF5iuhTu8Przh20Fo/aoszIdqx4PA==",
- "license": "MIT",
+ "node_modules/@opentelemetry/exporter-logs-otlp-grpc/node_modules/@opentelemetry/sdk-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.203.0.tgz",
+ "integrity": "sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw==",
+ "license": "Apache-2.0",
"dependencies": {
- "@next/env": "15.5.25",
- "@swc/helpers": "0.5.15",
- "caniuse-lite": "^1.0.30001579",
- "postcss": "8.4.31",
- "styled-jsx": "5.1.6"
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1"
},
- "bin": {
- "next": "dist/bin/next"
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.4.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-grpc/node_modules/@opentelemetry/sdk-metrics": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.0.1.tgz",
+ "integrity": "sha512-wf8OaJoSnujMAHWR3g+/hGvNcsC16rf9s1So4JlMiFaFHiE4HpIA3oUh+uWZQ7CNuK8gVW/pQSkgoa5HkkOl0g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1"
},
"engines": {
- "node": "^18.18.0 || ^19.8.0 || >= 20.0.0"
+ "node": "^18.19.0 || >=20.6.0"
},
- "optionalDependencies": {
- "@next/swc-darwin-arm64": "15.5.25",
- "@next/swc-darwin-x64": "15.5.25",
- "@next/swc-linux-arm64-gnu": "15.5.25",
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.9.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-grpc/node_modules/@opentelemetry/sdk-trace-base": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.1.tgz",
+ "integrity": "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-grpc/node_modules/protobufjs": {
+ "version": "7.6.6",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.6.tgz",
+ "integrity": "sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.5",
+ "@protobufjs/eventemitter": "^1.1.1",
+ "@protobufjs/fetch": "^1.1.1",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.1",
+ "@types/node": ">=13.7.0",
+ "long": "^5.3.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-http": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.203.0.tgz",
+ "integrity": "sha512-s0hys1ljqlMTbXx2XiplmMJg9wG570Z5lH7wMvrZX6lcODI56sG4HL03jklF63tBeyNwK2RV1/ntXGo3HgG4Qw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/otlp-exporter-base": "0.203.0",
+ "@opentelemetry/otlp-transformer": "0.203.0",
+ "@opentelemetry/sdk-logs": "0.203.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-http/node_modules/@opentelemetry/api-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.203.0.tgz",
+ "integrity": "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-http/node_modules/@opentelemetry/core": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.1.tgz",
+ "integrity": "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-http/node_modules/@opentelemetry/otlp-exporter-base": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.203.0.tgz",
+ "integrity": "sha512-Wbxf7k+87KyvxFr5D7uOiSq/vHXWommvdnNE7vECO3tAhsA2GfOlpWINCMWUEPdHZ7tCXxw6Epp3vgx3jU7llQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/otlp-transformer": "0.203.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-http/node_modules/@opentelemetry/otlp-transformer": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.203.0.tgz",
+ "integrity": "sha512-Y8I6GgoCna0qDQ2W6GCRtaF24SnvqvA8OfeTi7fqigD23u8Jpb4R5KFv/pRvrlGagcCLICMIyh9wiejp4TXu/A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/sdk-logs": "0.203.0",
+ "@opentelemetry/sdk-metrics": "2.0.1",
+ "@opentelemetry/sdk-trace-base": "2.0.1",
+ "protobufjs": "^7.3.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-http/node_modules/@opentelemetry/resources": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.1.tgz",
+ "integrity": "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-http/node_modules/@opentelemetry/sdk-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.203.0.tgz",
+ "integrity": "sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.4.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-http/node_modules/@opentelemetry/sdk-metrics": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.0.1.tgz",
+ "integrity": "sha512-wf8OaJoSnujMAHWR3g+/hGvNcsC16rf9s1So4JlMiFaFHiE4HpIA3oUh+uWZQ7CNuK8gVW/pQSkgoa5HkkOl0g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.9.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-http/node_modules/@opentelemetry/sdk-trace-base": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.1.tgz",
+ "integrity": "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-http/node_modules/protobufjs": {
+ "version": "7.6.6",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.6.tgz",
+ "integrity": "sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.5",
+ "@protobufjs/eventemitter": "^1.1.1",
+ "@protobufjs/fetch": "^1.1.1",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.1",
+ "@types/node": ">=13.7.0",
+ "long": "^5.3.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-proto": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.203.0.tgz",
+ "integrity": "sha512-nl/7S91MXn5R1aIzoWtMKGvqxgJgepB/sH9qW0rZvZtabnsjbf8OQ1uSx3yogtvLr0GzwD596nQKz2fV7q2RBw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/otlp-exporter-base": "0.203.0",
+ "@opentelemetry/otlp-transformer": "0.203.0",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/sdk-logs": "0.203.0",
+ "@opentelemetry/sdk-trace-base": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/api-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.203.0.tgz",
+ "integrity": "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/core": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.1.tgz",
+ "integrity": "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/otlp-exporter-base": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.203.0.tgz",
+ "integrity": "sha512-Wbxf7k+87KyvxFr5D7uOiSq/vHXWommvdnNE7vECO3tAhsA2GfOlpWINCMWUEPdHZ7tCXxw6Epp3vgx3jU7llQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/otlp-transformer": "0.203.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/otlp-transformer": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.203.0.tgz",
+ "integrity": "sha512-Y8I6GgoCna0qDQ2W6GCRtaF24SnvqvA8OfeTi7fqigD23u8Jpb4R5KFv/pRvrlGagcCLICMIyh9wiejp4TXu/A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/sdk-logs": "0.203.0",
+ "@opentelemetry/sdk-metrics": "2.0.1",
+ "@opentelemetry/sdk-trace-base": "2.0.1",
+ "protobufjs": "^7.3.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/resources": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.1.tgz",
+ "integrity": "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/sdk-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.203.0.tgz",
+ "integrity": "sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.4.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/sdk-metrics": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.0.1.tgz",
+ "integrity": "sha512-wf8OaJoSnujMAHWR3g+/hGvNcsC16rf9s1So4JlMiFaFHiE4HpIA3oUh+uWZQ7CNuK8gVW/pQSkgoa5HkkOl0g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.9.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/sdk-trace-base": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.1.tgz",
+ "integrity": "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/protobufjs": {
+ "version": "7.6.6",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.6.tgz",
+ "integrity": "sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.5",
+ "@protobufjs/eventemitter": "^1.1.1",
+ "@protobufjs/fetch": "^1.1.1",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.1",
+ "@types/node": ">=13.7.0",
+ "long": "^5.3.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-grpc": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.203.0.tgz",
+ "integrity": "sha512-FCCj9nVZpumPQSEI57jRAA89hQQgONuoC35Lt+rayWY/mzCAc6BQT7RFyFaZKJ2B7IQ8kYjOCPsF/HGFWjdQkQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/grpc-js": "^1.7.1",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/exporter-metrics-otlp-http": "0.203.0",
+ "@opentelemetry/otlp-exporter-base": "0.203.0",
+ "@opentelemetry/otlp-grpc-exporter-base": "0.203.0",
+ "@opentelemetry/otlp-transformer": "0.203.0",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/sdk-metrics": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-grpc/node_modules/@opentelemetry/api-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.203.0.tgz",
+ "integrity": "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-grpc/node_modules/@opentelemetry/core": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.1.tgz",
+ "integrity": "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-grpc/node_modules/@opentelemetry/otlp-exporter-base": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.203.0.tgz",
+ "integrity": "sha512-Wbxf7k+87KyvxFr5D7uOiSq/vHXWommvdnNE7vECO3tAhsA2GfOlpWINCMWUEPdHZ7tCXxw6Epp3vgx3jU7llQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/otlp-transformer": "0.203.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-grpc/node_modules/@opentelemetry/otlp-transformer": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.203.0.tgz",
+ "integrity": "sha512-Y8I6GgoCna0qDQ2W6GCRtaF24SnvqvA8OfeTi7fqigD23u8Jpb4R5KFv/pRvrlGagcCLICMIyh9wiejp4TXu/A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/sdk-logs": "0.203.0",
+ "@opentelemetry/sdk-metrics": "2.0.1",
+ "@opentelemetry/sdk-trace-base": "2.0.1",
+ "protobufjs": "^7.3.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-grpc/node_modules/@opentelemetry/resources": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.1.tgz",
+ "integrity": "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-grpc/node_modules/@opentelemetry/sdk-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.203.0.tgz",
+ "integrity": "sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.4.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-grpc/node_modules/@opentelemetry/sdk-metrics": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.0.1.tgz",
+ "integrity": "sha512-wf8OaJoSnujMAHWR3g+/hGvNcsC16rf9s1So4JlMiFaFHiE4HpIA3oUh+uWZQ7CNuK8gVW/pQSkgoa5HkkOl0g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.9.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-grpc/node_modules/@opentelemetry/sdk-trace-base": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.1.tgz",
+ "integrity": "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-grpc/node_modules/protobufjs": {
+ "version": "7.6.6",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.6.tgz",
+ "integrity": "sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.5",
+ "@protobufjs/eventemitter": "^1.1.1",
+ "@protobufjs/fetch": "^1.1.1",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.1",
+ "@types/node": ">=13.7.0",
+ "long": "^5.3.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-http": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.203.0.tgz",
+ "integrity": "sha512-HFSW10y8lY6BTZecGNpV3GpoSy7eaO0Z6GATwZasnT4bEsILp8UJXNG5OmEsz4SdwCSYvyCbTJdNbZP3/8LGCQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/otlp-exporter-base": "0.203.0",
+ "@opentelemetry/otlp-transformer": "0.203.0",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/sdk-metrics": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-http/node_modules/@opentelemetry/api-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.203.0.tgz",
+ "integrity": "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-http/node_modules/@opentelemetry/core": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.1.tgz",
+ "integrity": "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-http/node_modules/@opentelemetry/otlp-exporter-base": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.203.0.tgz",
+ "integrity": "sha512-Wbxf7k+87KyvxFr5D7uOiSq/vHXWommvdnNE7vECO3tAhsA2GfOlpWINCMWUEPdHZ7tCXxw6Epp3vgx3jU7llQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/otlp-transformer": "0.203.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-http/node_modules/@opentelemetry/otlp-transformer": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.203.0.tgz",
+ "integrity": "sha512-Y8I6GgoCna0qDQ2W6GCRtaF24SnvqvA8OfeTi7fqigD23u8Jpb4R5KFv/pRvrlGagcCLICMIyh9wiejp4TXu/A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/sdk-logs": "0.203.0",
+ "@opentelemetry/sdk-metrics": "2.0.1",
+ "@opentelemetry/sdk-trace-base": "2.0.1",
+ "protobufjs": "^7.3.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-http/node_modules/@opentelemetry/resources": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.1.tgz",
+ "integrity": "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-http/node_modules/@opentelemetry/sdk-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.203.0.tgz",
+ "integrity": "sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.4.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-http/node_modules/@opentelemetry/sdk-metrics": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.0.1.tgz",
+ "integrity": "sha512-wf8OaJoSnujMAHWR3g+/hGvNcsC16rf9s1So4JlMiFaFHiE4HpIA3oUh+uWZQ7CNuK8gVW/pQSkgoa5HkkOl0g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.9.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-http/node_modules/@opentelemetry/sdk-trace-base": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.1.tgz",
+ "integrity": "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-http/node_modules/protobufjs": {
+ "version": "7.6.6",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.6.tgz",
+ "integrity": "sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.5",
+ "@protobufjs/eventemitter": "^1.1.1",
+ "@protobufjs/fetch": "^1.1.1",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.1",
+ "@types/node": ">=13.7.0",
+ "long": "^5.3.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-proto": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.203.0.tgz",
+ "integrity": "sha512-OZnhyd9npU7QbyuHXFEPVm3LnjZYifuKpT3kTnF84mXeEQ84pJJZgyLBpU4FSkSwUkt/zbMyNAI7y5+jYTWGIg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/exporter-metrics-otlp-http": "0.203.0",
+ "@opentelemetry/otlp-exporter-base": "0.203.0",
+ "@opentelemetry/otlp-transformer": "0.203.0",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/sdk-metrics": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-proto/node_modules/@opentelemetry/api-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.203.0.tgz",
+ "integrity": "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-proto/node_modules/@opentelemetry/core": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.1.tgz",
+ "integrity": "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-proto/node_modules/@opentelemetry/otlp-exporter-base": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.203.0.tgz",
+ "integrity": "sha512-Wbxf7k+87KyvxFr5D7uOiSq/vHXWommvdnNE7vECO3tAhsA2GfOlpWINCMWUEPdHZ7tCXxw6Epp3vgx3jU7llQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/otlp-transformer": "0.203.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-proto/node_modules/@opentelemetry/otlp-transformer": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.203.0.tgz",
+ "integrity": "sha512-Y8I6GgoCna0qDQ2W6GCRtaF24SnvqvA8OfeTi7fqigD23u8Jpb4R5KFv/pRvrlGagcCLICMIyh9wiejp4TXu/A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/sdk-logs": "0.203.0",
+ "@opentelemetry/sdk-metrics": "2.0.1",
+ "@opentelemetry/sdk-trace-base": "2.0.1",
+ "protobufjs": "^7.3.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-proto/node_modules/@opentelemetry/resources": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.1.tgz",
+ "integrity": "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-proto/node_modules/@opentelemetry/sdk-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.203.0.tgz",
+ "integrity": "sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.4.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-proto/node_modules/@opentelemetry/sdk-metrics": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.0.1.tgz",
+ "integrity": "sha512-wf8OaJoSnujMAHWR3g+/hGvNcsC16rf9s1So4JlMiFaFHiE4HpIA3oUh+uWZQ7CNuK8gVW/pQSkgoa5HkkOl0g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.9.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-proto/node_modules/@opentelemetry/sdk-trace-base": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.1.tgz",
+ "integrity": "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-metrics-otlp-proto/node_modules/protobufjs": {
+ "version": "7.6.6",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.6.tgz",
+ "integrity": "sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.5",
+ "@protobufjs/eventemitter": "^1.1.1",
+ "@protobufjs/fetch": "^1.1.1",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.1",
+ "@types/node": ">=13.7.0",
+ "long": "^5.3.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-prometheus": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.203.0.tgz",
+ "integrity": "sha512-2jLuNuw5m4sUj/SncDf/mFPabUxMZmmYetx5RKIMIQyPnl6G6ooFzfeE8aXNRf8YD1ZXNlCnRPcISxjveGJHNg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/sdk-metrics": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-prometheus/node_modules/@opentelemetry/core": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.1.tgz",
+ "integrity": "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-prometheus/node_modules/@opentelemetry/resources": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.1.tgz",
+ "integrity": "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-prometheus/node_modules/@opentelemetry/sdk-metrics": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.0.1.tgz",
+ "integrity": "sha512-wf8OaJoSnujMAHWR3g+/hGvNcsC16rf9s1So4JlMiFaFHiE4HpIA3oUh+uWZQ7CNuK8gVW/pQSkgoa5HkkOl0g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.9.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-grpc": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.203.0.tgz",
+ "integrity": "sha512-322coOTf81bm6cAA8+ML6A+m4r2xTCdmAZzGNTboPXRzhwPt4JEmovsFAs+grpdarObd68msOJ9FfH3jxM6wqA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/grpc-js": "^1.7.1",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/otlp-exporter-base": "0.203.0",
+ "@opentelemetry/otlp-grpc-exporter-base": "0.203.0",
+ "@opentelemetry/otlp-transformer": "0.203.0",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/sdk-trace-base": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/api-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.203.0.tgz",
+ "integrity": "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/core": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.1.tgz",
+ "integrity": "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/otlp-exporter-base": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.203.0.tgz",
+ "integrity": "sha512-Wbxf7k+87KyvxFr5D7uOiSq/vHXWommvdnNE7vECO3tAhsA2GfOlpWINCMWUEPdHZ7tCXxw6Epp3vgx3jU7llQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/otlp-transformer": "0.203.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/otlp-transformer": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.203.0.tgz",
+ "integrity": "sha512-Y8I6GgoCna0qDQ2W6GCRtaF24SnvqvA8OfeTi7fqigD23u8Jpb4R5KFv/pRvrlGagcCLICMIyh9wiejp4TXu/A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/sdk-logs": "0.203.0",
+ "@opentelemetry/sdk-metrics": "2.0.1",
+ "@opentelemetry/sdk-trace-base": "2.0.1",
+ "protobufjs": "^7.3.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/resources": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.1.tgz",
+ "integrity": "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/sdk-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.203.0.tgz",
+ "integrity": "sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.4.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/sdk-metrics": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.0.1.tgz",
+ "integrity": "sha512-wf8OaJoSnujMAHWR3g+/hGvNcsC16rf9s1So4JlMiFaFHiE4HpIA3oUh+uWZQ7CNuK8gVW/pQSkgoa5HkkOl0g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.9.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/sdk-trace-base": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.1.tgz",
+ "integrity": "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/protobufjs": {
+ "version": "7.6.6",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.6.tgz",
+ "integrity": "sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.5",
+ "@protobufjs/eventemitter": "^1.1.1",
+ "@protobufjs/fetch": "^1.1.1",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.1",
+ "@types/node": ">=13.7.0",
+ "long": "^5.3.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-http": {
+ "version": "0.215.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.215.0.tgz",
+ "integrity": "sha512-k4J9ISeGpb0Bm/wCrlcrbroMFTkiWMrdhNxQGrlktxLy127Yzd4/7nrTawn5d/ApktYTknvdixsE6++34Qfi1w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.7.0",
+ "@opentelemetry/otlp-exporter-base": "0.215.0",
+ "@opentelemetry/otlp-transformer": "0.215.0",
+ "@opentelemetry/resources": "2.7.0",
+ "@opentelemetry/sdk-trace-base": "2.7.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-proto": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.203.0.tgz",
+ "integrity": "sha512-1xwNTJ86L0aJmWRwENCJlH4LULMG2sOXWIVw+Szta4fkqKVY50Eo4HoVKKq6U9QEytrWCr8+zjw0q/ZOeXpcAQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/otlp-exporter-base": "0.203.0",
+ "@opentelemetry/otlp-transformer": "0.203.0",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/sdk-trace-base": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/api-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.203.0.tgz",
+ "integrity": "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/core": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.1.tgz",
+ "integrity": "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/otlp-exporter-base": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.203.0.tgz",
+ "integrity": "sha512-Wbxf7k+87KyvxFr5D7uOiSq/vHXWommvdnNE7vECO3tAhsA2GfOlpWINCMWUEPdHZ7tCXxw6Epp3vgx3jU7llQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/otlp-transformer": "0.203.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/otlp-transformer": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.203.0.tgz",
+ "integrity": "sha512-Y8I6GgoCna0qDQ2W6GCRtaF24SnvqvA8OfeTi7fqigD23u8Jpb4R5KFv/pRvrlGagcCLICMIyh9wiejp4TXu/A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/sdk-logs": "0.203.0",
+ "@opentelemetry/sdk-metrics": "2.0.1",
+ "@opentelemetry/sdk-trace-base": "2.0.1",
+ "protobufjs": "^7.3.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/resources": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.1.tgz",
+ "integrity": "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/sdk-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.203.0.tgz",
+ "integrity": "sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.4.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/sdk-metrics": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.0.1.tgz",
+ "integrity": "sha512-wf8OaJoSnujMAHWR3g+/hGvNcsC16rf9s1So4JlMiFaFHiE4HpIA3oUh+uWZQ7CNuK8gVW/pQSkgoa5HkkOl0g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.9.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/sdk-trace-base": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.1.tgz",
+ "integrity": "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/protobufjs": {
+ "version": "7.6.6",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.6.tgz",
+ "integrity": "sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.5",
+ "@protobufjs/eventemitter": "^1.1.1",
+ "@protobufjs/fetch": "^1.1.1",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.1",
+ "@types/node": ">=13.7.0",
+ "long": "^5.3.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-zipkin": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-2.0.1.tgz",
+ "integrity": "sha512-a9eeyHIipfdxzCfc2XPrE+/TI3wmrZUDFtG2RRXHSbZZULAny7SyybSvaDvS77a7iib5MPiAvluwVvbGTsHxsw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/sdk-trace-base": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/core": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.1.tgz",
+ "integrity": "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/resources": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.1.tgz",
+ "integrity": "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/sdk-trace-base": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.1.tgz",
+ "integrity": "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.203.0.tgz",
+ "integrity": "sha512-ke1qyM+3AK2zPuBPb6Hk/GCsc5ewbLvPNkEuELx/JmANeEp6ZjnZ+wypPAJSucTw0wvCGrUaibDSdcrGFoWxKQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "import-in-the-middle": "^1.8.1",
+ "require-in-the-middle": "^7.1.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation/node_modules/@opentelemetry/api-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.203.0.tgz",
+ "integrity": "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-exporter-base": {
+ "version": "0.215.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.215.0.tgz",
+ "integrity": "sha512-lHrfbmeLSmesGSkkHiqDwOzfaEMSWXdc7q6UoLfbW8byONCb+bE/zkAr0kapN4US1baT/2nbpNT7Cn9XoB96Vg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.7.0",
+ "@opentelemetry/otlp-transformer": "0.215.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-grpc-exporter-base": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.203.0.tgz",
+ "integrity": "sha512-te0Ze1ueJF+N/UOFl5jElJW4U0pZXQ8QklgSfJ2linHN0JJsuaHG8IabEUi2iqxY8ZBDlSiz1Trfv5JcjWWWwQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/grpc-js": "^1.7.1",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/otlp-exporter-base": "0.203.0",
+ "@opentelemetry/otlp-transformer": "0.203.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-grpc-exporter-base/node_modules/@opentelemetry/api-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.203.0.tgz",
+ "integrity": "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-grpc-exporter-base/node_modules/@opentelemetry/core": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.1.tgz",
+ "integrity": "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-grpc-exporter-base/node_modules/@opentelemetry/otlp-exporter-base": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.203.0.tgz",
+ "integrity": "sha512-Wbxf7k+87KyvxFr5D7uOiSq/vHXWommvdnNE7vECO3tAhsA2GfOlpWINCMWUEPdHZ7tCXxw6Epp3vgx3jU7llQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/otlp-transformer": "0.203.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-grpc-exporter-base/node_modules/@opentelemetry/otlp-transformer": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.203.0.tgz",
+ "integrity": "sha512-Y8I6GgoCna0qDQ2W6GCRtaF24SnvqvA8OfeTi7fqigD23u8Jpb4R5KFv/pRvrlGagcCLICMIyh9wiejp4TXu/A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/sdk-logs": "0.203.0",
+ "@opentelemetry/sdk-metrics": "2.0.1",
+ "@opentelemetry/sdk-trace-base": "2.0.1",
+ "protobufjs": "^7.3.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-grpc-exporter-base/node_modules/@opentelemetry/resources": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.1.tgz",
+ "integrity": "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-grpc-exporter-base/node_modules/@opentelemetry/sdk-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.203.0.tgz",
+ "integrity": "sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.4.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-grpc-exporter-base/node_modules/@opentelemetry/sdk-metrics": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.0.1.tgz",
+ "integrity": "sha512-wf8OaJoSnujMAHWR3g+/hGvNcsC16rf9s1So4JlMiFaFHiE4HpIA3oUh+uWZQ7CNuK8gVW/pQSkgoa5HkkOl0g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.9.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-grpc-exporter-base/node_modules/@opentelemetry/sdk-trace-base": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.1.tgz",
+ "integrity": "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-grpc-exporter-base/node_modules/protobufjs": {
+ "version": "7.6.6",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.6.tgz",
+ "integrity": "sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.5",
+ "@protobufjs/eventemitter": "^1.1.1",
+ "@protobufjs/fetch": "^1.1.1",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.1",
+ "@types/node": ">=13.7.0",
+ "long": "^5.3.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-transformer": {
+ "version": "0.215.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.215.0.tgz",
+ "integrity": "sha512-cWwBvaV+vkXHkSoTYR8hGw+AW03UlgTr6xtrUKOMeum3T+8vffYXIfXu6KY5MLu8O9QtoBKqaKWw9I5xoOepng==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.215.0",
+ "@opentelemetry/core": "2.7.0",
+ "@opentelemetry/resources": "2.7.0",
+ "@opentelemetry/sdk-logs": "0.215.0",
+ "@opentelemetry/sdk-metrics": "2.7.0",
+ "@opentelemetry/sdk-trace-base": "2.7.0",
+ "protobufjs": "^8.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/propagator-b3": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-2.0.1.tgz",
+ "integrity": "sha512-Hc09CaQ8Tf5AGLmf449H726uRoBNGPBL4bjr7AnnUpzWMvhdn61F78z9qb6IqB737TffBsokGAK1XykFEZ1igw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/propagator-b3/node_modules/@opentelemetry/core": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.1.tgz",
+ "integrity": "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/propagator-jaeger": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-2.0.1.tgz",
+ "integrity": "sha512-7PMdPBmGVH2eQNb/AtSJizQNgeNTfh6jQFqys6lfhd6P4r+m/nTh3gKPPpaCXVdRQ+z93vfKk+4UGty390283w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/propagator-jaeger/node_modules/@opentelemetry/core": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.1.tgz",
+ "integrity": "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/resources": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.7.0.tgz",
+ "integrity": "sha512-K+oi0hNMv94EpZbnW3eyu2X6SGVpD3O5DhG2NIp65Hc7lhAj9brRXTAVzh3wB82+q3ThakEf7Zd7RsFUqcTc7A==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "@opentelemetry/core": "2.7.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-logs": {
+ "version": "0.215.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.215.0.tgz",
+ "integrity": "sha512-y3ucOmphzc4vgBTyIGchs+N/1rkACmoka8QalT2z1LBNM232Z17zMYayHcMl+dgMoOadZ0b72UZv7mDtqy1cFA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.215.0",
+ "@opentelemetry/core": "2.7.0",
+ "@opentelemetry/resources": "2.7.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.4.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-metrics": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.7.0.tgz",
+ "integrity": "sha512-Vd7h95av/LYRsAVN7wbprvvJnHkq7swMXAo7Uad0Uxf9jl6NSReLa0JNivrcc5BVIx/vl2t+cgdVQQbnVhsR9w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.7.0",
+ "@opentelemetry/resources": "2.7.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.9.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.203.0.tgz",
+ "integrity": "sha512-zRMvrZGhGVMvAbbjiNQW3eKzW/073dlrSiAKPVWmkoQzah9wfynpVPeL55f9fVIm0GaBxTLcPeukWGy0/Wj7KQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/exporter-logs-otlp-grpc": "0.203.0",
+ "@opentelemetry/exporter-logs-otlp-http": "0.203.0",
+ "@opentelemetry/exporter-logs-otlp-proto": "0.203.0",
+ "@opentelemetry/exporter-metrics-otlp-grpc": "0.203.0",
+ "@opentelemetry/exporter-metrics-otlp-http": "0.203.0",
+ "@opentelemetry/exporter-metrics-otlp-proto": "0.203.0",
+ "@opentelemetry/exporter-prometheus": "0.203.0",
+ "@opentelemetry/exporter-trace-otlp-grpc": "0.203.0",
+ "@opentelemetry/exporter-trace-otlp-http": "0.203.0",
+ "@opentelemetry/exporter-trace-otlp-proto": "0.203.0",
+ "@opentelemetry/exporter-zipkin": "2.0.1",
+ "@opentelemetry/instrumentation": "0.203.0",
+ "@opentelemetry/propagator-b3": "2.0.1",
+ "@opentelemetry/propagator-jaeger": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/sdk-logs": "0.203.0",
+ "@opentelemetry/sdk-metrics": "2.0.1",
+ "@opentelemetry/sdk-trace-base": "2.0.1",
+ "@opentelemetry/sdk-trace-node": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/api-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.203.0.tgz",
+ "integrity": "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/context-async-hooks": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.0.1.tgz",
+ "integrity": "sha512-XuY23lSI3d4PEqKA+7SLtAgwqIfc6E/E9eAQWLN1vlpC53ybO3o6jW4BsXo1xvz9lYyyWItfQDDLzezER01mCw==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/core": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.0.1.tgz",
+ "integrity": "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/exporter-trace-otlp-http": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.203.0.tgz",
+ "integrity": "sha512-ZDiaswNYo0yq/cy1bBLJFe691izEJ6IgNmkjm4C6kE9ub/OMQqDXORx2D2j8fzTBTxONyzusbaZlqtfmyqURPw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/otlp-exporter-base": "0.203.0",
+ "@opentelemetry/otlp-transformer": "0.203.0",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/sdk-trace-base": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/otlp-exporter-base": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.203.0.tgz",
+ "integrity": "sha512-Wbxf7k+87KyvxFr5D7uOiSq/vHXWommvdnNE7vECO3tAhsA2GfOlpWINCMWUEPdHZ7tCXxw6Epp3vgx3jU7llQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/otlp-transformer": "0.203.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/otlp-transformer": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.203.0.tgz",
+ "integrity": "sha512-Y8I6GgoCna0qDQ2W6GCRtaF24SnvqvA8OfeTi7fqigD23u8Jpb4R5KFv/pRvrlGagcCLICMIyh9wiejp4TXu/A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/sdk-logs": "0.203.0",
+ "@opentelemetry/sdk-metrics": "2.0.1",
+ "@opentelemetry/sdk-trace-base": "2.0.1",
+ "protobufjs": "^7.3.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/resources": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.0.1.tgz",
+ "integrity": "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/sdk-logs": {
+ "version": "0.203.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.203.0.tgz",
+ "integrity": "sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.203.0",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.4.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/sdk-metrics": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.0.1.tgz",
+ "integrity": "sha512-wf8OaJoSnujMAHWR3g+/hGvNcsC16rf9s1So4JlMiFaFHiE4HpIA3oUh+uWZQ7CNuK8gVW/pQSkgoa5HkkOl0g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.9.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/sdk-trace-base": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.1.tgz",
+ "integrity": "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/resources": "2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/sdk-trace-node": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-2.0.1.tgz",
+ "integrity": "sha512-UhdbPF19pMpBtCWYP5lHbTogLWx9N0EBxtdagvkn5YtsAnCBZzL7SjktG+ZmupRgifsHMjwUaCCaVmqGfSADmA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/context-async-hooks": "2.0.1",
+ "@opentelemetry/core": "2.0.1",
+ "@opentelemetry/sdk-trace-base": "2.0.1"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node/node_modules/protobufjs": {
+ "version": "7.6.6",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.6.tgz",
+ "integrity": "sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.5",
+ "@protobufjs/eventemitter": "^1.1.1",
+ "@protobufjs/fetch": "^1.1.1",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.1",
+ "@types/node": ">=13.7.0",
+ "long": "^5.3.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace/-/sdk-trace-2.11.0.tgz",
+ "integrity": "sha512-fFnTqGm8/G73GQVnxYi7LXa1ZVYEUvgL6XI1LpvV0bPC7WQ/ZGgKxCSl8FnlZBKto9JHHEFTO6s6CUpvvtwFrA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.11.0",
+ "@opentelemetry/resources": "2.11.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace-base": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.0.tgz",
+ "integrity": "sha512-Yg9zEXJB50DLVLpsKPk7NmNqlPlS+OvqhJGh0A8oawIOTPOwlm4eXs9BMJV7L79lvEwI+dWtAj+YjTyddV336A==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "@opentelemetry/core": "2.7.0",
+ "@opentelemetry/resources": "2.7.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace-node": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-2.11.0.tgz",
+ "integrity": "sha512-CuvCMJmZxswhNLlM2LfuLOW3h3fZujA4hsG4B+Sz4dX2zvaXO8Ng74cnDHWD64gLszTlhiG3c0iNUjj4g+0/sA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/context-async-hooks": "2.11.0",
+ "@opentelemetry/core": "2.11.0",
+ "@opentelemetry/sdk-trace-base": "2.11.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/core": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.11.0.tgz",
+ "integrity": "sha512-7YP44XH0tV6+Mb54x2YGf84i7yi+31MBZlE8JwvozkxyTvXbSp10X7cI7YE49ChJ3shMJoBmCJF3+1QFBJctGA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/resources": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.11.0.tgz",
+ "integrity": "sha512-Ie7+8q8MDF4FAEQCKVMTx3ReUvxiIAgIiiW3c9JdmP8+HMcDy20puT+AHjexnExgnbvBxjQ9fjkFDWrikJ2jQA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.11.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/sdk-trace-base": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.11.0.tgz",
+ "integrity": "sha512-H19x/TX/LZdqiYOjM7fqtSxwlplC5pgelavqbQdHbhdq0q/AI/TGkM2dfGuuynTXmJPeF2HoZVoPDu+TGoW78A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.11.0",
+ "@opentelemetry/resources": "2.11.0",
+ "@opentelemetry/sdk-trace": "2.11.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace/node_modules/@opentelemetry/core": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.11.0.tgz",
+ "integrity": "sha512-7YP44XH0tV6+Mb54x2YGf84i7yi+31MBZlE8JwvozkxyTvXbSp10X7cI7YE49ChJ3shMJoBmCJF3+1QFBJctGA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace/node_modules/@opentelemetry/resources": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.11.0.tgz",
+ "integrity": "sha512-Ie7+8q8MDF4FAEQCKVMTx3ReUvxiIAgIiiW3c9JdmP8+HMcDy20puT+AHjexnExgnbvBxjQ9fjkFDWrikJ2jQA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "2.11.0",
+ "@opentelemetry/semantic-conventions": "^1.29.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.6.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.43.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz",
+ "integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@protobufjs/aspromise": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
+ "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/base64": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
+ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/codegen": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz",
+ "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/eventemitter": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz",
+ "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/fetch": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz",
+ "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.1"
+ }
+ },
+ "node_modules/@protobufjs/float": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
+ "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/path": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
+ "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/pool": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
+ "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/utf8": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.2.tgz",
+ "integrity": "sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@standard-schema/spec": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
+ "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
+ "license": "MIT"
+ },
+ "node_modules/@swc/helpers": {
+ "version": "0.5.15",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
+ "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.8.0"
+ }
+ },
+ "node_modules/@tootallnate/once": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.1.tgz",
+ "integrity": "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@traceloop/ai-semantic-conventions": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/@traceloop/ai-semantic-conventions/-/ai-semantic-conventions-0.26.0.tgz",
+ "integrity": "sha512-Ict2OXBDw58Ij3WgHZqtloHkDsjVmm6MRsrehsfPfSg4rJk5HQc1ZIRwssFsjSbly6k6WXE//1U9lA61tZj4mg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.9.0",
+ "@opentelemetry/semantic-conventions": "^1.40.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@traceloop/instrumentation-anthropic": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/@traceloop/instrumentation-anthropic/-/instrumentation-anthropic-0.26.0.tgz",
+ "integrity": "sha512-esZbo2F3uEanIs6SU6hyt1sRlHRUnWIuTu29b72QXWT7XzS8l2TAY1usMNUT86W7CGVWZOHR4BT0B/tdoIijVA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.9.0",
+ "@opentelemetry/core": "^2.0.1",
+ "@opentelemetry/instrumentation": "^0.203.0",
+ "@opentelemetry/semantic-conventions": "^1.40.0",
+ "@traceloop/ai-semantic-conventions": "0.26.0",
+ "@traceloop/instrumentation-utils": "0.26.0",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@traceloop/instrumentation-bedrock": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/@traceloop/instrumentation-bedrock/-/instrumentation-bedrock-0.26.0.tgz",
+ "integrity": "sha512-SNTRyqmQHpH2CN7R3m3+aanYOqOzAhr0Orbbzx+mOonsUuXY+Yo7IiejwOu0exPudx+7czbUV1JbvDC1hjYZKQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.9.0",
+ "@opentelemetry/core": "^2.0.1",
+ "@opentelemetry/instrumentation": "^0.203.0",
+ "@opentelemetry/semantic-conventions": "^1.40.0",
+ "@traceloop/ai-semantic-conventions": "0.26.0",
+ "@traceloop/instrumentation-utils": "0.26.0",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@traceloop/instrumentation-chromadb": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/@traceloop/instrumentation-chromadb/-/instrumentation-chromadb-0.26.0.tgz",
+ "integrity": "sha512-eFu/Zwj5IblMRWzQblXO0mtUXWSylB08RSJzfj0gM2zU7TlHk7iz+NZHhvldTee39+wIqHIVPc6//d0UwB8+kQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.9.0",
+ "@opentelemetry/core": "^2.0.1",
+ "@opentelemetry/instrumentation": "^0.203.0",
+ "@opentelemetry/semantic-conventions": "^1.38.0",
+ "@traceloop/ai-semantic-conventions": "0.26.0",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@traceloop/instrumentation-cohere": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/@traceloop/instrumentation-cohere/-/instrumentation-cohere-0.26.0.tgz",
+ "integrity": "sha512-fdPq8kiL2gzHzJIwJXF2Ffw6J3jm5V9L1m6gqNHCQ8tSBT5WPwzHmN+OPCknq1/oaBaymWyepSYRn/8wOzov6g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.9.0",
+ "@opentelemetry/core": "^2.0.1",
+ "@opentelemetry/instrumentation": "^0.203.0",
+ "@opentelemetry/semantic-conventions": "^1.38.0",
+ "@traceloop/ai-semantic-conventions": "0.26.0",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@traceloop/instrumentation-google-generativeai": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/@traceloop/instrumentation-google-generativeai/-/instrumentation-google-generativeai-0.26.0.tgz",
+ "integrity": "sha512-26aiuE+e7hMol/vJDYVEynB86PFPZVdAdHHwxNZdEba6ASGo7EZvJYcvjHImP8dJVgOVP2en7YquJ0+TXUd0Yg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.9.0",
+ "@opentelemetry/core": "^2.0.1",
+ "@opentelemetry/instrumentation": "^0.203.0",
+ "@opentelemetry/semantic-conventions": "^1.40.0",
+ "@traceloop/ai-semantic-conventions": "0.26.0",
+ "@traceloop/instrumentation-utils": "0.26.0",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@traceloop/instrumentation-langchain": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/@traceloop/instrumentation-langchain/-/instrumentation-langchain-0.26.0.tgz",
+ "integrity": "sha512-WY8ZUXP51ZM0NwYiCupzEYyA/D2lw4LZi3bQ3NQRGjNTCaj/BEF1Ho9R8HpYSvBn/kJnbwsnGsxqgu1+fex6ig==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@langchain/core": ">=1.0.0 <2.0.0",
+ "@opentelemetry/api": "^1.9.0",
+ "@opentelemetry/core": "^2.0.1",
+ "@opentelemetry/instrumentation": "^0.203.0",
+ "@opentelemetry/semantic-conventions": "^1.40.0",
+ "@traceloop/ai-semantic-conventions": "0.26.0",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=20"
+ },
+ "peerDependencies": {
+ "@langchain/core": ">=1.0.0 <2.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@langchain/core": {
+ "optional": false
+ }
+ }
+ },
+ "node_modules/@traceloop/instrumentation-llamaindex": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/@traceloop/instrumentation-llamaindex/-/instrumentation-llamaindex-0.26.0.tgz",
+ "integrity": "sha512-hT9eB288hyhNmNoxXT7C+jzGq9W/nKe4qAZw8tsWZoxvNUapUda1ppd9aacVhJky2sW9++rSgxZPmoCVgqzpWA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.9.0",
+ "@opentelemetry/core": "^2.0.1",
+ "@opentelemetry/instrumentation": "^0.203.0",
+ "@opentelemetry/semantic-conventions": "^1.40.0",
+ "@traceloop/ai-semantic-conventions": "0.26.0",
+ "@traceloop/instrumentation-utils": "0.26.0",
+ "lodash": "^4.17.21",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@traceloop/instrumentation-mcp": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/@traceloop/instrumentation-mcp/-/instrumentation-mcp-0.26.0.tgz",
+ "integrity": "sha512-1xZZvAryZU/lWhagpnqQ+PULfpRnUc0mupp1BVso2fqJaISxBbJnUtWSUxHSZwcsHaWMz4nQ9NeZue/dnPBswQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.9.0",
+ "@opentelemetry/core": "^2.0.1",
+ "@opentelemetry/instrumentation": "^0.203.0",
+ "@opentelemetry/semantic-conventions": "^1.38.0",
+ "@traceloop/ai-semantic-conventions": "0.26.0",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@traceloop/instrumentation-openai": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/@traceloop/instrumentation-openai/-/instrumentation-openai-0.26.0.tgz",
+ "integrity": "sha512-ekFOgNLlb6VlxD30nCEH0dl2OgiWTWovZzMJJP80hH5hOgU9N20RJ468OtxVjlyw3PoU6iPVtU9UBsDsLhTfgQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.9.0",
+ "@opentelemetry/core": "^2.0.1",
+ "@opentelemetry/instrumentation": "^0.203.0",
+ "@opentelemetry/semantic-conventions": "^1.40.0",
+ "@traceloop/ai-semantic-conventions": "0.26.0",
+ "@traceloop/instrumentation-utils": "0.26.0",
+ "js-tiktoken": "^1.0.20",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@traceloop/instrumentation-pinecone": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/@traceloop/instrumentation-pinecone/-/instrumentation-pinecone-0.26.0.tgz",
+ "integrity": "sha512-2Dbhf1RvWFb/9gTf76c4bSbgTVP6yZBAb5qiIujfvIm3YTRC7coLfxKxzXaHGH3RF2fCdPxV6IIVFVHOAtCO/w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.9.0",
+ "@opentelemetry/core": "^2.0.1",
+ "@opentelemetry/instrumentation": "^0.203.0",
+ "@opentelemetry/semantic-conventions": "^1.38.0",
+ "@traceloop/ai-semantic-conventions": "0.26.0",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@traceloop/instrumentation-qdrant": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/@traceloop/instrumentation-qdrant/-/instrumentation-qdrant-0.26.0.tgz",
+ "integrity": "sha512-ZDU8C1wNrYhIVaAcwcm/ukDUSgLWvfZjYhCZxtXlOjeWMjodBUGR2/OrtYgjN68IbfM8dJukXHXj6uzS2S2/tw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.9.0",
+ "@opentelemetry/core": "^2.0.1",
+ "@opentelemetry/instrumentation": "^0.203.0",
+ "@traceloop/ai-semantic-conventions": "0.26.0",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@traceloop/instrumentation-together": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/@traceloop/instrumentation-together/-/instrumentation-together-0.26.0.tgz",
+ "integrity": "sha512-pLkQI8WUAEeJmWxILhZNGpn6NBtfrFqXzIa+TWxJVlxdUtUCQ1XLbc2f5KOHuwGCATlmCO1uFs+GlVur8mqcDw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.9.0",
+ "@opentelemetry/core": "^2.0.1",
+ "@opentelemetry/instrumentation": "^0.203.0",
+ "@opentelemetry/semantic-conventions": "^1.38.0",
+ "@traceloop/ai-semantic-conventions": "0.26.0",
+ "js-tiktoken": "^1.0.20",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@traceloop/instrumentation-utils": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/@traceloop/instrumentation-utils/-/instrumentation-utils-0.26.0.tgz",
+ "integrity": "sha512-9uPCUVeZzJ0xh9DogLWKXd+bZsjwh/XJfYeLG3fkoUgmj/4XaTVf3W3F/z3yjDBcUI0vHwOwe2vpg+nWBHXZFQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.40.0",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@traceloop/instrumentation-vertexai": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/@traceloop/instrumentation-vertexai/-/instrumentation-vertexai-0.26.0.tgz",
+ "integrity": "sha512-ithoN+3GuVVgue1Dgaj3fad0lxMj9JZqirvrjgHaI92L1rrJhlsYghX4ak965/4Jd3Uc9VGjnJm+Pz+OENPeBw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.9.0",
+ "@opentelemetry/core": "^2.0.1",
+ "@opentelemetry/instrumentation": "^0.203.0",
+ "@opentelemetry/semantic-conventions": "^1.38.0",
+ "@traceloop/ai-semantic-conventions": "0.26.0",
+ "google-gax": "^4.0.0",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@traceloop/node-server-sdk": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/@traceloop/node-server-sdk/-/node-server-sdk-0.26.0.tgz",
+ "integrity": "sha512-0m1fD58kl73n62IodjOx8rjz3hE5mOyy/kv5S7Fq/DS09lyrH7N7VcR2PCQpzDXKLm2Mv0PnYNqVBaVTK2WRfA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@google-cloud/opentelemetry-cloud-trace-exporter": "^3.0.0",
+ "@opentelemetry/api": "^1.9.0",
+ "@opentelemetry/core": "^2.0.1",
+ "@opentelemetry/exporter-trace-otlp-proto": "^0.203.0",
+ "@opentelemetry/instrumentation": "^0.203.0",
+ "@opentelemetry/resources": "^2.0.1",
+ "@opentelemetry/sdk-node": "^0.203.0",
+ "@opentelemetry/sdk-trace-base": "^2.0.1",
+ "@opentelemetry/sdk-trace-node": "^2.0.1",
+ "@opentelemetry/semantic-conventions": "^1.40.0",
+ "@traceloop/ai-semantic-conventions": "0.26.0",
+ "@traceloop/instrumentation-anthropic": "0.26.0",
+ "@traceloop/instrumentation-bedrock": "0.26.0",
+ "@traceloop/instrumentation-chromadb": "0.26.0",
+ "@traceloop/instrumentation-cohere": "0.26.0",
+ "@traceloop/instrumentation-google-generativeai": "0.26.0",
+ "@traceloop/instrumentation-langchain": "0.26.0",
+ "@traceloop/instrumentation-llamaindex": "0.26.0",
+ "@traceloop/instrumentation-mcp": "0.26.0",
+ "@traceloop/instrumentation-openai": "0.26.0",
+ "@traceloop/instrumentation-pinecone": "0.26.0",
+ "@traceloop/instrumentation-qdrant": "0.26.0",
+ "@traceloop/instrumentation-together": "0.26.0",
+ "@traceloop/instrumentation-utils": "0.26.0",
+ "@traceloop/instrumentation-vertexai": "0.26.0",
+ "@types/nunjucks": "^3.2.6",
+ "cross-fetch": "^4.1.0",
+ "eventsource": "^3.0.2",
+ "fetch-retry": "^6.0.0",
+ "mime-types": "^3.0.2",
+ "nunjucks": "^3.2.4",
+ "papaparse": "^5.5.3",
+ "supports-color": "^10.0.0",
+ "tslib": "^2.8.1",
+ "uuid": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.9.0",
+ "@opentelemetry/exporter-trace-otlp-proto": "^0.203.0",
+ "@opentelemetry/resources": "^2.0.0",
+ "@opentelemetry/sdk-trace-base": "^2.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@opentelemetry/api": {
+ "optional": false
+ },
+ "@opentelemetry/exporter-trace-otlp-proto": {
+ "optional": false
+ },
+ "@opentelemetry/resources": {
+ "optional": false
+ },
+ "@opentelemetry/sdk-trace-base": {
+ "optional": false
+ }
+ }
+ },
+ "node_modules/@traceloop/node-server-sdk/node_modules/uuid": {
+ "version": "11.1.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz",
+ "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/esm/bin/uuid"
+ }
+ },
+ "node_modules/@types/caseless": {
+ "version": "0.12.5",
+ "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz",
+ "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/long": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz",
+ "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "22.10.2",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz",
+ "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.20.0"
+ }
+ },
+ "node_modules/@types/nunjucks": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/@types/nunjucks/-/nunjucks-3.2.6.tgz",
+ "integrity": "sha512-pHiGtf83na1nCzliuAdq8GowYiXvH5l931xZ0YEHaLMNFgynpEqx+IPStlu7UaDkehfvl01e4x/9Tpwhy7Ue3w==",
+ "license": "MIT"
+ },
+ "node_modules/@types/prismjs": {
+ "version": "1.26.6",
+ "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.6.tgz",
+ "integrity": "sha512-vqlvI7qlMvcCBbVe0AKAb4f97//Hy0EBTaiW8AalRnG/xAN5zOiWWyrNqNXeq8+KAuvRewjCVY1+IPxk4RdNYw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/react": {
+ "version": "19.1.1",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.1.tgz",
+ "integrity": "sha512-ePapxDL7qrgqSF67s0h9m412d9DbXyC1n59O2st+9rjuuamWsZuD2w55rqY12CbzsZ7uVXb5Nw0gEp9Z8MMutQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "19.1.1",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.1.tgz",
+ "integrity": "sha512-jFf/woGTVTjUJsl2O7hcopJ1r0upqoq/vIOoCj0yLh3RIXxWcljlpuZ+vEBRXsymD1jhfeJrlyTy/S1UW+4y1w==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "^19.0.0"
+ }
+ },
+ "node_modules/@types/request": {
+ "version": "2.48.13",
+ "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.13.tgz",
+ "integrity": "sha512-FGJ6udDNUCjd19pp0Q3iTiDkwhYup7J8hpMW9c4k53NrccQFFWKRho6hvtPPEhnXWKvukfwAlB6DbDz4yhH5Gg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/caseless": "*",
+ "@types/node": "*",
+ "@types/tough-cookie": "*",
+ "form-data": "^2.5.5"
+ }
+ },
+ "node_modules/@types/request/node_modules/form-data": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.6.tgz",
+ "integrity": "sha512-Ogz/E85h9tlfJzpI6TuFpGcHZFhLrb9Gw8wq9v40CxSCPnv7ahKr6Xgtkn0KYCDQJ8DNn5VoMO8EXr9V5PadyA==",
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.4",
+ "mime-types": "^2.1.35",
+ "safe-buffer": "^5.2.1"
+ },
+ "engines": {
+ "node": ">= 0.12"
+ }
+ },
+ "node_modules/@types/request/node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/@types/request/node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/@types/tough-cookie": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
+ "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==",
+ "license": "MIT"
+ },
+ "node_modules/a-sync-waterfall": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz",
+ "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==",
+ "license": "MIT"
+ },
+ "node_modules/abort-controller": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
+ "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
+ "license": "MIT",
+ "dependencies": {
+ "event-target-shim": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6.5"
+ }
+ },
+ "node_modules/accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/accepts/node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/accepts/node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz",
+ "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==",
+ "license": "MIT",
+ "peer": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-import-attributes": {
+ "version": "1.9.5",
+ "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz",
+ "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^8"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/agent-base/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/agent-base/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
+ "license": "MIT"
+ },
+ "node_modules/asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
+ "license": "MIT"
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT"
+ },
+ "node_modules/axios": {
+ "version": "1.20.0",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.20.0.tgz",
+ "integrity": "sha512-r8aOh8j9cGKpgQAqpzrUHnSIc6a59Y3Xf/cv8sy1DrHCkZHzQGEuoq1tARk6qSyDdtQGSDgpb9kFlruzPvrgwg==",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.16.0",
+ "form-data": "^4.0.6",
+ "https-proxy-agent": "^5.0.1",
+ "proxy-from-env": "^2.1.0"
+ }
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/bignumber.js": {
+ "version": "9.3.1",
+ "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz",
+ "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/body-parser": {
+ "version": "1.20.3",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
+ "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "content-type": "~1.0.5",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "on-finished": "2.4.1",
+ "qs": "6.13.0",
+ "raw-body": "2.5.2",
+ "type-is": "~1.6.18",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001810",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001810.tgz",
+ "integrity": "sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/cjs-module-lexer": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz",
+ "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==",
+ "license": "MIT"
+ },
+ "node_modules/client-only": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
+ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
+ "license": "MIT"
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/commander": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
+ "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/content-disposition": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "5.2.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
+ "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
+ "license": "MIT"
+ },
+ "node_modules/cross-fetch": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz",
+ "integrity": "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==",
+ "license": "MIT",
+ "dependencies": {
+ "node-fetch": "^2.7.0"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/data-uri-to-buffer": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
+ "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/destroy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/detect-libc": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/duplexify": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz",
+ "integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==",
+ "license": "MIT",
+ "dependencies": {
+ "end-of-stream": "^1.4.1",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.1.1",
+ "stream-shift": "^1.0.2"
+ }
+ },
+ "node_modules/ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "license": "MIT"
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/encodeurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/end-of-stream": {
+ "version": "1.4.5",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
+ "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
+ "license": "MIT",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz",
+ "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "license": "MIT"
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/event-target-shim": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
+ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/eventemitter3": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
+ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
+ "license": "MIT"
+ },
+ "node_modules/eventsource": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz",
+ "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==",
+ "license": "MIT",
+ "dependencies": {
+ "eventsource-parser": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/eventsource-parser": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.1.1.tgz",
+ "integrity": "sha512-EKN1vKAMcZ8MlYMpaNuxN6R9yakzH6uajHcHVTqWJzvu5pWw9DyhbP35HH8MVBQ+dZjAfDxk+A8NiR9KWaXiyQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/express": {
+ "version": "4.21.2",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
+ "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "accepts": "~1.3.8",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.20.3",
+ "content-disposition": "0.5.4",
+ "content-type": "~1.0.4",
+ "cookie": "0.7.1",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "1.3.1",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "merge-descriptors": "1.0.3",
+ "methods": "~1.1.2",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.12",
+ "proxy-addr": "~2.0.7",
+ "qs": "6.13.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.2.1",
+ "send": "0.19.0",
+ "serve-static": "1.16.2",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "license": "MIT"
+ },
+ "node_modules/fetch-blob": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
+ "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/jimmywarting"
+ },
+ {
+ "type": "paypal",
+ "url": "https://paypal.me/jimmywarting"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "node-domexception": "^1.0.0",
+ "web-streams-polyfill": "^3.0.3"
+ },
+ "engines": {
+ "node": "^12.20 || >= 14.13"
+ }
+ },
+ "node_modules/fetch-retry": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-6.0.0.tgz",
+ "integrity": "sha512-BUFj1aMubgib37I3v4q78fYo63Po7t4HUPTpQ6/QE6yK6cIQrP+W43FYToeTEyg5m2Y7eFUtijUuAv/PDlWuag==",
+ "license": "MIT"
+ },
+ "node_modules/finalhandler": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
+ "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "2.6.9",
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "statuses": "2.0.1",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz",
+ "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
+ "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.4",
+ "mime-types": "^2.1.35"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/form-data/node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/form-data/node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/formdata-polyfill": {
+ "version": "4.0.10",
+ "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
+ "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
+ "license": "MIT",
+ "dependencies": {
+ "fetch-blob": "^3.1.2"
+ },
+ "engines": {
+ "node": ">=12.20.0"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gaxios": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.3.1.tgz",
+ "integrity": "sha512-kB3rzJV7d9juLZh8/56QTXCwQfxyhdOMdyYk1HdQKFtF8TJTDTZQJtixWIwXdE9Jji91mC41DUNpjleo4L4eAQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "extend": "^3.0.2",
+ "https-proxy-agent": "^7.0.1",
+ "node-fetch": "^3.3.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/gaxios/node_modules/agent-base": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+ "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/gaxios/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/gaxios/node_modules/https-proxy-agent": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/gaxios/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/gaxios/node_modules/node-fetch": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
+ "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
+ "license": "MIT",
+ "dependencies": {
+ "data-uri-to-buffer": "^4.0.0",
+ "fetch-blob": "^3.1.4",
+ "formdata-polyfill": "^4.0.10"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/node-fetch"
+ }
+ },
+ "node_modules/gcp-metadata": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-9.0.3.tgz",
+ "integrity": "sha512-2YYnIlHaKBGT2IPg3G2M57hia9Galz15zsEOvw9T3oRf0lSn6KN6VcHQLqby7x8ksYKnjXvp3rp2KJyLCN6zfQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "gaxios": "^7.1.3",
+ "google-logging-utils": "^2.0.0",
+ "json-bigint": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/google-auth-library": {
+ "version": "10.9.1",
+ "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.9.1.tgz",
+ "integrity": "sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "base64-js": "^1.3.0",
+ "ecdsa-sig-formatter": "^1.0.11",
+ "gaxios": "^7.1.4",
+ "gcp-metadata": "8.1.2",
+ "google-logging-utils": "1.1.3",
+ "jws": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/google-auth-library/node_modules/gcp-metadata": {
+ "version": "8.1.2",
+ "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz",
+ "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "gaxios": "^7.0.0",
+ "google-logging-utils": "^1.0.0",
+ "json-bigint": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/google-auth-library/node_modules/google-logging-utils": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz",
+ "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/google-gax": {
+ "version": "4.6.1",
+ "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.6.1.tgz",
+ "integrity": "sha512-V6eky/xz2mcKfAd1Ioxyd6nmA61gao3n01C+YeuIwu3vzM9EDR6wcVzMSIbLMDXWeoi9SHYctXuKYC5uJUT3eQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/grpc-js": "^1.10.9",
+ "@grpc/proto-loader": "^0.7.13",
+ "@types/long": "^4.0.0",
+ "abort-controller": "^3.0.0",
+ "duplexify": "^4.0.0",
+ "google-auth-library": "^9.3.0",
+ "node-fetch": "^2.7.0",
+ "object-hash": "^3.0.0",
+ "proto3-json-serializer": "^2.0.2",
+ "protobufjs": "^7.3.2",
+ "retry-request": "^7.0.0",
+ "uuid": "^9.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/google-gax/node_modules/@grpc/proto-loader": {
+ "version": "0.7.15",
+ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz",
+ "integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "lodash.camelcase": "^4.3.0",
+ "long": "^5.0.0",
+ "protobufjs": "^7.2.5",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/google-gax/node_modules/agent-base": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+ "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/google-gax/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/google-gax/node_modules/gaxios": {
+ "version": "6.7.1",
+ "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz",
+ "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "extend": "^3.0.2",
+ "https-proxy-agent": "^7.0.1",
+ "is-stream": "^2.0.0",
+ "node-fetch": "^2.6.9",
+ "uuid": "^9.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/google-gax/node_modules/gcp-metadata": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz",
+ "integrity": "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "gaxios": "^6.1.1",
+ "google-logging-utils": "^0.0.2",
+ "json-bigint": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/google-gax/node_modules/google-auth-library": {
+ "version": "9.15.1",
+ "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.15.1.tgz",
+ "integrity": "sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "base64-js": "^1.3.0",
+ "ecdsa-sig-formatter": "^1.0.11",
+ "gaxios": "^6.1.1",
+ "gcp-metadata": "^6.1.0",
+ "gtoken": "^7.0.0",
+ "jws": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/google-gax/node_modules/google-logging-utils": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-0.0.2.tgz",
+ "integrity": "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/google-gax/node_modules/https-proxy-agent": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/google-gax/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/google-gax/node_modules/protobufjs": {
+ "version": "7.6.6",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.6.tgz",
+ "integrity": "sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.5",
+ "@protobufjs/eventemitter": "^1.1.1",
+ "@protobufjs/fetch": "^1.1.1",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.1",
+ "@types/node": ">=13.7.0",
+ "long": "^5.3.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/google-gax/node_modules/uuid": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
+ "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
+ "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/google-logging-utils": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-2.0.1.tgz",
+ "integrity": "sha512-HMhaQghlOTvbcb3c4T5jmmOMtG3JUF1iOQMezaJXL86CDS+Tm2vHd0IeLFRAx3+ewd+bo9E1HFHoy17X5aJa9A==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=22"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gtoken": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz",
+ "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==",
+ "license": "MIT",
+ "dependencies": {
+ "gaxios": "^6.0.0",
+ "jws": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/gtoken/node_modules/agent-base": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+ "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/gtoken/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/gtoken/node_modules/gaxios": {
+ "version": "6.7.1",
+ "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz",
+ "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "extend": "^3.0.2",
+ "https-proxy-agent": "^7.0.1",
+ "is-stream": "^2.0.0",
+ "node-fetch": "^2.6.9",
+ "uuid": "^9.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/gtoken/node_modules/https-proxy-agent": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/gtoken/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/gtoken/node_modules/uuid": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
+ "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
+ "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
+ "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "depd": "2.0.0",
+ "inherits": "2.0.4",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "toidentifier": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/http-proxy-agent": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
+ "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
+ "license": "MIT",
+ "dependencies": {
+ "@tootallnate/once": "2",
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/http-proxy-agent/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/http-proxy-agent/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/https-proxy-agent/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/https-proxy-agent/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/import-in-the-middle": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz",
+ "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.14.0",
+ "acorn-import-attributes": "^1.9.5",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "license": "ISC"
+ },
+ "node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.2",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz",
+ "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==",
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/jose": {
+ "version": "5.10.0",
+ "resolved": "https://registry.npmjs.org/jose/-/jose-5.10.0.tgz",
+ "integrity": "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/panva"
+ }
+ },
+ "node_modules/js-file-download": {
+ "version": "0.4.12",
+ "resolved": "https://registry.npmjs.org/js-file-download/-/js-file-download-0.4.12.tgz",
+ "integrity": "sha512-rML+NkoD08p5Dllpjo0ffy4jRHeY6Zsapvr/W86N7E0yuzAO6qa5X9+xog6zQNlH102J7IXljNY2FtS6Lj3ucg==",
+ "license": "MIT"
+ },
+ "node_modules/js-tiktoken": {
+ "version": "1.0.21",
+ "resolved": "https://registry.npmjs.org/js-tiktoken/-/js-tiktoken-1.0.21.tgz",
+ "integrity": "sha512-biOj/6M5qdgx5TKjDnFT1ymSpM5tbd3ylwDtrQvFQSu0Z7bBYko2dF+W/aUkXUPuk6IVpRxk/3Q2sHOzGlS36g==",
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "^1.5.1"
+ }
+ },
+ "node_modules/json-bigint": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
+ "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "bignumber.js": "^9.0.0"
+ }
+ },
+ "node_modules/jwa": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
+ "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer-equal-constant-time": "^1.0.1",
+ "ecdsa-sig-formatter": "1.0.11",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/jws": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
+ "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
+ "license": "MIT",
+ "dependencies": {
+ "jwa": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/langsmith": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/langsmith/-/langsmith-0.9.0.tgz",
+ "integrity": "sha512-tlg/aG7qezAKY6G3fgADSX7PkRj+JKoF3z7QNkCMsAOvwvuzhiwP9Amn1Z+zAIxuKoWuXQdIjtFN0LVmUC1oUQ==",
+ "license": "MIT",
+ "dependencies": {
+ "p-queue": "6.6.2"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "*",
+ "@opentelemetry/exporter-trace-otlp-proto": "*",
+ "@opentelemetry/sdk-trace-base": "*",
+ "openai": "*",
+ "ws": ">=7"
+ },
+ "peerDependenciesMeta": {
+ "@opentelemetry/api": {
+ "optional": true
+ },
+ "@opentelemetry/exporter-trace-otlp-proto": {
+ "optional": true
+ },
+ "@opentelemetry/sdk-trace-base": {
+ "optional": true
+ },
+ "openai": {
+ "optional": true
+ },
+ "ws": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.18.1",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
+ "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
+ "license": "MIT"
+ },
+ "node_modules/long": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
+ "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/merge-descriptors": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
+ "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "license": "MIT",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.54.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
+ "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "^1.54.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/module-details-from-path": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz",
+ "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==",
+ "license": "MIT"
+ },
+ "node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/mustache": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz",
+ "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==",
+ "license": "MIT",
+ "bin": {
+ "mustache": "bin/mustache"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.18",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
+ "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/next": {
+ "version": "15.5.25",
+ "resolved": "https://registry.npmjs.org/next/-/next-15.5.25.tgz",
+ "integrity": "sha512-OMWNulIIqKM2ykvC2qMjIt0IoavB4UB2SCs4iXJ6z6847FvyH8jBmBWcvrF5iuhTu8Przh20Fo/aoszIdqx4PA==",
+ "license": "MIT",
+ "dependencies": {
+ "@next/env": "15.5.25",
+ "@swc/helpers": "0.5.15",
+ "caniuse-lite": "^1.0.30001579",
+ "postcss": "8.4.31",
+ "styled-jsx": "5.1.6"
+ },
+ "bin": {
+ "next": "dist/bin/next"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^19.8.0 || >= 20.0.0"
+ },
+ "optionalDependencies": {
+ "@next/swc-darwin-arm64": "15.5.25",
+ "@next/swc-darwin-x64": "15.5.25",
+ "@next/swc-linux-arm64-gnu": "15.5.25",
"@next/swc-linux-arm64-musl": "15.5.25",
"@next/swc-linux-x64-gnu": "15.5.25",
"@next/swc-linux-x64-musl": "15.5.25",
@@ -826,6 +5510,199 @@
}
}
},
+ "node_modules/node-domexception": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
+ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
+ "deprecated": "Use your platform's native DOMException instead",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/jimmywarting"
+ },
+ {
+ "type": "github",
+ "url": "https://paypal.me/jimmywarting"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.5.0"
+ }
+ },
+ "node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/nunjucks": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz",
+ "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "a-sync-waterfall": "^1.0.0",
+ "asap": "^2.0.3",
+ "commander": "^5.1.0"
+ },
+ "bin": {
+ "nunjucks-precompile": "bin/precompile"
+ },
+ "engines": {
+ "node": ">= 6.9.0"
+ },
+ "peerDependencies": {
+ "chokidar": "^3.3.0"
+ },
+ "peerDependenciesMeta": {
+ "chokidar": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/object-hash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
+ "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "license": "MIT",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/openai": {
+ "version": "5.23.2",
+ "resolved": "https://registry.npmjs.org/openai/-/openai-5.23.2.tgz",
+ "integrity": "sha512-MQBzmTulj+MM5O8SKEk/gL8a7s5mktS9zUtAkU257WjvobGc9nKcBuVwjyEEcb9SI8a8Y2G/mzn3vm9n1Jlleg==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "bin": {
+ "openai": "bin/cli"
+ },
+ "peerDependencies": {
+ "ws": "^8.18.0",
+ "zod": "^3.23.8"
+ },
+ "peerDependenciesMeta": {
+ "ws": {
+ "optional": true
+ },
+ "zod": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/p-queue": {
+ "version": "6.6.2",
+ "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz",
+ "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==",
+ "license": "MIT",
+ "dependencies": {
+ "eventemitter3": "^4.0.4",
+ "p-timeout": "^3.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-timeout": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz",
+ "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==",
+ "license": "MIT",
+ "dependencies": {
+ "p-finally": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/papaparse": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.7.0.tgz",
+ "integrity": "sha512-qBGxg/7Q3Kl9Wfhrz2Z74UnvnHTXLNG6jmKJFeBvP2+y4lV7So+7SR62+Zd47JvdrCkX+nDcnr0ObPzek/+6RA==",
+ "license": "MIT"
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "license": "MIT"
+ },
+ "node_modules/path-to-regexp": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
+ "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
+ "license": "MIT"
+ },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -866,7 +5743,115 @@
"integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==",
"license": "MIT",
"engines": {
- "node": ">=6"
+ "node": ">=6"
+ }
+ },
+ "node_modules/proto3-json-serializer": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-2.0.2.tgz",
+ "integrity": "sha512-SAzp/O4Yh02jGdRc+uIrGoe87dkN/XtwxfZ4ZyafJHymd79ozp5VG5nyZ7ygqPM5+cpLDjjGnYFUkngonyDPOQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "protobufjs": "^7.2.5"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/proto3-json-serializer/node_modules/protobufjs": {
+ "version": "7.6.6",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.6.tgz",
+ "integrity": "sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.5",
+ "@protobufjs/eventemitter": "^1.1.1",
+ "@protobufjs/fetch": "^1.1.1",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.1",
+ "@types/node": ">=13.7.0",
+ "long": "^5.3.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/protobufjs": {
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-8.8.0.tgz",
+ "integrity": "sha512-N3xhQ5yyBx3vQq4gubBfASzYhJGNzeDbjqBpu61g7UVylsN/qyffU96TKWD3GbbLOKF82VGNRNvv1+BFgE31Eg==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "long": "^5.3.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "license": "MIT",
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/proxy-from-env": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
+ "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
+ "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "side-channel": "^1.0.6"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
+ "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
}
},
"node_modules/react": {
@@ -892,6 +5877,127 @@
"react": "^19.1.1"
}
},
+ "node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-in-the-middle": {
+ "version": "7.5.2",
+ "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz",
+ "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.5",
+ "module-details-from-path": "^1.0.3",
+ "resolve": "^1.22.8"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/require-in-the-middle/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/require-in-the-middle/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/resolve": {
+ "version": "1.22.12",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
+ "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "is-core-module": "^2.16.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/retry-request": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz",
+ "integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/request": "^2.48.8",
+ "extend": "^3.0.2",
+ "teeny-request": "^9.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "license": "MIT"
+ },
"node_modules/scheduler": {
"version": "0.26.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
@@ -911,6 +6017,66 @@
"node": ">=10"
}
},
+ "node_modules/send": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
+ "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "mime": "1.6.0",
+ "ms": "2.1.3",
+ "on-finished": "2.4.1",
+ "range-parser": "~1.2.1",
+ "statuses": "2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/send/node_modules/encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/send/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/serve-static": {
+ "version": "1.16.2",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
+ "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
+ "license": "MIT",
+ "dependencies": {
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.19.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "license": "ISC"
+ },
"node_modules/sharp": {
"version": "0.35.4",
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.4.tgz",
@@ -961,6 +6127,78 @@
}
}
},
+ "node_modules/side-channel": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz",
+ "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.4",
+ "side-channel-list": "^1.0.1",
+ "side-channel-map": "^1.0.1",
+ "side-channel-weakmap": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-list": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
+ "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-map": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-weakmap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3",
+ "side-channel-map": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -970,6 +6208,71 @@
"node": ">=0.10.0"
}
},
+ "node_modules/statuses": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/stream-events": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz",
+ "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==",
+ "license": "MIT",
+ "dependencies": {
+ "stubs": "^3.0.0"
+ }
+ },
+ "node_modules/stream-shift": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz",
+ "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==",
+ "license": "MIT"
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/stubs": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz",
+ "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==",
+ "license": "MIT"
+ },
"node_modules/styled-jsx": {
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz",
@@ -993,12 +6296,115 @@
}
}
},
+ "node_modules/supports-color": {
+ "version": "10.2.2",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz",
+ "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/teeny-request": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz",
+ "integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "http-proxy-agent": "^5.0.0",
+ "https-proxy-agent": "^5.0.0",
+ "node-fetch": "^2.6.9",
+ "stream-events": "^1.0.5",
+ "uuid": "^9.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/teeny-request/node_modules/uuid": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
+ "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
+ "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "license": "MIT"
+ },
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD"
},
+ "node_modules/type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "license": "MIT",
+ "dependencies": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/type-is/node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/type-is/node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/typescript": {
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz",
@@ -1017,8 +6423,157 @@
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
- "dev": true,
"license": "MIT"
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "license": "MIT"
+ },
+ "node_modules/utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/uuid": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz",
+ "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==",
+ "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/web-streams-polyfill": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
+ "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "license": "ISC"
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs": {
+ "version": "17.7.3",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz",
+ "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==",
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/zod": {
+ "version": "3.25.76",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
+ "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
+ "license": "MIT",
+ "peer": true,
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/zod-to-json-schema": {
+ "version": "3.25.2",
+ "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz",
+ "integrity": "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==",
+ "license": "ISC",
+ "peerDependencies": {
+ "zod": "^3.25.28 || ^4"
+ }
}
}
}
diff --git a/showcase/package.json b/showcase/package.json
index 29fd580d..fb8bde65 100644
--- a/showcase/package.json
+++ b/showcase/package.json
@@ -12,6 +12,7 @@
"sync:media": "bash scripts/sync-media.sh"
},
"dependencies": {
+ "@nevermined-io/payments": "1.11.2",
"next": "^15.5.25",
"prismjs": "^1.30.0",
"react": "19.1.1",
From 2d1cf39c194dd2193397dd65f7179c591cd52490 Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 18:57:32 +0200
Subject: [PATCH 15/24] =?UTF-8?q?feat(showcase):=20Connect-with-Nevermined?=
=?UTF-8?q?=20flow=20=E2=80=94=20per-user=20API=20key=20(localStorage)=20d?=
=?UTF-8?q?rives=20live=20x402/MPP?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Connect button redirects to the App /auth/cli?callback_url=...; callback returns ?nvm_api_key,
stored in localStorage and sent per-request; server mints tokens with the viewer's own key.
- Security: shared-key env fallback gated behind ALLOW_SHARED_KEY_DEV (prod = per-user only);
key lives in localStorage not the cookie (CSRF can't trigger spend); key never logged.
---
showcase/app/api/agent/route.ts | 9 +-
showcase/components/LiveRunPanel.tsx | 177 ++++++++++++++++++++-------
showcase/lib/live-agent.mjs | 82 ++++++++-----
3 files changed, 194 insertions(+), 74 deletions(-)
diff --git a/showcase/app/api/agent/route.ts b/showcase/app/api/agent/route.ts
index 8e24a6b6..3184fa17 100644
--- a/showcase/app/api/agent/route.ts
+++ b/showcase/app/api/agent/route.ts
@@ -19,7 +19,7 @@ type Sub = { authorized: boolean; balance: number };
// and unsigned (httpOnly is not integrity), so it must never gate real spend — a raw
// `Cookie: nvm_demo={"x":{"authorized":true,"balance":1e9}}` would otherwise pass.
export async function POST(req: NextRequest) {
- let payload: { slug?: string; action?: string; message?: string };
+ let payload: { slug?: string; action?: string; message?: string; apiKey?: string };
try {
payload = await req.json();
} catch {
@@ -45,10 +45,13 @@ export async function POST(req: NextRequest) {
slug,
action: (payload.action ?? "ask") as "intro" | "ask" | "authorize" | "reset",
message: payload.message,
+ // The viewer's Nevermined key (from localStorage via the Connect flow); used server-side to
+ // mint tokens on their behalf. Only forwarded to the live buyer, never to the simulator.
+ apiKey: payload.apiKey,
};
// Live slugs hit the real deployed agent (server-side buyer); everything else uses the
- // in-process simulator. isLiveSlug is false unless WEATHER_AGENT_URL + NVM_API_KEY + a plan id
- // are configured, so the site stays a pure simulator when unconfigured.
+ // in-process simulator. isLiveSlug is false unless WEATHER_AGENT_URL + a plan id are configured,
+ // so the site stays a pure simulator when unconfigured.
const result = isLiveSlug(slug)
? await liveRespond(all[slug], agentReq)
: respond(all[slug], agentReq);
diff --git a/showcase/components/LiveRunPanel.tsx b/showcase/components/LiveRunPanel.tsx
index e1c4400f..1ab4a855 100644
--- a/showcase/components/LiveRunPanel.tsx
+++ b/showcase/components/LiveRunPanel.tsx
@@ -15,6 +15,27 @@ interface Intro {
suggestions: string[];
authorized: boolean;
balance: number;
+ live?: boolean;
+}
+
+// The Nevermined App host for the "Connect" (CLI-auth) flow. Sandbox vs live is chosen inside the
+// App; this is just the frontend host. Override per-deployment via NEXT_PUBLIC_NVM_APP_URL.
+const APP_URL = process.env.NEXT_PUBLIC_NVM_APP_URL || "https://nevermined.app";
+const KEY_STORAGE = "nvm_api_key";
+
+function readStoredKey(): string | null {
+ try {
+ return localStorage.getItem(KEY_STORAGE);
+ } catch {
+ return null;
+ }
+}
+
+// Current page URL with any nvm_api_key param stripped — used as the callback target.
+function cleanCallbackUrl(): string {
+ const u = new URL(window.location.href);
+ u.searchParams.delete(KEY_STORAGE);
+ return u.toString();
}
export default function LiveRunPanel({
@@ -33,13 +54,31 @@ export default function LiveRunPanel({
const [flash, setFlash] = useState(false);
const [input, setInput] = useState("");
const [busy, setBusy] = useState(false);
+ const [live, setLive] = useState(false);
+ const [apiKey, setApiKey] = useState(null);
const logRef = useRef(null);
+ // On mount: capture an nvm_api_key returned by the Nevermined App callback (query string),
+ // persist it, and clean the URL — otherwise fall back to a previously stored key.
+ useEffect(() => {
+ try {
+ const params = new URLSearchParams(window.location.search);
+ const returned = params.get(KEY_STORAGE);
+ if (returned) {
+ localStorage.setItem(KEY_STORAGE, returned);
+ window.history.replaceState({}, "", cleanCallbackUrl());
+ }
+ } catch {
+ /* private mode / no storage — connect flow just won't persist */
+ }
+ setApiKey(readStoredKey());
+ }, []);
+
async function call(action: string, message?: string) {
const res = await fetch("/api/agent", {
method: "POST",
headers: { "content-type": "application/json" },
- body: JSON.stringify({ slug, action, message }),
+ body: JSON.stringify({ slug, action, message, apiKey: readStoredKey() ?? undefined }),
});
return { status: res.status, body: await res.json() };
}
@@ -51,17 +90,18 @@ export default function LiveRunPanel({
}
useEffect(() => {
- let live = true;
+ let alive = true;
call("intro").then(({ body }) => {
- if (!live) return;
+ if (!alive) return;
const intro = body as Intro;
setItems([{ type: "msg", role: "agent", text: intro.greeting }]);
setSuggestions(intro.suggestions ?? []);
setAuthorized(intro.authorized);
setBalance(intro.balance);
+ setLive(!!intro.live);
});
return () => {
- live = false;
+ alive = false;
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [slug]);
@@ -70,6 +110,24 @@ export default function LiveRunPanel({
logRef.current?.scrollTo({ top: logRef.current.scrollHeight });
}, [items]);
+ function connect() {
+ const url = `${APP_URL}/auth/cli?callback_url=${encodeURIComponent(
+ cleanCallbackUrl(),
+ )}&key_name=${encodeURIComponent("Nevermined Tutorials")}`;
+ window.location.href = url;
+ }
+
+ function disconnect() {
+ try {
+ localStorage.removeItem(KEY_STORAGE);
+ } catch {
+ /* ignore */
+ }
+ setApiKey(null);
+ setAuthorized(false);
+ setItems((x) => [...x, { type: "notice", text: "Disconnected — your Nevermined key was removed from this browser." }]);
+ }
+
async function ask(text: string) {
const message = text.trim();
if (!message || busy) return;
@@ -77,7 +135,9 @@ export default function LiveRunPanel({
setItems((x) => [...x, { type: "msg", role: "user", text: message }]);
try {
const { status, body } = await call("ask", message);
- if (status === 402 && body.kind === "payment_required") {
+ if (status === 401 && body.kind === "not_connected") {
+ setItems((x) => [...x, { type: "notice", text: "Connect with Nevermined first to make paid requests." }]);
+ } else if (status === 402 && body.kind === "payment_required") {
setItems((x) => [...x, { type: "pay", credits: body.credits, pending: message }]);
} else if (status === 402 && body.kind === "insufficient") {
setBalance(body.balance);
@@ -95,7 +155,10 @@ export default function LiveRunPanel({
{ type: "msg", role: "agent", text: body.answer, tag: "paid" },
]);
} else {
- setItems((x) => [...x, { type: "settle", text: "the agent returned an error", error: true }]);
+ setItems((x) => [
+ ...x,
+ { type: "settle", text: body.error || "the agent returned an error", error: true },
+ ]);
}
} catch {
setItems((x) => [
@@ -124,16 +187,27 @@ export default function LiveRunPanel({
async function reset() {
await call("reset");
setAuthorized(false);
- setBalance(100);
- setItems((x) => [...x, { type: "notice", text: "Card delegation reset · balance back to 100." }]);
+ setBalance(live ? balance : 100);
+ setItems((x) => [...x, { type: "notice", text: "Delegation reset." }]);
}
+ // Live tutorial, not yet connected → show the Connect gate instead of the input.
+ const needsConnect = live && !apiKey;
+
return (
<>
{title}
+ {live && apiKey ? (
+
+ connected{" "}
+
+ disconnect
+
+
+ ) : null}
{balance !== null ? (
balance {balance}
@@ -166,7 +240,7 @@ export default function LiveRunPanel({
402 Payment Required
- This capability costs {it.credits} credit(s). Authorize a card delegation once and
+ This capability costs {it.credits} credit(s). Authorize a spending delegation once and
the agent pays per call — you're not asked again this session.
authorize(it.pending, i)}
disabled={busy || it.resolved}
>
- {it.resolved ? "Authorized" : "Authorize with card"}
+ {it.resolved ? "Authorized" : "Authorize delegation"}
{!it.resolved ? : null}
@@ -196,40 +270,61 @@ export default function LiveRunPanel({
})}
- {suggestions.length > 0 && items.length <= 1 ? (
-
- {suggestions.map((s) => (
-
ask(s)} disabled={busy}>
- {s}
-
- ))}
+ {needsConnect ? (
+
+
+ This tutorial makes real x402 / MPP requests to a live sandbox agent. Connect your
+ Nevermined account to get a sandbox API key — you'll be sent to the Nevermined App to log
+ in and returned here automatically.
+
+
+ Connect with Nevermined
+
- ) : null}
-
-
+ ) : (
+ <>
+ {suggestions.length > 0 && items.length <= 1 ? (
+
+ {suggestions.map((s) => (
+ ask(s)} disabled={busy}>
+ {s}
+
+ ))}
+
+ ) : null}
+
+
+ >
+ )}
- {authorized ? (
+ {live ? (
+ apiKey ? (
+ <>Live agent — real x402/MPP payments on Nevermined sandbox, paid with your connected key. >
+ ) : (
+ <>Live agent — connect once to pay real x402/MPP requests on Nevermined sandbox. >
+ )
+ ) : authorized ? (
<>
Sandbox agent — real payment round-trips and a real per-session credit balance, no real money.{" "}
diff --git a/showcase/lib/live-agent.mjs b/showcase/lib/live-agent.mjs
index 02dcff97..d3814432 100644
--- a/showcase/lib/live-agent.mjs
+++ b/showcase/lib/live-agent.mjs
@@ -1,17 +1,24 @@
// Live buyer behind the "see it run" panels — the REAL counterpart to demo-agent.mjs.
// It speaks the same response contract the panel expects ({status, body, state}), but performs
-// genuine x402 / MPP purchases against a deployed weather agent, paying with a sandbox account
-// held server-side (NVM_API_KEY never reaches the browser). Enabled per-slug only when the env is
-// present; otherwise the route falls back to the pure simulator.
+// genuine x402 / MPP purchases against a deployed weather agent.
//
-// ponytail: one shared delegation + a per-session credit counter — enough for a demo. Per-viewer
-// delegations / real on-chain balance readback if this ever needs to bill distinct visitors.
+// The buyer identity is the VIEWER's own Nevermined API key: the panel obtains it via the
+// "Connect with Nevermined" flow, stores it in localStorage, and sends it on each request. The key
+// only travels to this same-origin API route (never cross-origin) and is used server-side to mint
+// tokens on the viewer's behalf. A shared NVM_API_KEY env var is a dev fallback when no per-user
+// key is supplied.
+//
+// ponytail: per-key Payments + one delegation cached per key — enough for a demo. Real on-chain
+// balance readback / per-viewer credit accounting later if needed.
import { Payments } from "@nevermined-io/payments";
import { X402_HEADERS } from "@nevermined-io/payments/express";
const AGENT_URL = process.env.WEATHER_AGENT_URL || "";
-const NVM_API_KEY = process.env.NVM_API_KEY || "";
+// Shared-key fallback is DEV-ONLY and off unless explicitly enabled. In production it stays empty,
+// so a request with no per-user key cannot spend the shared account (the cookie is UX-only and
+// unsigned — it must never gate real spend). Every real purchase uses the VIEWER's own key.
+const ENV_KEY = process.env.ALLOW_SHARED_KEY_DEV === "1" ? process.env.NVM_API_KEY || "" : "";
const START_BALANCE = 10;
// slug → how to buy from it. Add a row to wire another tutorial to the live agent.
@@ -38,28 +45,36 @@ const LIVE = {
},
};
+// A slug is live-capable when the agent URL + a plan id are configured. Whether a given REQUEST
+// runs live also needs a key (per-user or the env fallback) — see resolveKey / liveRespond.
export function isLiveSlug(slug) {
- return !!(AGENT_URL && NVM_API_KEY && LIVE[slug] && LIVE[slug].planId);
+ return !!(AGENT_URL && LIVE[slug] && LIVE[slug].planId);
+}
+export function hasEnvKey() {
+ return !!ENV_KEY;
+}
+function resolveKey(reqApiKey) {
+ return (reqApiKey && String(reqApiKey).trim()) || ENV_KEY;
}
-// ── lazy singletons ─────────────────────────────────────────────────────────
-let _payments;
-function payments() {
- if (!_payments) _payments = Payments.getInstance({ nvmApiKey: NVM_API_KEY });
- return _payments;
+// ── per-key singletons ────────────────────────────────────────────────────────
+const _payments = new Map(); // key -> Payments
+const _delegation = new Map(); // key -> delegationId
+function paymentsFor(key) {
+ if (!_payments.has(key)) _payments.set(key, Payments.getInstance({ nvmApiKey: key }));
+ return _payments.get(key);
}
-let _delegationId;
-async function delegationId() {
- if (!_delegationId) {
- const { delegationId: id } = await payments().delegation.createDelegation({
+async function delegationFor(key) {
+ if (!_delegation.has(key)) {
+ const { delegationId } = await paymentsFor(key).delegation.createDelegation({
provider: "erc4337",
spendingLimitCents: 10000,
durationSecs: 604800,
currency: "usdc",
});
- _delegationId = id;
+ _delegation.set(key, delegationId);
}
- return _delegationId;
+ return _delegation.get(key);
}
function cityOf(message) {
@@ -80,9 +95,9 @@ function formatWeather(w) {
const freshState = () => ({ authorized: false, balance: START_BALANCE });
-async function buyX402(cfg, city) {
- const { accessToken } = await payments().x402.getX402AccessToken(cfg.planId, undefined, {
- delegationConfig: { delegationId: await delegationId() },
+async function buyX402(key, cfg, city) {
+ const { accessToken } = await paymentsFor(key).x402.getX402AccessToken(cfg.planId, undefined, {
+ delegationConfig: { delegationId: await delegationFor(key) },
});
const res = await fetch(`${AGENT_URL}${cfg.route}`, {
method: "POST",
@@ -91,19 +106,18 @@ async function buyX402(cfg, city) {
});
if (res.status !== 200) throw new Error(`agent returned ${res.status}: ${await res.text()}`);
const settled = !!res.headers.get(X402_HEADERS.PAYMENT_RESPONSE);
- return { weather: await res.json(), settled, note: settled ? "settled in one x402 round-trip" : "served (settlement async)" };
+ return { weather: await res.json(), note: settled ? "settled in one x402 round-trip" : "served (settlement async)" };
}
-async function buyMpp(cfg, city) {
- const { response, paid, settled, credentialsPresented } = await payments().mpp.fetch(
+async function buyMpp(key, cfg, city) {
+ const { response, paid, credentialsPresented } = await paymentsFor(key).mpp.fetch(
`${AGENT_URL}${cfg.route}`,
{ method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ city }) },
- { delegationConfig: { delegationId: await delegationId() }, planId: cfg.planId },
+ { delegationConfig: { delegationId: await delegationFor(key) }, planId: cfg.planId },
);
if (response.status !== 200) throw new Error(`agent returned ${response.status}`);
return {
weather: await response.json(),
- settled: !!settled,
note: paid
? "settled via MPP credential"
: `MPP handshake served (credential presented=${credentialsPresented}); settlement pending on this backend`,
@@ -112,22 +126,26 @@ async function buyMpp(cfg, city) {
/**
* Real buyer, mirroring demo-agent.mjs's respond() contract.
+ * req: { slug, action, message?, apiKey? }
* @returns {Promise<{status:number, body:object, state:{authorized:boolean,balance:number}}>}
*/
export async function liveRespond(state, req) {
const s = state && typeof state.balance === "number" ? { ...state } : freshState();
const cfg = LIVE[req.slug];
if (!cfg) return { status: 404, body: { error: "unknown live agent" }, state: s };
+ const key = resolveKey(req.apiKey);
if (req.action === "intro") {
return {
status: 200,
body: {
+ live: true, // tells the panel to show the "Connect with Nevermined" flow
greeting: cfg.greeting,
suggestions: cfg.suggestions,
pill: cfg.pill,
credits: cfg.credits,
hasFreeTier: false,
+ connected: !!key,
authorized: s.authorized,
balance: s.balance,
},
@@ -135,14 +153,18 @@ export async function liveRespond(state, req) {
};
}
+ // Every action past intro needs a buyer key.
+ if (!key) {
+ return { status: 401, body: { kind: "not_connected", error: "Connect with Nevermined to get an API key first." }, state: s };
+ }
+
if (req.action === "authorize") {
try {
- await delegationId(); // create the real erc4337 delegation now
+ await delegationFor(key); // create the real erc4337 delegation for this key now
} catch (e) {
return { status: 502, body: { error: `could not create delegation: ${e.message}` }, state: s };
}
- const next = { authorized: true, balance: s.balance };
- return { status: 200, body: { ok: true, method: "erc4337 delegation", balance: next.balance }, state: next };
+ return { status: 200, body: { ok: true, method: "erc4337 delegation", balance: s.balance }, state: { authorized: true, balance: s.balance } };
}
if (req.action === "reset") {
@@ -160,7 +182,7 @@ export async function liveRespond(state, req) {
}
const city = cityOf(message);
try {
- const { weather, note } = cfg.protocol === "mpp" ? await buyMpp(cfg, city) : await buyX402(cfg, city);
+ const { weather, note } = cfg.protocol === "mpp" ? await buyMpp(key, cfg, city) : await buyX402(key, cfg, city);
const next = { authorized: true, balance: s.balance - cfg.credits };
return {
status: 200,
From 0d51841bca0f26b5464f23b9cc943c865dd18082 Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 19:03:05 +0200
Subject: [PATCH 16/24] style(showcase): compact 402 row, 'Authorize' label,
in-flight spinners
---
showcase/app/globals.css | 14 +++++++++++++
showcase/components/LiveRunPanel.tsx | 31 +++++++++++++++-------------
2 files changed, 31 insertions(+), 14 deletions(-)
diff --git a/showcase/app/globals.css b/showcase/app/globals.css
index c329739f..efb66d82 100644
--- a/showcase/app/globals.css
+++ b/showcase/app/globals.css
@@ -349,8 +349,22 @@ table.dt tr.total td:last-child { color: var(--paid); }
.settle.err { border-color: var(--danger); background: var(--danger-wash); }
.settle.err .stamp { background: var(--danger); }
.settle.err .txt { color: var(--danger-ink); }
+/* compact 402 row — same footprint as .settle (the PAID line), not the big paycard */
+.payline { align-self: stretch; display: flex; align-items: center; gap: 11px; border: 1.5px solid var(--pay);
+ background: var(--pay-wash); border-radius: 12px; padding: 12px 14px; }
+.payline .stamp { font-family: var(--mono); font-weight: 500; font-size: 12px; color: #fff; background: var(--pay);
+ padding: 4px 9px; border-radius: 6px; flex: none; }
+.payline .txt { font-family: var(--mono); font-size: 12.5px; color: var(--ink-soft); }
+.cta.sm { margin-left: auto; padding: 6px 12px; font-size: 12.5px; border-radius: 9px; flex: none; }
.notice { align-self: stretch; font-size: 12.5px; color: var(--muted); border: 1px solid var(--border);
background: var(--bg); border-radius: 10px; padding: 10px 13px; }
+/* spinner for in-flight requests */
+.spinner { display: inline-block; width: 13px; height: 13px; border: 2px solid var(--border-strong);
+ border-top-color: var(--accent-ink); border-radius: 50%; animation: spin 0.7s linear infinite; }
+.cta .spinner, .rp-input button .spinner { border-color: rgba(0,0,0,0.25); border-top-color: currentColor; }
+.working { align-self: flex-start; display: flex; align-items: center; gap: 9px; color: var(--muted); font-size: 13px;
+ padding: 4px 2px; }
+@keyframes spin { to { transform: rotate(360deg); } }
.rp-suggest { display: flex; flex-wrap: wrap; gap: 8px; padding: 0 18px 14px; background: var(--bg-tint); }
.rp-suggest .schip { cursor: pointer; background: var(--bg); }
diff --git a/showcase/components/LiveRunPanel.tsx b/showcase/components/LiveRunPanel.tsx
index 1ab4a855..b40937ac 100644
--- a/showcase/components/LiveRunPanel.tsx
+++ b/showcase/components/LiveRunPanel.tsx
@@ -56,6 +56,7 @@ export default function LiveRunPanel({
const [busy, setBusy] = useState(false);
const [live, setLive] = useState(false);
const [apiKey, setApiKey] = useState(null);
+ const [connecting, setConnecting] = useState(false);
const logRef = useRef(null);
// On mount: capture an nvm_api_key returned by the Nevermined App callback (query string),
@@ -111,6 +112,7 @@ export default function LiveRunPanel({
}, [items]);
function connect() {
+ setConnecting(true);
const url = `${APP_URL}/auth/cli?callback_url=${encodeURIComponent(
cleanCallbackUrl(),
)}&key_name=${encodeURIComponent("Nevermined Tutorials")}`;
@@ -235,21 +237,16 @@ export default function LiveRunPanel({
}
if (it.type === "pay") {
return (
-
-
- 402 Payment Required
-
-
- This capability costs {it.credits} credit(s). Authorize a spending delegation once and
- the agent pays per call — you're not asked again this session.
-
+
+
402
+
Payment required · {it.credits} credit(s)
authorize(it.pending, i)}
disabled={busy || it.resolved}
>
- {it.resolved ? "Authorized" : "Authorize delegation"}
- {!it.resolved ? : null}
+ {it.resolved ? "Authorized" : "Authorize"}
+ {!it.resolved ? (busy ? : ) : null}
);
@@ -268,6 +265,11 @@ export default function LiveRunPanel({
);
})}
+ {busy ? (
+
+ contacting the agent…
+
+ ) : null}
{needsConnect ? (
@@ -277,8 +279,9 @@ export default function LiveRunPanel({
Nevermined account to get a sandbox API key — you'll be sent to the Nevermined App to log
in and returned here automatically.
-
- Connect with Nevermined
+
+ {connecting ? "Redirecting to Nevermined…" : "Connect with Nevermined"}
+ {connecting ? : }
) : (
@@ -311,7 +314,7 @@ export default function LiveRunPanel({
aria-label="Message the agent"
/>
- Send
+ {busy ? : "Send"}
>
From bc7835dce64c0984968bb11f9893b7ae51331112 Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 19:10:17 +0200
Subject: [PATCH 17/24] feat(showcase): signal 'Connect' button (Nevermined
ribbon) + server code links in live panel
---
showcase/app/globals.css | 25 ++++++++++++++
showcase/components/LiveRunPanel.tsx | 50 ++++++++++++++++++++++++++--
showcase/lib/live-agent.mjs | 9 +++++
3 files changed, 81 insertions(+), 3 deletions(-)
diff --git a/showcase/app/globals.css b/showcase/app/globals.css
index efb66d82..cd5022c1 100644
--- a/showcase/app/globals.css
+++ b/showcase/app/globals.css
@@ -366,6 +366,28 @@ table.dt tr.total td:last-child { color: var(--paid); }
padding: 4px 2px; }
@keyframes spin { to { transform: rotate(360deg); } }
+/* "Connect" button — signal variant, from the Nevermined Button Studio design
+ (artifact f119d119). Ribbon logo + pulsing signal rings on hover. Vars are --nc-*
+ prefixed so they don't collide with the showcase's own --accent/--lime. */
+.nvm-connect { --nc-brand: #0d3f48; --nc-brand-ink: #ffffff; --nc-accent: #4ac6bf;
+ position: relative; isolation: isolate; z-index: 0; display: inline-flex; align-items: center; gap: 11px;
+ padding: 13px 22px; border: 0; border-radius: 12px; background: var(--nc-brand); color: var(--nc-brand-ink);
+ font-weight: 600; font-size: 15px; line-height: 1; cursor: pointer; }
+.nvm-connect:disabled { opacity: 0.7; cursor: default; }
+.nvm-connect:focus-visible { outline: 2px solid var(--nc-accent); outline-offset: 3px; }
+.nvm-connect .ico { position: relative; display: grid; place-items: center; color: var(--nc-accent); }
+.nvm-connect .ribbon { height: 17px; width: auto; display: block; }
+.nvm-connect .ribbon path { fill: currentColor; }
+.nvm-connect .lbl { position: relative; z-index: 1; }
+.nvm-connect .ico::before, .nvm-connect .ico::after { content: ""; position: absolute; top: 50%; left: 50%;
+ width: 32px; height: 32px; margin: -16px 0 0 -16px; border-radius: 50%; border: 2px solid var(--nc-accent);
+ opacity: 0; z-index: -1; }
+.nvm-connect:hover .ico::before, .nvm-connect:focus-visible .ico::before { animation: sig 1.4s ease-out infinite; }
+.nvm-connect:hover .ico::after, .nvm-connect:focus-visible .ico::after { animation: sig 1.4s ease-out 0.7s infinite; }
+.nvm-connect:hover .ico, .nvm-connect:focus-visible .ico {
+ filter: drop-shadow(0 0 6px color-mix(in srgb, var(--nc-accent) 75%, transparent)); }
+@keyframes sig { from { transform: scale(0.45); opacity: 0.95; } to { transform: scale(2.6); opacity: 0; } }
+
.rp-suggest { display: flex; flex-wrap: wrap; gap: 8px; padding: 0 18px 14px; background: var(--bg-tint); }
.rp-suggest .schip { cursor: pointer; background: var(--bg); }
.rp-suggest .schip:hover { border-color: var(--accent); color: var(--accent-ink); }
@@ -378,6 +400,9 @@ table.dt tr.total td:last-child { color: var(--paid); }
font-weight: 700; font-size: 13.5px; cursor: pointer; }
.rp-input button:disabled { opacity: 0.5; cursor: default; }
.runnote { font-size: 12.5px; color: var(--faint); margin-top: 14px; }
+.codelinks { font-size: 12px; color: var(--faint); margin: 12px 0 0; }
+.codelinks a { color: var(--accent-ink); text-decoration: underline; text-underline-offset: 2px; }
+.runnote a { color: var(--accent-ink); text-decoration: underline; text-underline-offset: 2px; }
.linkbtn { background: none; border: none; padding: 0; font: inherit; color: var(--accent-ink); cursor: pointer;
text-decoration: underline; }
.linkbtn:hover { color: var(--accent); }
diff --git a/showcase/components/LiveRunPanel.tsx b/showcase/components/LiveRunPanel.tsx
index b40937ac..b2645e30 100644
--- a/showcase/components/LiveRunPanel.tsx
+++ b/showcase/components/LiveRunPanel.tsx
@@ -10,12 +10,18 @@ type Item =
| { type: "settle"; text: string; error?: boolean }
| { type: "notice"; text: string };
+interface CodeLink {
+ label: string;
+ url: string;
+}
+
interface Intro {
greeting: string;
suggestions: string[];
authorized: boolean;
balance: number;
live?: boolean;
+ code?: CodeLink[];
}
// The Nevermined App host for the "Connect" (CLI-auth) flow. Sandbox vs live is chosen inside the
@@ -57,6 +63,7 @@ export default function LiveRunPanel({
const [live, setLive] = useState(false);
const [apiKey, setApiKey] = useState(null);
const [connecting, setConnecting] = useState(false);
+ const [codeLinks, setCodeLinks] = useState([]);
const logRef = useRef(null);
// On mount: capture an nvm_api_key returned by the Nevermined App callback (query string),
@@ -100,6 +107,7 @@ export default function LiveRunPanel({
setAuthorized(intro.authorized);
setBalance(intro.balance);
setLive(!!intro.live);
+ setCodeLinks(intro.code ?? []);
});
return () => {
alive = false;
@@ -279,10 +287,32 @@ export default function LiveRunPanel({
Nevermined account to get a sandbox API key — you'll be sent to the Nevermined App to log
in and returned here automatically.
-
- {connecting ? "Redirecting to Nevermined…" : "Connect with Nevermined"}
- {connecting ? : }
+
+
+ {connecting ? (
+
+ ) : (
+
+
+
+
+ )}
+
+ {connecting ? "Redirecting…" : "Connect"}
+ {codeLinks.length > 0 ? (
+
+ Server code:{" "}
+ {codeLinks.map((c, i) => (
+
+ {i > 0 ? " · " : ""}
+
+ {c.label}
+
+
+ ))}
+
+ ) : null}
) : (
<>
@@ -338,6 +368,20 @@ export default function LiveRunPanel({
) : (
"Sandbox agent — real payment round-trips (402 → authorize → settle) with a per-session credit balance, no external service and no real money. "
)}
+ {live && apiKey && codeLinks.length > 0 ? (
+ <>
+ Server code:{" "}
+ {codeLinks.map((c, i) => (
+
+ {i > 0 ? " · " : ""}
+
+ {c.label}
+
+
+ ))}
+ {". "}
+ >
+ ) : null}
{run.note}
>
diff --git a/showcase/lib/live-agent.mjs b/showcase/lib/live-agent.mjs
index d3814432..73d2a4a1 100644
--- a/showcase/lib/live-agent.mjs
+++ b/showcase/lib/live-agent.mjs
@@ -21,6 +21,14 @@ const AGENT_URL = process.env.WEATHER_AGENT_URL || "";
const ENV_KEY = process.env.ALLOW_SHARED_KEY_DEV === "1" ? process.env.NVM_API_KEY || "" : "";
const START_BALANCE = 10;
+// The deployed weather agent's source (the "server" behind these live demos). Both live slugs
+// hit the same TS agent (MPP is TS-only), so they share these links.
+const AGENT_CODE = [
+ { label: "agent server", url: "https://github.com/nevermined-io/tutorials/tree/main/http-simple-agent-ts" },
+ { label: "agent.ts", url: "https://github.com/nevermined-io/tutorials/blob/main/http-simple-agent-ts/src/agent.ts" },
+ { label: "weather.service.ts", url: "https://github.com/nevermined-io/tutorials/blob/main/http-simple-agent-ts/src/services/weather.service.ts" },
+];
+
// slug → how to buy from it. Add a row to wire another tutorial to the live agent.
const LIVE = {
"http-simple-agent-ts": {
@@ -148,6 +156,7 @@ export async function liveRespond(state, req) {
connected: !!key,
authorized: s.authorized,
balance: s.balance,
+ code: AGENT_CODE, // links to the deployed agent (server) source
},
state: s,
};
From 08f0f15022f36bb87624038b8d82b595bb5df24f Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 19:10:17 +0200
Subject: [PATCH 18/24] fix(showcase): suppress benign Prism/extension
hydration warning on code blocks
---
showcase/components/CodeBlock.tsx | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/showcase/components/CodeBlock.tsx b/showcase/components/CodeBlock.tsx
index dc58edfb..aeccf080 100644
--- a/showcase/components/CodeBlock.tsx
+++ b/showcase/components/CodeBlock.tsx
@@ -58,7 +58,10 @@ export default function CodeBlock({
{copied ? : }
{copied ? "Copied" : "Copy"}
-
+ {/* suppressHydrationWarning: Prism (and some browser extensions) mutate the
+ highlighted / after SSR — adding a language class / tabindex — which
+ is a benign attribute-only diff React would otherwise warn about. */}
+
{html ? (
// Safe: `code` is our own static content (content/tutorials.ts), and
// Prism.highlight HTML-escapes its input before emitting token spans —
@@ -66,6 +69,7 @@ export default function CodeBlock({
) : (
{code}
From b3eb1c538d839e8f54a482e82cc661d07e9c66fa Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 19:37:45 +0200
Subject: [PATCH 19/24] feat(showcase): 3.1 Client / 3.2 Agent split + MPP
category with a pay-as-you-go MPP tutorial
- Under the hood: optional grouped code samples rendered as numbered sub-sections; http-simple-agent-ts now shows real Client + Agent (server) code, keyless dual-protocol.
- New MPP protocol category + 'Pay per forecast over MPP' tutorial (live, /weather/payg, PAYG pricing).
- live buyer: mpp-weather-payg slug, parses forecast days, formats multi-day forecasts; py tutorial reverts to simulator.
---
showcase/app/globals.css | 7 ++
showcase/app/t/[slug]/page.tsx | 26 ++++-
showcase/components/AppShell.tsx | 1 +
showcase/content/tutorials.ts | 170 ++++++++++++++++++++++++++++---
showcase/lib/live-agent.mjs | 46 ++++++---
showcase/lib/types.ts | 14 ++-
6 files changed, 230 insertions(+), 34 deletions(-)
diff --git a/showcase/app/globals.css b/showcase/app/globals.css
index cd5022c1..e1ce1190 100644
--- a/showcase/app/globals.css
+++ b/showcase/app/globals.css
@@ -254,6 +254,13 @@ button { font-family: inherit; }
width: 22px; height: 22px; border-radius: 6px; display: grid; place-items: center; }
.block .lead { font-family: var(--disp); font-size: 24px; font-weight: 700; letter-spacing: -0.02em; line-height: 1.22;
margin-bottom: 14px; color: var(--ink); max-width: 22ch; }
+/* numbered sub-sections inside a block (e.g. 3.1 Client, 3.2 Agent) */
+.subblock { margin-top: 24px; }
+.subblock .h3 { font-family: var(--disp); font-weight: 800; font-size: 12px; color: var(--ink-soft);
+ letter-spacing: 0.02em; margin: 0 0 12px; display: flex; align-items: center; gap: 9px; }
+.subblock .h3 .num { font-family: var(--mono); font-weight: 500; color: var(--ink); background: var(--bg-tint);
+ border: 1px solid var(--border); font-size: 10.5px; padding: 3px 7px; border-radius: 5px; }
+.subblock .sublead { color: var(--ink-soft); font-size: 14px; margin: 0 0 12px; }
.block p { color: var(--ink-soft); font-size: 15.5px; }
.block p + p { margin-top: 12px; }
ul.learn { list-style: none; padding: 0; margin: 14px 0 0; display: flex; flex-direction: column; gap: 11px; }
diff --git a/showcase/app/t/[slug]/page.tsx b/showcase/app/t/[slug]/page.tsx
index ed579461..3519adfb 100644
--- a/showcase/app/t/[slug]/page.tsx
+++ b/showcase/app/t/[slug]/page.tsx
@@ -132,11 +132,27 @@ export default async function TutorialPage({ params }: { params: Promise<{ slug:
))}
- {t.tech.samples.map((s, i) => (
-
-
-
- ))}
+ {t.tech.groups?.length ? (
+ t.tech.groups.map((g, gi) => (
+
+
+ 3.{gi + 1} {g.title}
+
+ {g.lead ?
{g.lead}
: null}
+ {g.samples.map((s, i) => (
+
+
+
+ ))}
+
+ ))
+ ) : (
+ t.tech.samples.map((s, i) => (
+
+
+
+ ))
+ )}
{t.tech.files?.length ? (
diff --git a/showcase/components/AppShell.tsx b/showcase/components/AppShell.tsx
index 5257aafa..840facce 100644
--- a/showcase/components/AppShell.tsx
+++ b/showcase/components/AppShell.tsx
@@ -44,6 +44,7 @@ export interface NavGroup {
const GLYPH: Record = {
catalog: ,
x402: ,
+ mpp: ,
mcp: ,
langchain: ,
};
diff --git a/showcase/content/tutorials.ts b/showcase/content/tutorials.ts
index 8c2e38df..f5d190ac 100644
--- a/showcase/content/tutorials.ts
+++ b/showcase/content/tutorials.ts
@@ -125,25 +125,62 @@ export const tutorials: Tutorial[] = [
],
},
tech: {
- stack: ["Express", "TypeScript", "@nevermined-io/payments/express", "OpenAI"],
- samples: [
+ stack: ["Express", "TypeScript", "@nevermined-io/payments/express", "x402 + MPP", "Open-Meteo"],
+ samples: [],
+ groups: [
+ {
+ title: "Client",
+ lead: "Create a delegation once, mint an x402 token, and call the paid route.",
+ samples: [
+ {
+ caption: "buy the weather over x402",
+ lang: "typescript",
+ code: `// one delegation backs the buyer (erc4337)
+const { delegationId } = await payments.delegation.createDelegation({
+ provider: 'erc4337', spendingLimitCents: 10000, durationSecs: 604800, currency: 'usdc',
+})
+
+// mint an x402 access token for the plan, then call the route with it
+const { accessToken } = await payments.x402.getX402AccessToken(
+ PLAN_ID, undefined, { delegationConfig: { delegationId } },
+)
+const res = await fetch(AGENT_URL + '/weather/credits', {
+ method: 'POST',
+ headers: { 'content-type': 'application/json', [X402_HEADERS.PAYMENT_SIGNATURE]: accessToken },
+ body: JSON.stringify({ city: 'Lisbon' }),
+})
+// → 200 + weather, plus a 'payment-response' settlement receipt`,
+ },
+ ],
+ },
{
- caption: "one line gates the route",
- lang: "typescript",
- code: `import { paymentMiddleware } from '@nevermined-io/payments/express'
+ title: "Agent",
+ lead: "One paymentMiddleware, three plans, both protocols — mpp: true makes every 402 advertise x402 AND MPP, so either buyer works against the same URL.",
+ samples: [
+ {
+ caption: "three dual-protocol routes gate the agent",
+ lang: "typescript",
+ code: `import { paymentMiddleware } from '@nevermined-io/payments/express'
app.use(paymentMiddleware(payments, {
- 'POST /ask': { planId: PLAN_ID, credits: 1 }
-}))`,
+ 'POST /weather/credits': { planId: PLAN_ID_CREDITS, credits: 1, mpp: true },
+ 'POST /weather/subscription': { planId: PLAN_ID_TIME, credits: 1, mpp: true },
+ 'POST /weather/payg': { planId: PLAN_ID_PAYG, credits: (req) => priceForRequest(req.body), mpp: true },
+}))
+
+app.post('/weather/credits', async (req, res) => {
+ const { city } = parseWeatherRequest(req.body) // 400 on bad input
+ res.json(await getTodayWeather(city)) // keyless Open-Meteo
+})`,
+ },
+ ],
},
],
files: [
- { path: "src/agent.ts", desc: "Express server with a payment-protected /ask endpoint" },
- {
- path: "src/agent-observability.ts",
- desc: "same agent, with Nevermined observability tracking OpenAI cost",
- },
- { path: "src/client.ts", desc: "demo client showing the full x402 payment flow" },
+ { path: "src/agent.ts", desc: "Express agent — three dual-protocol (x402 + MPP) weather routes" },
+ { path: "src/services/weather.service.ts", desc: "keyless weather from Open-Meteo" },
+ { path: "scripts/smoke.ts", desc: "buyer: x402 + MPP round-trips against the agent" },
+ { path: "scripts/register-plans.ts", desc: "registers the credits / time / pay-as-you-go plans" },
],
},
run: {
@@ -778,6 +815,112 @@ weather.ensureCity # prompt — guide the LLM to request weather`,
],
},
},
+
+ // ─────────────────────────────── MPP — pay-as-you-go forecast ───────────────
+ {
+ slug: "mpp-weather-payg",
+ title: "Pay per forecast over MPP",
+ tagline:
+ "Buy a weather forecast with the Machine Payments Protocol — a challenge→credential handshake, priced pay-as-you-go (1 credit for today, up to 7 for a week).",
+ protocol: "mpp",
+ language: "ts",
+ tier: "live",
+ repoPath: "http-simple-agent-ts/",
+ learn: {
+ lead: "Pay per forecast with the Machine Payments Protocol.",
+ bullets: [
+ "MPP: a challenge→credential handshake over the same plans, delegations and credits as x402",
+ "Pay-as-you-go pricing — the agent's credits function charges 1 credit for today, up to 7 for a week",
+ "payments.mpp.fetch runs the whole round-trip and returns the Payment-Receipt",
+ "The same route also serves x402 buyers — mpp: true advertises both protocols",
+ ],
+ },
+ how: {
+ paragraphs: [
+ "The buyer POSTs to /weather/payg with no credential and gets 402 with a WWW-Authenticate: Payment challenge — the price (credits) is sealed into the challenge at that moment. payments.mpp.fetch mints an MPP credential for your delegation, retries with Authorization: Payment, and the agent verifies, serves the forecast, and settles — returning a Payment-Receipt.",
+ ],
+ flow: [
+ { label: "POST /weather/payg", sub: "no credential" },
+ { label: "402", sub: "WWW-Authenticate: Payment" },
+ { label: "credential + retry", sub: "Authorization: Payment", emphasis: true },
+ { label: "200", sub: "Payment-Receipt" },
+ ],
+ },
+ tech: {
+ stack: ["MPP", "TypeScript", "@nevermined-io/payments", "pay-as-you-go", "Open-Meteo"],
+ samples: [],
+ groups: [
+ {
+ title: "Client",
+ lead: "payments.mpp.fetch runs the full challenge→credential handshake in one call.",
+ samples: [
+ {
+ caption: "pay a PAYG forecast over MPP",
+ lang: "typescript",
+ code: `// a delegation backs the buyer (erc4337), same as x402
+const { delegationId } = await payments.delegation.createDelegation({
+ provider: 'erc4337', spendingLimitCents: 10000, durationSecs: 604800, currency: 'usdc',
+})
+
+// one call: unpaid → 402 challenge → mint credential → retry → 200 + receipt
+const { response, receipt, paid } = await payments.mpp.fetch(
+ AGENT_URL + '/weather/payg',
+ { method: 'POST', headers: { 'content-type': 'application/json' },
+ body: JSON.stringify({ city: 'Berlin', days: 5 }) },
+ { delegationConfig: { delegationId }, planId: PLAN_ID_PAYG, maxCredits: 7 },
+)
+const forecast = await response.json() // 5-day forecast`,
+ },
+ ],
+ },
+ {
+ title: "Agent",
+ lead: "The credits function prices each request; mpp: true accepts the MPP handshake on the same route.",
+ samples: [
+ {
+ caption: "pay-as-you-go route, dual-protocol",
+ lang: "typescript",
+ code: `import { paymentMiddleware } from '@nevermined-io/payments/express'
+
+app.use(paymentMiddleware(payments, {
+ 'POST /weather/payg': {
+ planId: PLAN_ID_PAYG,
+ credits: (req) => priceForRequest(req.body), // 1 for today, up to 7 for a week
+ mpp: true,
+ },
+}))
+
+app.post('/weather/payg', async (req, res) => {
+ const { city, days } = parseWeatherRequest(req.body)
+ res.json(days && days > 1 ? await getForecast(city, days) : await getTodayWeather(city))
+})`,
+ },
+ ],
+ },
+ ],
+ files: [
+ { path: "src/agent.ts", desc: "the /weather/payg route — dynamic credits, mpp: true" },
+ { path: "src/pricing.ts", desc: "priceForRequest: 1 credit for today, up to 7 for a forecast" },
+ { path: "src/services/weather.service.ts", desc: "getForecast — keyless multi-day weather from Open-Meteo" },
+ { path: "scripts/smoke.ts", desc: "buyer: the MPP round-trip against the agent" },
+ ],
+ },
+ run: {
+ kind: "live",
+ present: "transcript",
+ paymentPill: "MPP · pay-as-you-go",
+ transcript: [
+ { t: "POST /weather/payg { city: 'Berlin', days: 5 }", kind: "req" },
+ { t: "← 402 WWW-Authenticate: Payment · 5 credits", kind: "r402" },
+ { t: " mint MPP credential for the delegation", kind: "dim" },
+ { t: "POST /weather/payg Authorization: Payment eyJ…", kind: "req" },
+ { t: " verify → serve → settle", kind: "dim" },
+ { t: "← 200 OK Payment-Receipt", kind: "r200" },
+ { t: "5 credits burned · 5-day forecast", kind: "settle" },
+ ],
+ note: "Connect your Nevermined sandbox account, then send a city — the buyer runs the real MPP handshake (payments.mpp.fetch) against the deployed agent's pay-as-you-go route.",
+ },
+ },
];
export function getTutorial(slug: string): Tutorial | undefined {
@@ -788,6 +931,7 @@ export function getTutorial(slug: string): Tutorial | undefined {
export const GROUP_ORDER: { label: string; protocol: Protocol }[] = [
{ label: "Catalog", protocol: "catalog" },
{ label: "x402 HTTP", protocol: "x402" },
+ { label: "MPP", protocol: "mpp" },
{ label: "MCP", protocol: "mcp" },
{ label: "LangChain", protocol: "langchain" },
];
diff --git a/showcase/lib/live-agent.mjs b/showcase/lib/live-agent.mjs
index 73d2a4a1..18ecdf03 100644
--- a/showcase/lib/live-agent.mjs
+++ b/showcase/lib/live-agent.mjs
@@ -41,15 +41,15 @@ const LIVE = {
"I'm a live weather agent. Ask for the weather in any city — each call is paid over x402 (1 credit) against the real Nevermined sandbox.",
suggestions: ["What's the weather in Lisbon?", "Weather in Tokyo"],
},
- "http-simple-agent-py": {
+ "mpp-weather-payg": {
protocol: "mpp",
- route: "/weather/credits",
- planId: process.env.PLAN_ID_CREDITS || "",
- credits: 1,
- pill: "MPP · sandbox",
+ route: "/weather/payg",
+ planId: process.env.PLAN_ID_PAYG || "",
+ credits: 1, // nominal; pay-as-you-go actually charges by requested days (1..7)
+ pill: "MPP · pay-as-you-go",
greeting:
- "I'm a live weather agent paid over MPP (Machine Payments Protocol). Ask for a city — the buyer runs the challenge→credential handshake against the real sandbox.",
- suggestions: ["What's the weather in Madrid?", "Weather in Berlin"],
+ "I'm a live weather agent paid over MPP (Machine Payments Protocol), priced pay-as-you-go. Ask for a city — add a number of days for a forecast (e.g. '5-day forecast in Berlin'). The buyer runs the challenge→credential handshake against the real sandbox.",
+ suggestions: ["5-day forecast in Berlin", "Weather in Madrid"],
},
};
@@ -92,9 +92,24 @@ function cityOf(message) {
return cap ? cap[1] : "Lisbon";
}
+// "5-day forecast" / "next 3 days" / "7 day" → the number of forecast days (pay-as-you-go).
+function daysOf(message) {
+ const m = message.match(/(\d+)\s*[- ]?\s*day/i);
+ return m ? Math.max(1, Math.min(7, parseInt(m[1], 10))) : undefined;
+}
+
function formatWeather(w) {
- const parts = [];
const place = w.country ? `${w.city}, ${w.country}` : w.city;
+ // multi-day forecast (pay-as-you-go /weather/payg with days > 1)
+ if (Array.isArray(w.days)) {
+ const lines = w.days.map((d) => {
+ const t = `${d.tmaxC ?? "?"}° / ${d.tminC ?? "?"}°C`;
+ return ` ${d.date}: ${t}${d.weatherText ? ", " + String(d.weatherText).toLowerCase() : ""}`;
+ });
+ return `${place} — ${w.days.length}-day forecast\n${lines.join("\n")}`;
+ }
+ // single-day current weather
+ const parts = [];
if (w.tmaxC != null || w.tminC != null) parts.push(`${w.tmaxC ?? "?"}° / ${w.tminC ?? "?"}°C`);
if (w.weatherText) parts.push(String(w.weatherText).toLowerCase());
if (w.precipitationMm != null) parts.push(`${w.precipitationMm}mm precip`);
@@ -103,25 +118,25 @@ function formatWeather(w) {
const freshState = () => ({ authorized: false, balance: START_BALANCE });
-async function buyX402(key, cfg, city) {
+async function buyX402(key, cfg, body) {
const { accessToken } = await paymentsFor(key).x402.getX402AccessToken(cfg.planId, undefined, {
delegationConfig: { delegationId: await delegationFor(key) },
});
const res = await fetch(`${AGENT_URL}${cfg.route}`, {
method: "POST",
headers: { "content-type": "application/json", [X402_HEADERS.PAYMENT_SIGNATURE]: accessToken },
- body: JSON.stringify({ city }),
+ body: JSON.stringify(body),
});
if (res.status !== 200) throw new Error(`agent returned ${res.status}: ${await res.text()}`);
const settled = !!res.headers.get(X402_HEADERS.PAYMENT_RESPONSE);
return { weather: await res.json(), note: settled ? "settled in one x402 round-trip" : "served (settlement async)" };
}
-async function buyMpp(key, cfg, city) {
+async function buyMpp(key, cfg, body) {
const { response, paid, credentialsPresented } = await paymentsFor(key).mpp.fetch(
`${AGENT_URL}${cfg.route}`,
- { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ city }) },
- { delegationConfig: { delegationId: await delegationFor(key) }, planId: cfg.planId },
+ { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body) },
+ { delegationConfig: { delegationId: await delegationFor(key) }, planId: cfg.planId, maxCredits: 7 },
);
if (response.status !== 200) throw new Error(`agent returned ${response.status}`);
return {
@@ -189,9 +204,10 @@ export async function liveRespond(state, req) {
if (s.balance < cfg.credits) {
return { status: 402, body: { kind: "insufficient", balance: s.balance }, state: s };
}
- const city = cityOf(message);
+ const days = daysOf(message);
+ const body = { city: cityOf(message), ...(days ? { days } : {}) };
try {
- const { weather, note } = cfg.protocol === "mpp" ? await buyMpp(key, cfg, city) : await buyX402(key, cfg, city);
+ const { weather, note } = cfg.protocol === "mpp" ? await buyMpp(key, cfg, body) : await buyX402(key, cfg, body);
const next = { authorized: true, balance: s.balance - cfg.credits };
return {
status: 200,
diff --git a/showcase/lib/types.ts b/showcase/lib/types.ts
index 26994ff0..6c49bb8b 100644
--- a/showcase/lib/types.ts
+++ b/showcase/lib/types.ts
@@ -1,7 +1,7 @@
// Normalized content model shared by every tutorial page.
// One shape for all tutorials → uniform pages out of wildly different READMEs.
-export type Protocol = "x402" | "mcp" | "langchain" | "catalog";
+export type Protocol = "x402" | "mpp" | "mcp" | "langchain" | "catalog";
export type Language = "ts" | "py" | "autonomous" | "agnostic";
export type Tier = "live" | "recap" | "discover";
@@ -42,10 +42,21 @@ export interface HowSection {
table?: DataTable;
}
+/** A titled group of code samples — rendered as a numbered sub-section (3.1, 3.2, …). */
+export interface CodeGroup {
+ title: string;
+ /** optional lead sentence under the sub-section heading */
+ lead?: string;
+ samples: CodeSample[];
+}
+
/** Section 3 — technical details. */
export interface TechSection {
stack: string[];
+ /** flat samples — rendered when `groups` is absent (most tutorials) */
samples: CodeSample[];
+ /** when present, samples are split into numbered sub-sections (e.g. 3.1 Client, 3.2 Agent) */
+ groups?: CodeGroup[];
files?: FileRow[];
}
@@ -132,6 +143,7 @@ export interface Tutorial {
export const PROTOCOL_LABEL: Record = {
x402: "x402 HTTP",
+ mpp: "MPP",
mcp: "MCP",
langchain: "LangChain",
catalog: "Catalog",
From 4151c370880b09c1d8e506b37b9eeb258d90440f Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 19:58:51 +0200
Subject: [PATCH 20/24] fix(showcase): pay-as-you-go shows real variable
credits, not a fixed count
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The MPP/PAYG tutorial priced every request at a flat '1 credit'. Now the live buyer
computes the actual per-request cost (1 for today, up to 7 for a forecast), the 402 reads
'Pay-as-you-go · N credit(s) for this request', settle notes '(pay-as-you-go)', and the
balance draws down by the real amount.
---
showcase/components/LiveRunPanel.tsx | 18 ++++++++++++++----
showcase/lib/live-agent.mjs | 28 +++++++++++++++++++++-------
2 files changed, 35 insertions(+), 11 deletions(-)
diff --git a/showcase/components/LiveRunPanel.tsx b/showcase/components/LiveRunPanel.tsx
index b2645e30..0eee681f 100644
--- a/showcase/components/LiveRunPanel.tsx
+++ b/showcase/components/LiveRunPanel.tsx
@@ -6,7 +6,7 @@ import { ArrowRight } from "./icons";
type Item =
| { type: "msg"; role: "user" | "agent"; text: string; tag?: "free" | "paid" }
- | { type: "pay"; credits: number; pending: string; resolved?: boolean }
+ | { type: "pay"; credits: number; pending: string; resolved?: boolean; payg?: boolean }
| { type: "settle"; text: string; error?: boolean }
| { type: "notice"; text: string };
@@ -148,7 +148,10 @@ export default function LiveRunPanel({
if (status === 401 && body.kind === "not_connected") {
setItems((x) => [...x, { type: "notice", text: "Connect with Nevermined first to make paid requests." }]);
} else if (status === 402 && body.kind === "payment_required") {
- setItems((x) => [...x, { type: "pay", credits: body.credits, pending: message }]);
+ setItems((x) => [
+ ...x,
+ { type: "pay", credits: body.credits, pending: message, payg: !!body.payg },
+ ]);
} else if (status === 402 && body.kind === "insufficient") {
setBalance(body.balance);
setItems((x) => [
@@ -161,7 +164,10 @@ export default function LiveRunPanel({
tickBalance(body.balance);
setItems((x) => [
...x,
- { type: "settle", text: `200 OK · settled ${body.credits} credit(s) · balance ${body.balance}` },
+ {
+ type: "settle",
+ text: `200 OK · settled ${body.credits} credit(s)${body.payg ? " (pay-as-you-go)" : ""} · balance ${body.balance}`,
+ },
{ type: "msg", role: "agent", text: body.answer, tag: "paid" },
]);
} else {
@@ -247,7 +253,11 @@ export default function LiveRunPanel({
return (
402
-
Payment required · {it.credits} credit(s)
+
+ {it.payg
+ ? `Pay-as-you-go · ${it.credits} credit(s) for this request`
+ : `Payment required · ${it.credits} credit(s)`}
+
authorize(it.pending, i)}
diff --git a/showcase/lib/live-agent.mjs b/showcase/lib/live-agent.mjs
index 18ecdf03..77b76fd1 100644
--- a/showcase/lib/live-agent.mjs
+++ b/showcase/lib/live-agent.mjs
@@ -45,7 +45,8 @@ const LIVE = {
protocol: "mpp",
route: "/weather/payg",
planId: process.env.PLAN_ID_PAYG || "",
- credits: 1, // nominal; pay-as-you-go actually charges by requested days (1..7)
+ payg: true, // variable price per request (no fixed credit count)
+ credits: 1, // fallback only; paygCost() computes the real per-request amount
pill: "MPP · pay-as-you-go",
greeting:
"I'm a live weather agent paid over MPP (Machine Payments Protocol), priced pay-as-you-go. Ask for a city — add a number of days for a forecast (e.g. '5-day forecast in Berlin'). The buyer runs the challenge→credential handshake against the real sandbox.",
@@ -98,6 +99,13 @@ function daysOf(message) {
return m ? Math.max(1, Math.min(7, parseInt(m[1], 10))) : undefined;
}
+// Pay-as-you-go price for a request: 1 credit for today, up to 7 for a forecast.
+// Mirrors the agent's priceForRequest so the UI can show the real, variable cost.
+function paygCost(body) {
+ const d = body.days;
+ return typeof d === "number" && d > 1 ? Math.min(7, Math.trunc(d)) : 1;
+}
+
function formatWeather(w) {
const place = w.country ? `${w.city}, ${w.country}` : w.city;
// multi-day forecast (pay-as-you-go /weather/payg with days > 1)
@@ -198,20 +206,26 @@ export async function liveRespond(state, req) {
if (req.action === "ask") {
const message = (req.message || "").trim();
if (!message) return { status: 400, body: { error: "empty message" }, state: s };
+ const days = daysOf(message);
+ const body = { city: cityOf(message), ...(days ? { days } : {}) };
+ // Pay-as-you-go: the real cost depends on the request (1..7). Fixed plans use cfg.credits.
+ const cost = cfg.payg ? paygCost(body) : cfg.credits;
if (!s.authorized) {
- return { status: 402, body: { kind: "payment_required", credits: cfg.credits, method: cfg.protocol }, state: s };
+ return {
+ status: 402,
+ body: { kind: "payment_required", credits: cost, payg: !!cfg.payg, method: cfg.protocol },
+ state: s,
+ };
}
- if (s.balance < cfg.credits) {
+ if (s.balance < cost) {
return { status: 402, body: { kind: "insufficient", balance: s.balance }, state: s };
}
- const days = daysOf(message);
- const body = { city: cityOf(message), ...(days ? { days } : {}) };
try {
const { weather, note } = cfg.protocol === "mpp" ? await buyMpp(key, cfg, body) : await buyX402(key, cfg, body);
- const next = { authorized: true, balance: s.balance - cfg.credits };
+ const next = { authorized: true, balance: s.balance - cost };
return {
status: 200,
- body: { kind: "paid", answer: `${formatWeather(weather)}\n\n(${note})`, credits: cfg.credits, balance: next.balance },
+ body: { kind: "paid", answer: `${formatWeather(weather)}\n\n(${note})`, credits: cost, payg: !!cfg.payg, balance: next.balance },
state: next,
};
} catch (e) {
From a4744ec07518c99a62d0e1f1a3370f676b30e9ac Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 20:11:42 +0200
Subject: [PATCH 21/24] =?UTF-8?q?fix(showcase):=20PAYG=20is=20paid=20per?=
=?UTF-8?q?=20request=20=E2=80=94=20drop=20credits=20and=20balance=20entir?=
=?UTF-8?q?ely?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Pay-as-you-go has no credit pool: the 402 reads 'Payment required · pay-as-you-go', the
receipt reads 'paid · pay-as-you-go', and no credit balance is shown or tracked. Fixed-credit
tutorials still show credits + balance.
---
showcase/components/LiveRunPanel.tsx | 21 ++++++++++-----
showcase/content/tutorials.ts | 4 +--
showcase/lib/live-agent.mjs | 38 +++++++++++++---------------
3 files changed, 35 insertions(+), 28 deletions(-)
diff --git a/showcase/components/LiveRunPanel.tsx b/showcase/components/LiveRunPanel.tsx
index 0eee681f..248c085a 100644
--- a/showcase/components/LiveRunPanel.tsx
+++ b/showcase/components/LiveRunPanel.tsx
@@ -19,8 +19,9 @@ interface Intro {
greeting: string;
suggestions: string[];
authorized: boolean;
- balance: number;
+ balance?: number;
live?: boolean;
+ payg?: boolean;
code?: CodeLink[];
}
@@ -64,6 +65,7 @@ export default function LiveRunPanel({
const [apiKey, setApiKey] = useState(null);
const [connecting, setConnecting] = useState(false);
const [codeLinks, setCodeLinks] = useState([]);
+ const [payg, setPayg] = useState(false);
const logRef = useRef(null);
// On mount: capture an nvm_api_key returned by the Nevermined App callback (query string),
@@ -105,9 +107,10 @@ export default function LiveRunPanel({
setItems([{ type: "msg", role: "agent", text: intro.greeting }]);
setSuggestions(intro.suggestions ?? []);
setAuthorized(intro.authorized);
- setBalance(intro.balance);
+ setBalance(typeof intro.balance === "number" ? intro.balance : null);
setLive(!!intro.live);
setCodeLinks(intro.code ?? []);
+ setPayg(!!intro.payg);
});
return () => {
alive = false;
@@ -161,12 +164,14 @@ export default function LiveRunPanel({
} else if (body.kind === "free") {
setItems((x) => [...x, { type: "msg", role: "agent", text: body.answer, tag: "free" }]);
} else if (body.kind === "paid") {
- tickBalance(body.balance);
+ if (typeof body.balance === "number") tickBalance(body.balance);
setItems((x) => [
...x,
{
type: "settle",
- text: `200 OK · settled ${body.credits} credit(s)${body.payg ? " (pay-as-you-go)" : ""} · balance ${body.balance}`,
+ text: body.payg
+ ? "200 OK · paid · pay-as-you-go"
+ : `200 OK · settled ${body.credits} credit(s) · balance ${body.balance}`,
},
{ type: "msg", role: "agent", text: body.answer, tag: "paid" },
]);
@@ -255,7 +260,7 @@ export default function LiveRunPanel({
402
{it.payg
- ? `Pay-as-you-go · ${it.credits} credit(s) for this request`
+ ? "Payment required · pay-as-you-go"
: `Payment required · ${it.credits} credit(s)`}
{live ? (
apiKey ? (
- <>Live agent — real x402/MPP payments on Nevermined sandbox, paid with your connected key. >
+ payg ? (
+ <>Live agent — pay-as-you-go: each request is paid on its own against Nevermined sandbox, no credit balance. >
+ ) : (
+ <>Live agent — real x402/MPP payments on Nevermined sandbox, paid with your connected key. >
+ )
) : (
<>Live agent — connect once to pay real x402/MPP requests on Nevermined sandbox. >
)
diff --git a/showcase/content/tutorials.ts b/showcase/content/tutorials.ts
index f5d190ac..2be2e0b0 100644
--- a/showcase/content/tutorials.ts
+++ b/showcase/content/tutorials.ts
@@ -911,12 +911,12 @@ app.post('/weather/payg', async (req, res) => {
paymentPill: "MPP · pay-as-you-go",
transcript: [
{ t: "POST /weather/payg { city: 'Berlin', days: 5 }", kind: "req" },
- { t: "← 402 WWW-Authenticate: Payment · 5 credits", kind: "r402" },
+ { t: "← 402 WWW-Authenticate: Payment (pay-as-you-go)", kind: "r402" },
{ t: " mint MPP credential for the delegation", kind: "dim" },
{ t: "POST /weather/payg Authorization: Payment eyJ…", kind: "req" },
{ t: " verify → serve → settle", kind: "dim" },
{ t: "← 200 OK Payment-Receipt", kind: "r200" },
- { t: "5 credits burned · 5-day forecast", kind: "settle" },
+ { t: "paid · 5-day forecast", kind: "settle" },
],
note: "Connect your Nevermined sandbox account, then send a city — the buyer runs the real MPP handshake (payments.mpp.fetch) against the deployed agent's pay-as-you-go route.",
},
diff --git a/showcase/lib/live-agent.mjs b/showcase/lib/live-agent.mjs
index 77b76fd1..6bd0a325 100644
--- a/showcase/lib/live-agent.mjs
+++ b/showcase/lib/live-agent.mjs
@@ -99,13 +99,6 @@ function daysOf(message) {
return m ? Math.max(1, Math.min(7, parseInt(m[1], 10))) : undefined;
}
-// Pay-as-you-go price for a request: 1 credit for today, up to 7 for a forecast.
-// Mirrors the agent's priceForRequest so the UI can show the real, variable cost.
-function paygCost(body) {
- const d = body.days;
- return typeof d === "number" && d > 1 ? Math.min(7, Math.trunc(d)) : 1;
-}
-
function formatWeather(w) {
const place = w.country ? `${w.city}, ${w.country}` : w.city;
// multi-day forecast (pay-as-you-go /weather/payg with days > 1)
@@ -174,12 +167,13 @@ export async function liveRespond(state, req) {
greeting: cfg.greeting,
suggestions: cfg.suggestions,
pill: cfg.pill,
- credits: cfg.credits,
hasFreeTier: false,
connected: !!key,
authorized: s.authorized,
- balance: s.balance,
code: AGENT_CODE, // links to the deployed agent (server) source
+ // Pay-as-you-go pays a fixed price per request — no credit pool, so no
+ // credits/balance are surfaced. Fixed-credit plans report both.
+ ...(cfg.payg ? { payg: true } : { credits: cfg.credits, balance: s.balance }),
},
state: s,
};
@@ -196,7 +190,11 @@ export async function liveRespond(state, req) {
} catch (e) {
return { status: 502, body: { error: `could not create delegation: ${e.message}` }, state: s };
}
- return { status: 200, body: { ok: true, method: "erc4337 delegation", balance: s.balance }, state: { authorized: true, balance: s.balance } };
+ return {
+ status: 200,
+ body: { ok: true, method: "erc4337 delegation", ...(cfg.payg ? {} : { balance: s.balance }) },
+ state: { authorized: true, balance: s.balance },
+ };
}
if (req.action === "reset") {
@@ -208,26 +206,26 @@ export async function liveRespond(state, req) {
if (!message) return { status: 400, body: { error: "empty message" }, state: s };
const days = daysOf(message);
const body = { city: cityOf(message), ...(days ? { days } : {}) };
- // Pay-as-you-go: the real cost depends on the request (1..7). Fixed plans use cfg.credits.
- const cost = cfg.payg ? paygCost(body) : cfg.credits;
if (!s.authorized) {
+ // Pay-as-you-go: fixed price per request, no credit count. Fixed plans quote credits.
return {
status: 402,
- body: { kind: "payment_required", credits: cost, payg: !!cfg.payg, method: cfg.protocol },
+ body: { kind: "payment_required", method: cfg.protocol, ...(cfg.payg ? { payg: true } : { credits: cfg.credits }) },
state: s,
};
}
- if (s.balance < cost) {
+ if (!cfg.payg && s.balance < cfg.credits) {
return { status: 402, body: { kind: "insufficient", balance: s.balance }, state: s };
}
try {
const { weather, note } = cfg.protocol === "mpp" ? await buyMpp(key, cfg, body) : await buyX402(key, cfg, body);
- const next = { authorized: true, balance: s.balance - cost };
- return {
- status: 200,
- body: { kind: "paid", answer: `${formatWeather(weather)}\n\n(${note})`, credits: cost, payg: !!cfg.payg, balance: next.balance },
- state: next,
- };
+ const answer = `${formatWeather(weather)}\n\n(${note})`;
+ if (cfg.payg) {
+ // paid per request — no credits, no balance
+ return { status: 200, body: { kind: "paid", payg: true, answer }, state: { authorized: true, balance: s.balance } };
+ }
+ const next = { authorized: true, balance: s.balance - cfg.credits };
+ return { status: 200, body: { kind: "paid", answer, credits: cfg.credits, balance: next.balance }, state: next };
} catch (e) {
return { status: 502, body: { kind: "error", error: `live agent call failed: ${e.message}` }, state: s };
}
From 82aace8b490c2f6aa6e19380ef1d9cf15a2ca98c Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Fri, 4 Sep 2026 20:32:37 +0200
Subject: [PATCH 22/24] feat(showcase): distinct Signal glyph for the MPP
category
---
showcase/components/AppShell.tsx | 3 ++-
showcase/components/icons.tsx | 18 ++++++++++++++++++
2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/showcase/components/AppShell.tsx b/showcase/components/AppShell.tsx
index 840facce..daf4c2ef 100644
--- a/showcase/components/AppShell.tsx
+++ b/showcase/components/AppShell.tsx
@@ -12,6 +12,7 @@ import {
External,
Spark,
Bolt,
+ Signal,
Plug,
Layers,
Book,
@@ -44,7 +45,7 @@ export interface NavGroup {
const GLYPH: Record = {
catalog: ,
x402: ,
- mpp: ,
+ mpp: ,
mcp: ,
langchain: ,
};
diff --git a/showcase/components/icons.tsx b/showcase/components/icons.tsx
index 497987d5..2e791f06 100644
--- a/showcase/components/icons.tsx
+++ b/showcase/components/icons.tsx
@@ -112,6 +112,24 @@ export const Bolt = ({ size, className }: P) => (
);
+// Signal / broadcast — the MPP category glyph (matches the "signal" Connect button theme).
+export const Signal = ({ size, className }: P) => (
+
+
+
+
+
+);
export const Grid = ({ size, className, strokeWidth }: P) =>
svg(
<>
From fb39059acede248eec692052a5bfebfa02f55198 Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Sat, 5 Sep 2026 12:05:31 +0200
Subject: [PATCH 23/24] fix(http-ts,showcase): address PR #69 review
(r-marques)
- BLOCKER: rewrite http-simple-agent-ts/README.md for the weather x402+MPP agent (routes, PLAN_ID_* env, scripts).
- Drop stale LLM-era client.ts + agent-observability.ts (broke `yarn client`); remove the client script + tsconfig excludes.
- register-plans: warn loudly when NVM_RECEIVER unset (no silent FREE plans); add NVM_RECEIVER/PLAN_PRICE_WEI to .env.example.
- Drop deprecated `environment` option (agent.ts + register-plans.ts); remove NVM_ENVIRONMENT.
- live-agent: delegation TTL + re-mint past expiry + invalidate on expiry error; bound the per-key caches; scale delegation limit to $5; cityOf takes the last non-stopword capitalised token.
- Read the connect key from URL fragment too (forward-compat for the App-side log fix); strip fragment on cleanup.
- deploy README: correct MPP-guard attribution (SDK middleware, not agent.ts); document ~15-20s boot probe timing + API-key-in-logs exposure.
---
http-simple-agent-ts/.env.example | 11 +-
http-simple-agent-ts/README.md | 381 +++++-------------
http-simple-agent-ts/deploy/argocd/README.md | 28 +-
http-simple-agent-ts/package.json | 1 -
.../scripts/register-plans.ts | 15 +-
.../src/agent-observability.ts | 176 --------
http-simple-agent-ts/src/agent.ts | 6 +-
http-simple-agent-ts/src/client.ts | 242 -----------
http-simple-agent-ts/tsconfig.json | 2 +-
showcase/components/LiveRunPanel.tsx | 16 +-
showcase/lib/live-agent.mjs | 53 ++-
11 files changed, 210 insertions(+), 721 deletions(-)
delete mode 100644 http-simple-agent-ts/src/agent-observability.ts
delete mode 100644 http-simple-agent-ts/src/client.ts
diff --git a/http-simple-agent-ts/.env.example b/http-simple-agent-ts/.env.example
index 0cd9bb8b..beea3eab 100644
--- a/http-simple-agent-ts/.env.example
+++ b/http-simple-agent-ts/.env.example
@@ -1,11 +1,16 @@
-# Nevermined (required)
-NVM_API_KEY=nvm:your-api-key
-NVM_ENVIRONMENT=sandbox
+# Nevermined (required). The environment (sandbox/live) is derived from the key prefix.
+NVM_API_KEY=sandbox:your-api-key
# Plan IDs — created by `yarn register-plans` (see scripts/register-plans.ts)
PLAN_ID_CREDITS=
PLAN_ID_TIME=
PLAN_ID_PAYG=
+# For `yarn register-plans` only: the builder wallet that receives payment.
+# REQUIRED for crypto-priced (payable) plans — without it the plans register as FREE.
+NVM_RECEIVER=
+# Optional: on-chain price per plan purchase, in the token's smallest unit (default 0).
+PLAN_PRICE_WEI=0
+
# Server
PORT=3000
diff --git a/http-simple-agent-ts/README.md b/http-simple-agent-ts/README.md
index 5d482f52..052c5849 100644
--- a/http-simple-agent-ts/README.md
+++ b/http-simple-agent-ts/README.md
@@ -1,353 +1,196 @@
-# HTTP Simple Agent (TypeScript) with x402 Payment Protection
+# HTTP Weather Agent (TypeScript) — x402 + MPP
-A minimal Express server demonstrating the [x402 payment protocol](https://github.com/coinbase/x402) using Nevermined's payment middleware. This tutorial shows how to protect API endpoints with credit-based payments.
+A minimal Express server whose weather endpoints are gated by Nevermined's payment middleware. One `paymentMiddleware` call protects three routes, each backed by a different payment plan and each accepting **both** payment protocols — [x402](https://github.com/coinbase/x402) and **MPP** (Machine Payments Protocol). Weather comes from the free, keyless [Open-Meteo](https://open-meteo.com) API, so the agent needs no third-party keys to run.
-> **Note:** For a Python version of this tutorial, see [http-simple-agent-py](../http-simple-agent-py/).
+> **Note:** For a Python version of the x402 flow, see [http-simple-agent-py](../http-simple-agent-py/). MPP is TypeScript-only.
[](https://discord.com/invite/GZju2qScKq)
## Overview
-This tutorial includes:
+- **Agent** (`src/agent.ts`) — an Express server exposing three payment-protected weather routes plus an unprotected `/health`.
+- **Weather service** (`src/services/weather.service.ts`) — current weather + multi-day forecast from Open-Meteo (no API key).
+- **Plan registration** (`scripts/register-plans.ts`) — one-shot script that registers the three plans and prints their IDs.
+- **Smoke test / buyer example** (`scripts/smoke.ts`) — drives the full x402 and MPP buyer round-trips against the agent.
-- **Agent** (`src/agent.ts`) - An Express server with a payment-protected `/ask` endpoint
-- **Agent with Observability** (`src/agent-observability.ts`) - Same agent with Nevermined observability for tracking OpenAI costs
-- **Client** (`src/client.ts`) - A demo client showing the complete x402 payment flow
+### Routes, plans and protocols
-## x402 Payment Flow
+| Route | Plan type | Cost | Protocols |
+| --- | --- | --- | --- |
+| `POST /weather/credits` | fixed credits | 1 credit / request | x402 + MPP |
+| `POST /weather/subscription` | time-based (24h pass) | time-boxed access | x402 + MPP |
+| `POST /weather/payg` | dynamic (pay-as-you-go) | 1 for today, up to 7 for a forecast | x402 + MPP |
-```
-┌─────────┐ ┌─────────┐
-│ Client │ │ Agent │
-└────┬────┘ └────┬────┘
- │ │
- │ 1. POST /ask (no token) │
- │───────────────────────────────────────>│
- │ │
- │ 2. 402 Payment Required │
- │ Header: payment-required (base64) │
- │<───────────────────────────────────────│
- │ │
- │ 3. Generate x402 token via SDK │
- │ │
- │ 4. POST /ask │
- │ Header: payment-signature (token) │
- │───────────────────────────────────────>│
- │ │
- │ - Verify permissions │
- │ - Execute request │
- │ - Settle (burn credits) │
- │ │
- │ 5. 200 OK + AI response │
- │ Header: payment-response (base64) │
- │<───────────────────────────────────────│
- │ │
-```
+`mpp: true` on each route makes the `402` advertise **both** protocols, so an x402 buyer and an MPP buyer work against the same URL.
+
+## Payment headers
+
+| Protocol | Challenge (402) | Client → server | Receipt (200) |
+| --- | --- | --- | --- |
+| **x402** | `payment-required` | `payment-signature` | `payment-response` |
+| **MPP** | `WWW-Authenticate: Payment` | `Authorization: Payment` | `Payment-Receipt` |
-## Quick Start
+## Quick start
-### 1. Install dependencies
+### 1. Install
```bash
yarn install
```
-### 2. Configure environment
+### 2. Register the plans
+
+Registers the three plans against your Nevermined account and prints their IDs. The environment (sandbox/live) is derived from your API-key prefix. Set `NVM_RECEIVER` to your builder wallet so the plans are **crypto-priced (payable)** — without it the script registers FREE plans and warns loudly.
```bash
-cp .env.example .env
+NVM_API_KEY=sandbox:your-api-key NVM_RECEIVER=0xYourBuilderWallet yarn register-plans
+# -> PLAN_ID_CREDITS=... / PLAN_ID_TIME=... / PLAN_ID_PAYG=...
```
-Edit `.env` with your credentials:
+### 3. Configure environment
```bash
-# Nevermined (required)
-NVM_API_KEY=nvm:your-api-key
-NVM_ENVIRONMENT=sandbox
-NVM_PLAN_ID=your-plan-id
-
-# Agent
-OPENAI_API_KEY=sk-your-openai-api-key
-PORT=3000
-
-# Client
-SERVER_URL=http://localhost:3000
+cp .env.example .env
```
-### 3. Run the agent (server)
-
```bash
-yarn agent
+# Nevermined (required). Environment is derived from the key prefix (sandbox:/live:).
+NVM_API_KEY=sandbox:your-api-key
+
+# Plan IDs from `yarn register-plans`
+PLAN_ID_CREDITS=...
+PLAN_ID_TIME=...
+PLAN_ID_PAYG=...
+
+PORT=3000
```
-### 4. Run the client (in another terminal)
+### 4. Run the agent
```bash
-yarn client
+yarn agent # dev (tsx)
+# or: yarn build && yarn start # compiled (dist/agent.js) — same as the Docker image
```
-## x402 Headers
+### 5. Run the smoke test (buyer, in another terminal)
-The middleware follows the [x402 HTTP transport spec](https://github.com/coinbase/x402/blob/main/specs/transports-v2/http.md):
+Exercises the x402 and MPP buyer flows against the running agent. Needs a Nevermined key and an `erc4337` delegation (created by the script); point it at the server with `SERVER_URL`.
-| Header | Direction | Description |
-| ------------------- | --------------------- | ----------------------------------- |
-| `payment-signature` | Client → Server | Base64-encoded x402 access token |
-| `payment-required` | Server → Client (402) | Base64-encoded payment requirements |
-| `payment-response` | Server → Client (200) | Base64-encoded settlement receipt |
+```bash
+SERVER_URL=http://localhost:3000 NVM_API_KEY=sandbox:your-api-key PLAN_ID_CREDITS=... yarn smoke
+```
-## Agent Code
+## Agent code
-The agent uses the `paymentMiddleware` from `@nevermined-io/payments/express`:
+One middleware protects all three routes; `mpp: true` opts each into MPP alongside x402:
```typescript
import { Payments } from "@nevermined-io/payments";
import { paymentMiddleware } from "@nevermined-io/payments/express";
-const payments = Payments.getInstance({
- nvmApiKey: NVM_API_KEY,
- environment: NVM_ENVIRONMENT,
-});
+// Environment is derived from the API-key prefix — no `environment` option.
+const payments = Payments.getInstance({ nvmApiKey: NVM_API_KEY });
-// Protect routes with one line
app.use(
paymentMiddleware(payments, {
- "POST /ask": {
- planId: NVM_PLAN_ID,
- credits: 1,
+ "POST /weather/credits": { planId: PLAN_ID_CREDITS, credits: 1, mpp: true },
+ "POST /weather/subscription": { planId: PLAN_ID_TIME, credits: 1, mpp: true },
+ "POST /weather/payg": {
+ planId: PLAN_ID_PAYG,
+ credits: (req) => priceForRequest(req.body), // 1 for today, up to 7 for a forecast
+ mpp: true,
},
- })
+ }),
);
-// Route handler - no payment logic needed!
-app.post("/ask", async (req, res) => {
- const response = await openai.chat.completions.create({ ... });
- res.json({ response: response.choices[0].message.content });
+app.post("/weather/credits", async (req, res) => {
+ const { city } = parseWeatherRequest(req.body); // 400 on invalid input
+ res.json(await getTodayWeather(city)); // keyless Open-Meteo
});
```
-## Client Code
+## Buyer code
-The client demonstrates the full x402 flow:
+A delegation backs the buyer for both protocols (in 1.11.2 even the x402 token needs one):
```typescript
-import { Payments } from "@nevermined-io/payments";
import { X402_HEADERS } from "@nevermined-io/payments/express";
-// Step 1: Request without token -> 402
-const response1 = await fetch(`${SERVER_URL}/ask`, {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({ query: "What is 2+2?" }),
+const { delegationId } = await payments.delegation.createDelegation({
+ provider: "erc4337", spendingLimitCents: 10000, durationSecs: 604800, currency: "usdc",
});
-// Status: 402, Header: payment-required
-// Step 2: Decode payment requirements
-const paymentRequired = JSON.parse(
- Buffer.from(response1.headers.get("payment-required"), "base64").toString()
+// --- x402 ---
+const { accessToken } = await payments.x402.getX402AccessToken(
+ PLAN_ID_CREDITS, undefined, { delegationConfig: { delegationId } },
);
-
-// Step 3: Generate x402 token
-const { accessToken } = await payments.x402.getX402AccessToken(NVM_PLAN_ID);
-
-// Step 4: Request with token -> 200
-const response2 = await fetch(`${SERVER_URL}/ask`, {
+const res = await fetch(SERVER_URL + "/weather/credits", {
method: "POST",
- headers: {
- "Content-Type": "application/json",
- [X402_HEADERS.PAYMENT_SIGNATURE]: accessToken,
- },
- body: JSON.stringify({ query: "What is 2+2?" }),
+ headers: { "content-type": "application/json", [X402_HEADERS.PAYMENT_SIGNATURE]: accessToken },
+ body: JSON.stringify({ city: "Lisbon" }),
});
-// Status: 200, Header: payment-response
-
-// Step 5: Decode settlement receipt
-const settlement = JSON.parse(
- Buffer.from(response2.headers.get("payment-response"), "base64").toString()
+// -> 200 + weather, with a `payment-response` settlement receipt
+
+// --- MPP (same route; one call runs the challenge -> credential handshake) ---
+const { response, receipt } = await payments.mpp.fetch(
+ SERVER_URL + "/weather/payg",
+ { method: "POST", headers: { "content-type": "application/json" },
+ body: JSON.stringify({ city: "Berlin", days: 5 }) },
+ { delegationConfig: { delegationId }, planId: PLAN_ID_PAYG, maxCredits: 7 },
);
```
-## API Reference
-
-### POST /ask
-
-Send a query to the AI assistant (payment protected).
-
-**Request Headers:**
-
-```
-Content-Type: application/json
-payment-signature:
-```
-
-**Request Body:**
-
-```json
-{
- "query": "Your question here"
-}
-```
-
-**Success Response (200):**
+## API reference
-```
-Header: payment-response:
-```
+All weather routes take `{ "city": "", "days"?: <1-7> }` and return the weather as JSON. `days > 1` (on `/weather/payg`) returns a multi-day forecast.
-```json
-{
- "response": "AI's answer"
-}
-```
+| Method | Route | Auth |
+| --- | --- | --- |
+| `POST` | `/weather/credits` | payment (x402 or MPP) |
+| `POST` | `/weather/subscription` | payment (x402 or MPP) |
+| `POST` | `/weather/payg` | payment (x402 or MPP) |
+| `GET` | `/health` | none — returns `{ "ok": true }` |
-**Payment Required Response (402):**
+An unpaid request returns `402` with the x402 `payment-required` header and the MPP `WWW-Authenticate: Payment` challenge. Invalid input (missing/short `city`) returns `400`; an unknown city returns `404`.
-```
-Header: payment-required:
-```
+## Scripts
-```json
-{
- "error": "Payment Required",
- "message": "Missing x402 payment token. Send token in payment-signature header."
-}
-```
+| Script | Description |
+| --- | --- |
+| `yarn agent` | Run the agent (dev, tsx) |
+| `yarn register-plans` | Register the credits / time / pay-as-you-go plans |
+| `yarn smoke` | Buyer round-trips (x402 + MPP) against a running agent |
+| `yarn pricing:selfcheck` | Unit self-check for the pay-as-you-go pricing function |
+| `yarn request:selfcheck` | Unit self-check for request input validation |
+| `yarn build` | Compile TypeScript to `dist/` |
+| `yarn start` | Run the compiled agent (`node dist/agent.js`) |
-## Project Structure
+## Project structure
```
http-simple-agent-ts/
├── src/
-│ ├── agent.ts # Express server with payment middleware
-│ ├── agent-observability.ts # Agent with Nevermined observability
-│ └── client.ts # x402 flow demo client
+│ ├── agent.ts # Express server — three dual-protocol weather routes
+│ ├── pricing.ts # priceForRequest (pay-as-you-go)
+│ ├── request.ts # parseWeatherRequest (boundary validation)
+│ └── services/weather.service.ts # Open-Meteo current weather + forecast (keyless)
+├── scripts/
+│ ├── register-plans.ts # register the three plans
+│ └── smoke.ts # x402 + MPP buyer smoke test
+├── deploy/argocd/ # ArgoCD deploy manifests + runbook (agents namespace)
+├── Dockerfile
├── package.json
├── tsconfig.json
-├── .env.example
-├── .gitignore
-└── README.md
-```
-
-## Scripts
-
-| Script | Description |
-| ------------------------ | ---------------------------------------- |
-| `yarn agent` | Run the agent server (dev mode) |
-| `yarn agent:observability` | Run the agent with observability logging |
-| `yarn client` | Run the client demo |
-| `yarn build` | Build TypeScript to JavaScript |
-| `yarn start:agent` | Run built agent |
-| `yarn start:client` | Run built client |
-
-## Middleware Options
-
-```typescript
-paymentMiddleware(payments, routes, {
- // Custom token header - default: 'payment-signature' (x402 v2)
- tokenHeader: "payment-signature",
-
- // Hook before verification
- onBeforeVerify: (req, paymentRequired) => {
- console.log(`Verifying ${req.path}`);
- },
-
- // Hook after verification (for observability)
- onAfterVerify: (req, verification) => {
- // Access agentRequest for observability setup
- const agentRequest = verification.agentRequest;
- if (agentRequest) {
- console.log(`Agent: ${agentRequest.agentName}`);
- }
- },
-
- // Hook after settlement
- onAfterSettle: (req, creditsUsed, settlement) => {
- console.log(`Settled ${creditsUsed} credits`);
- },
-
- // Custom error handler
- onPaymentError: (error, req, res) => {
- res.status(402).json({ error: error.message });
- },
-});
-```
-
-## Route Configuration
-
-```typescript
-paymentMiddleware(payments, {
- // Fixed credits
- "POST /ask": { planId: PLAN_ID, credits: 1 },
-
- // Dynamic credits based on request
- "POST /generate": {
- planId: PLAN_ID,
- credits: (req, res) => req.body.tokens / 100,
- },
-
- // Path parameters
- "GET /users/:id": { planId: PLAN_ID, credits: 1 },
-
- // With agent ID
- "POST /agent/task": {
- planId: PLAN_ID,
- agentId: AGENT_ID,
- credits: 5,
- },
-});
-```
-
-## Observability
-
-The `agent-observability.ts` demonstrates how to integrate Nevermined observability for tracking OpenAI costs per agent and plan.
-
-### How it works
-
-1. The `paymentMiddleware` verifies the x402 token and returns an `agentRequest` object
-2. The `agentRequest` is available via `req.paymentContext.agentRequest` in route handlers
-3. Pass `agentRequest` to `payments.observability.withOpenAI()` to route calls through Nevermined observability
-
-```typescript
-// In your route handler
-const agentRequest = req.paymentContext?.agentRequest;
-
-if (agentRequest) {
- // Route OpenAI calls through Nevermined observability
- const config = payments.observability.withOpenAI(
- OPENAI_API_KEY,
- agentRequest,
- { sessionid: randomUUID() }
- );
- openai = new OpenAI(config);
-}
+└── .env.example
```
-### agentRequest contents
-
-The `agentRequest` object contains:
+## Deployment
-| Field | Description |
-| ----- | ----------- |
-| `agentRequestId` | Unique identifier for this request |
-| `agentName` | Name of the AI agent |
-| `agentId` | ID of the AI agent |
-| `balance.planId` | Payment plan ID |
-| `balance.planName` | Payment plan name |
-| `balance.balance` | Subscriber's remaining credits |
-| `balance.pricePerCredit` | Cost per credit in USD |
-| `urlMatching` | The matched endpoint URL |
-| `verbMatching` | The matched HTTP verb |
-
-### Running with observability
-
-```bash
-yarn agent:observability
-```
+Deployment reference (Dockerfile → GCP Artifact Registry via the CI workflow → ArgoCD in the `agents` namespace) lives in [`deploy/argocd/`](./deploy/argocd/README.md), including the required chart env patch, the secret, `replicaCount: 1` (MPP single-use is in-process), and the startup-probe timing.
-## Learn More
+## Learn more
- [Nevermined Documentation](https://nevermined.ai/docs)
-- [Nevermined Observability Guide](https://nevermined.ai/docs/development-guide/observability)
- [Nevermined x402 Smart Accounts Spec](https://nevermined.ai/docs/specs/x402-smart-accounts)
- [x402 Protocol Specification](https://github.com/coinbase/x402)
- [@nevermined-io/payments SDK](https://github.com/nevermined-io/payments)
diff --git a/http-simple-agent-ts/deploy/argocd/README.md b/http-simple-agent-ts/deploy/argocd/README.md
index 0ebdf6ff..b15aa83e 100644
--- a/http-simple-agent-ts/deploy/argocd/README.md
+++ b/http-simple-agent-ts/deploy/argocd/README.md
@@ -65,9 +65,31 @@ because the template has no line for them.
param (`{{ .Values.replicaCount }}` is used directly in `deployment.yaml`
when `autoscaling.enabled` is false, which is also the default). Both
manifests set it explicitly anyway for visibility: **do not raise it and do
-not enable `autoscaling`**. The MPP single-use-token guard in `agent.ts` is
-an in-process in-memory set; a second replica (or HPA scale-out) would let
-the same MPP token be redeemed twice, defeating the guard.
+not enable `autoscaling`**. The MPP single-use-token guard lives inside
+`paymentMiddleware` (`@nevermined-io/payments/express`) — the
+`inFlightMppCredentials` / `spentMppCredentials` in-process, in-memory sets,
+not anything in `agent.ts` — so a second replica (or HPA scale-out) would let
+the same MPP credential be redeemed twice, defeating the guard. (The SDK's own
+comment on `spentMppCredentials` says the same: it does not span processes or
+horizontally-scaled instances.)
+
+## Startup: probes must tolerate a ~15–20s boot
+
+The image takes ~15–20s to start (the payments SDK import is heavy) before
+`GET /health` responds. Ensure the pod's readiness/liveness probe allows for
+this — a startup probe, or a `readinessProbe` with enough `initialDelaySeconds`
+/ `failureThreshold`. A liveness probe that fires sooner will kill the pod
+mid-boot and crash-loop it.
+
+## Viewer API keys in access logs (showcase Connect flow)
+
+The tutorials showcase's "Connect with Nevermined" flow returns the viewer's
+API key to the site as a **query param** (`?nvm_api_key=…`, the App's
+`/auth/cli` shape), so it lands in the showcase server's (and any proxy/CDN's)
+access logs on the redirect's request line. If you deploy the showcase, either
+scrub that param at the edge, or track the App-side fix to return the key in
+the URL **fragment** (`#…`, never sent to the server — the showcase capture
+code already reads both).
## `helm template` render summary (validated locally, no cluster contact)
diff --git a/http-simple-agent-ts/package.json b/http-simple-agent-ts/package.json
index e4f84341..4e817e6d 100644
--- a/http-simple-agent-ts/package.json
+++ b/http-simple-agent-ts/package.json
@@ -7,7 +7,6 @@
"type": "module",
"scripts": {
"agent": "tsx src/agent.ts",
- "client": "tsx src/client.ts",
"register-plans": "tsx scripts/register-plans.ts",
"smoke": "tsx scripts/smoke.ts",
"pricing:selfcheck": "tsx src/pricing.selfcheck.ts",
diff --git a/http-simple-agent-ts/scripts/register-plans.ts b/http-simple-agent-ts/scripts/register-plans.ts
index 698cf0ed..47bc50e9 100644
--- a/http-simple-agent-ts/scripts/register-plans.ts
+++ b/http-simple-agent-ts/scripts/register-plans.ts
@@ -1,16 +1,21 @@
import "dotenv/config";
-import { Payments, EnvironmentName } from "@nevermined-io/payments";
+import { Payments } from "@nevermined-io/payments";
-const payments = Payments.getInstance({
- nvmApiKey: process.env.NVM_API_KEY!,
- environment: (process.env.NVM_ENVIRONMENT || "sandbox") as EnvironmentName,
-});
+// Environment is derived from the API-key prefix (sandbox:/live:); no `environment` option.
+const payments = Payments.getInstance({ nvmApiKey: process.env.NVM_API_KEY! });
const plans = payments.plans;
// Crypto price so BOTH x402 (erc4337) and MPP can pay. Needs the builder's receiver wallet.
// If NVM_RECEIVER is unset, fall back to a free plan so the script still runs for a demo.
const receiver = process.env.NVM_RECEIVER ?? "";
const amount = BigInt(process.env.PLAN_PRICE_WEI ?? "0");
+if (!receiver) {
+ console.warn(
+ "⚠ NVM_RECEIVER is unset — registering FREE plans (getFreePriceConfig); NO payment will be charged. " +
+ "Set NVM_RECEIVER= (and optionally PLAN_PRICE_WEI) to register crypto-priced plans " +
+ "that x402 and MPP buyers actually pay.",
+ );
+}
const price = receiver
? plans.getCryptoPriceConfig(amount, receiver as `0x${string}`)
: plans.getFreePriceConfig();
diff --git a/http-simple-agent-ts/src/agent-observability.ts b/http-simple-agent-ts/src/agent-observability.ts
deleted file mode 100644
index cdc52a9b..00000000
--- a/http-simple-agent-ts/src/agent-observability.ts
+++ /dev/null
@@ -1,176 +0,0 @@
-/**
- * HTTP Agent with Observability - Express server with Nevermined payment middleware and observability logging.
- *
- * This demonstrates how to:
- * 1. Protect an endpoint using the x402 protocol with the standard paymentMiddleware
- * 2. Access agentRequest from the payment context for observability
- * 3. Route OpenAI calls through Nevermined observability for logging and analytics
- *
- * The agentRequest (available via req.paymentContext.agentRequest) contains:
- * - agentRequestId: Unique identifier for this request
- * - agentName: Name of the AI agent
- * - agentId: ID of the AI agent
- * - balance: Subscriber's credit balance info
- * - urlMatching: The matched endpoint pattern
- * - verbMatching: The matched HTTP verb
- */
-import "dotenv/config";
-import express, { Request, Response, RequestHandler } from "express";
-import OpenAI from "openai";
-import {
- Payments,
- EnvironmentName,
- StartAgentRequest,
-} from "@nevermined-io/payments";
-import {
- paymentMiddleware,
- X402_HEADERS,
- PaymentContext,
-} from "@nevermined-io/payments/express";
-import { randomUUID } from "crypto";
-
-const app = express();
-app.use(express.json());
-
-const PORT = process.env.PORT ? Number(process.env.PORT) : 3000;
-const OPENAI_API_KEY = process.env.OPENAI_API_KEY ?? "";
-const NVM_API_KEY = process.env.NVM_API_KEY ?? "";
-const NVM_ENVIRONMENT = (process.env.NVM_ENVIRONMENT || "staging_sandbox") as EnvironmentName;
-const NVM_PLAN_ID = process.env.NVM_PLAN_ID ?? "";
-const NVM_AGENT_ID = process.env.NVM_AGENT_ID ?? "";
-
-if (!OPENAI_API_KEY) {
- console.error("OPENAI_API_KEY is required. Set it in .env file.");
- process.exit(1);
-}
-
-if (!NVM_API_KEY || !NVM_PLAN_ID) {
- console.error("NVM_API_KEY and NVM_PLAN_ID are required for payment protection.");
- process.exit(1);
-}
-
-// Initialize Nevermined Payments SDK
-const payments = Payments.getInstance({
- nvmApiKey: NVM_API_KEY,
- environment: NVM_ENVIRONMENT,
-});
-
-// Extend Express Request to include payment context
-declare global {
- namespace Express {
- interface Request {
- paymentContext?: PaymentContext;
- }
- }
-}
-
-// Apply payment middleware with observability hooks
-app.use(
- paymentMiddleware(payments, {
- "POST /ask": {
- planId: NVM_PLAN_ID,
- agentId: NVM_AGENT_ID || undefined,
- credits: 1,
- },
- }, {
- onAfterVerify: (req, verification) => {
- // Log observability info after verification
- const agentRequest = verification.agentRequest;
- if (agentRequest) {
- console.log("[Observability] Verification successful");
- console.log(` Agent: ${agentRequest.agentName} (${agentRequest.agentId})`);
- console.log(` Request ID: ${agentRequest.agentRequestId}`);
- console.log(` Plan: ${agentRequest.balance.planName} (${agentRequest.balance.planId})`);
- console.log(` Balance: ${agentRequest.balance.balance} credits`);
- }
- },
- onAfterSettle: (req, creditsUsed, result) => {
- console.log(`[Payment] Settled ${creditsUsed} credits`);
- },
- }) as RequestHandler
-);
-
-/**
- * POST /ask - Send a query to the AI with Nevermined observability
- *
- * When agentRequest is available from payment verification, OpenAI calls
- * are routed through Nevermined observability for:
- * - Cost tracking per agent/plan
- * - Usage analytics
- * - Request tracing
- */
-app.post("/ask", async (req: Request, res: Response) => {
- try {
- const { query } = req.body as { query?: string };
-
- if (!query || typeof query !== "string") {
- return res.status(400).json({ error: "Missing or invalid 'query' field" });
- }
-
- // Get agentRequest from payment context (set by middleware)
- const agentRequest = req.paymentContext?.agentRequest;
-
- let openai: OpenAI;
-
- if (agentRequest) {
- // With observability - routes through Nevermined observability for logging
- const config = payments.observability.withOpenAI(
- OPENAI_API_KEY,
- agentRequest,
- { sessionid: randomUUID() }
- );
- openai = new OpenAI(config);
-
- console.log("[Observability] Using Nevermined observability logging");
- } else {
- // Fallback without observability
- openai = new OpenAI({ apiKey: OPENAI_API_KEY });
- console.log("[Observability] Nevermined observability not available, using direct OpenAI");
- }
-
- const completion = await openai.chat.completions.create({
- model: "gpt-4o-mini",
- messages: [
- {
- role: "system",
- content: "You are a helpful assistant. Be concise and informative.",
- },
- { role: "user", content: query },
- ],
- max_tokens: 500,
- });
-
- const response = completion.choices[0]?.message?.content ?? "No response generated";
-
- // Settlement happens automatically via middleware after res.json()
- res.json({
- response,
- observability: agentRequest ? {
- agentRequestId: agentRequest.agentRequestId,
- agentName: agentRequest.agentName,
- planId: agentRequest.balance.planId,
- } : null,
- });
- } catch (error) {
- console.error("Error in /ask:", error);
- res.status(500).json({ error: "Internal server error" });
- }
-});
-
-/**
- * GET /health - Health check endpoint (unprotected)
- */
-app.get("/health", (_req: Request, res: Response) => {
- res.json({ status: "ok", observability: "enabled" });
-});
-
-app.listen(PORT, () => {
- console.log(`HTTP Agent with Observability running on http://localhost:${PORT}`);
- console.log(`\nPayment protection enabled for POST /ask`);
- console.log(`Plan ID: ${NVM_PLAN_ID}`);
- if (NVM_AGENT_ID) {
- console.log(`Agent ID: ${NVM_AGENT_ID}`);
- }
- console.log(`\nObservability: OpenAI calls are logged to Nevermined when agentRequest is available.`);
- console.log(`\nTo test, send requests with x402 token in '${X402_HEADERS.PAYMENT_SIGNATURE}' header.`);
-});
diff --git a/http-simple-agent-ts/src/agent.ts b/http-simple-agent-ts/src/agent.ts
index 2eade80a..db968707 100644
--- a/http-simple-agent-ts/src/agent.ts
+++ b/http-simple-agent-ts/src/agent.ts
@@ -14,7 +14,7 @@
*/
import "dotenv/config";
import express, { Request, Response, RequestHandler } from "express";
-import { Payments, EnvironmentName } from "@nevermined-io/payments";
+import { Payments } from "@nevermined-io/payments";
import { paymentMiddleware, X402_HEADERS, MPP_HEADERS } from "@nevermined-io/payments/express";
import { getTodayWeather, getForecast, CityNotFoundError } from "./services/weather.service.js";
import { priceForRequest } from "./pricing.js";
@@ -22,7 +22,6 @@ import { parseWeatherRequest, BadRequestError } from "./request.js";
const PORT = process.env.PORT ? Number(process.env.PORT) : 3000;
const NVM_API_KEY = process.env.NVM_API_KEY ?? "";
-const NVM_ENVIRONMENT = (process.env.NVM_ENVIRONMENT || "sandbox") as EnvironmentName;
const PLAN_ID_CREDITS = process.env.PLAN_ID_CREDITS ?? "";
const PLAN_ID_TIME = process.env.PLAN_ID_TIME ?? "";
const PLAN_ID_PAYG = process.env.PLAN_ID_PAYG ?? "";
@@ -32,7 +31,8 @@ if (!NVM_API_KEY || !PLAN_ID_CREDITS || !PLAN_ID_TIME || !PLAN_ID_PAYG) {
process.exit(1);
}
-const payments = Payments.getInstance({ nvmApiKey: NVM_API_KEY, environment: NVM_ENVIRONMENT });
+// Environment is derived from the API-key prefix (sandbox:/live:); no `environment` option.
+const payments = Payments.getInstance({ nvmApiKey: NVM_API_KEY });
const app = express();
app.use(express.json());
diff --git a/http-simple-agent-ts/src/client.ts b/http-simple-agent-ts/src/client.ts
deleted file mode 100644
index 8f152e3a..00000000
--- a/http-simple-agent-ts/src/client.ts
+++ /dev/null
@@ -1,242 +0,0 @@
-/**
- * x402 Client - Demonstrates the full payment flow.
- *
- * This client shows the complete x402 HTTP protocol flow:
- * 1. Request without token -> 402 Payment Required
- * 2. Decode payment requirements from header
- * 3. Generate x402 access token
- * 4. Request with token -> Success
- * 5. Decode settlement response from header
- */
-import "dotenv/config";
-import { Payments, EnvironmentName } from "@nevermined-io/payments";
-import { X402_HEADERS } from "@nevermined-io/payments/express";
-import type { X402SchemeType } from "@nevermined-io/payments";
-
-const SERVER_URL = process.env.SERVER_URL || "http://localhost:3000";
-const NVM_API_KEY = process.env.NVM_API_KEY ?? "";
-const NVM_ENVIRONMENT = (process.env.NVM_ENVIRONMENT || "testing") as EnvironmentName;
-const NVM_PLAN_ID = process.env.NVM_PLAN_ID ?? "";
-
-if (!NVM_API_KEY || !NVM_PLAN_ID) {
- console.error("NVM_API_KEY and NVM_PLAN_ID are required.");
- process.exit(1);
-}
-
-// Initialize Nevermined Payments SDK
-const payments = Payments.getInstance({
- nvmApiKey: NVM_API_KEY,
- environment: NVM_ENVIRONMENT,
-});
-
-/**
- * Helper to decode base64 JSON from headers
- */
-function decodeBase64Json(base64: string): unknown {
- const json = Buffer.from(base64, "base64").toString("utf-8");
- return JSON.parse(json);
-}
-
-/**
- * Helper to format JSON for console output
- */
-function prettyJson(obj: unknown): string {
- return JSON.stringify(obj, null, 2);
-}
-
-async function main() {
- console.log("=".repeat(60));
- console.log("x402 Payment Flow Demo");
- console.log("=".repeat(60));
- console.log(`\nServer: ${SERVER_URL}`);
- console.log(`Plan ID: ${NVM_PLAN_ID}`);
-
- // ============================================================
- // Step 1: Request without token -> Expect 402
- // ============================================================
- console.log("\n" + "=".repeat(60));
- console.log("STEP 1: Request without payment token");
- console.log("=".repeat(60));
-
- const response1 = await fetch(`${SERVER_URL}/ask`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({ query: "What is 2+2?" }),
- });
-
- console.log(`\nStatus: ${response1.status} ${response1.statusText}`);
-
- if (response1.status !== 402) {
- console.error("Expected 402 Payment Required, got:", response1.status);
- process.exit(1);
- }
-
- // ============================================================
- // Step 2: Decode payment requirements from header
- // ============================================================
- console.log("\n" + "=".repeat(60));
- console.log("STEP 2: Decode payment requirements from header");
- console.log("=".repeat(60));
-
- const paymentRequiredHeader = response1.headers.get(X402_HEADERS.PAYMENT_REQUIRED);
-
- if (!paymentRequiredHeader) {
- console.error(`Missing '${X402_HEADERS.PAYMENT_REQUIRED}' header in 402 response`);
- process.exit(1);
- }
-
- console.log(`\nHeader '${X402_HEADERS.PAYMENT_REQUIRED}' (base64):`);
- console.log(paymentRequiredHeader.substring(0, 80) + "...");
-
- const paymentRequired = decodeBase64Json(paymentRequiredHeader);
- console.log("\nDecoded Payment Requirements:");
- console.log(prettyJson(paymentRequired));
-
- // Also print the JSON body
- const body1 = await response1.json();
- console.log("\nResponse body:");
- console.log(prettyJson(body1));
-
- // ============================================================
- // Step 3: Generate x402 access token (scheme-aware)
- // ============================================================
- console.log("\n" + "=".repeat(60));
- console.log("STEP 3: Generate x402 access token");
- console.log("=".repeat(60));
-
- // Read scheme from the 402 response to determine payment type
- const paymentRequiredObj = paymentRequired as any;
- const scheme: X402SchemeType =
- paymentRequiredObj?.accepts?.[0]?.scheme || "nvm:erc4337";
- console.log(`\nDetected scheme: ${scheme}`);
-
- let tokenResult;
- if (scheme === "nvm:card-delegation") {
- // Fiat flow: list enrolled cards and create a card-delegation token
- console.log("\nFiat plan detected — listing enrolled payment methods...");
- const paymentMethods = await payments.delegation.listPaymentMethods();
- if (paymentMethods.length === 0) {
- console.error(
- "No enrolled payment methods. Enroll a card in the Nevermined App first."
- );
- process.exit(1);
- }
- const pm = paymentMethods[0];
- console.log(`Using payment method: ${pm.brand} ****${pm.last4}`);
-
- tokenResult = await payments.x402.getX402AccessToken(
- NVM_PLAN_ID,
- undefined,
- undefined,
- undefined,
- undefined,
- {
- scheme: "nvm:card-delegation",
- delegationConfig: {
- providerPaymentMethodId: pm.id,
- spendingLimitCents: 10000,
- durationSecs: 604800,
- currency: "usd",
- },
- }
- );
- } else {
- // Crypto flow: standard ERC-4337 token
- console.log("\nCalling payments.x402.getX402AccessToken()...");
- tokenResult = await payments.x402.getX402AccessToken(NVM_PLAN_ID);
- }
-
- const accessToken = tokenResult.accessToken;
-
- console.log("\nToken generated successfully!");
- console.log(`Token length: ${accessToken.length} characters`);
- console.log(`Token preview: ${accessToken.substring(0, 50)}...`);
-
- // Decode and show token structure (it's base64-encoded JSON)
- try {
- const decodedToken = decodeBase64Json(accessToken);
- console.log("\nDecoded token structure:");
- console.log(prettyJson(decodedToken));
- } catch {
- console.log("\n(Token is not base64 JSON - showing raw)");
- }
-
- // ============================================================
- // Step 4: Request with token -> Expect success
- // ============================================================
- console.log("\n" + "=".repeat(60));
- console.log("STEP 4: Request with payment token");
- console.log("=".repeat(60));
-
- console.log(`\nSending request with '${X402_HEADERS.PAYMENT_SIGNATURE}' header...`);
-
- const response2 = await fetch(`${SERVER_URL}/ask`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- [X402_HEADERS.PAYMENT_SIGNATURE]: accessToken,
- },
- body: JSON.stringify({ query: "What is 2+2?" }),
- });
-
- console.log(`\nStatus: ${response2.status} ${response2.statusText}`);
-
- if (response2.status !== 200) {
- console.error("Expected 200 OK, got:", response2.status);
- const errorBody = await response2.text();
- console.error("Response:", errorBody);
- process.exit(1);
- }
-
- const body2 = await response2.json();
- console.log("\nResponse body:");
- console.log(prettyJson(body2));
-
- // ============================================================
- // Step 5: Check for settlement response header
- // ============================================================
- console.log("\n" + "=".repeat(60));
- console.log("STEP 5: Check settlement response header");
- console.log("=".repeat(60));
-
- const paymentResponseHeader = response2.headers.get(X402_HEADERS.PAYMENT_RESPONSE);
-
- if (paymentResponseHeader) {
- console.log(`\nHeader '${X402_HEADERS.PAYMENT_RESPONSE}' found!`);
- console.log(`(base64): ${paymentResponseHeader.substring(0, 80)}...`);
-
- try {
- const settlementResponse = decodeBase64Json(paymentResponseHeader);
- console.log("\nDecoded Settlement Response:");
- console.log(prettyJson(settlementResponse));
- } catch {
- console.log("\n(Could not decode as JSON)");
- console.log(paymentResponseHeader);
- }
- } else {
- console.log(`\nNo '${X402_HEADERS.PAYMENT_RESPONSE}' header in response.`);
- console.log("(Settlement happens asynchronously after response is sent)");
- }
-
- // ============================================================
- // Summary
- // ============================================================
- console.log("\n" + "=".repeat(60));
- console.log("FLOW COMPLETE!");
- console.log("=".repeat(60));
- console.log(`
-x402 Payment Flow Summary:
-1. Request without token -> 402 Payment Required
-2. Decoded payment-required -> Plan ID, scheme, network
-3. Generated access token -> Using Nevermined SDK
-4. Request with token -> 200 OK + AI response
-5. Settlement -> Credits burned asynchronously
-`);
-}
-
-main().catch((error) => {
- console.error("Error:", error);
- process.exit(1);
-});
diff --git a/http-simple-agent-ts/tsconfig.json b/http-simple-agent-ts/tsconfig.json
index 783df977..627f0e60 100644
--- a/http-simple-agent-ts/tsconfig.json
+++ b/http-simple-agent-ts/tsconfig.json
@@ -10,5 +10,5 @@
"rootDir": "src"
},
"include": ["src/**/*"],
- "exclude": ["node_modules", "dist", "src/agent-observability.ts", "src/client.ts"]
+ "exclude": ["node_modules", "dist"]
}
diff --git a/showcase/components/LiveRunPanel.tsx b/showcase/components/LiveRunPanel.tsx
index 248c085a..b66aff6c 100644
--- a/showcase/components/LiveRunPanel.tsx
+++ b/showcase/components/LiveRunPanel.tsx
@@ -38,10 +38,11 @@ function readStoredKey(): string | null {
}
}
-// Current page URL with any nvm_api_key param stripped — used as the callback target.
+// Current page URL with any nvm_api_key stripped from BOTH query and fragment — the callback target.
function cleanCallbackUrl(): string {
const u = new URL(window.location.href);
u.searchParams.delete(KEY_STORAGE);
+ u.hash = "";
return u.toString();
}
@@ -68,12 +69,19 @@ export default function LiveRunPanel({
const [payg, setPayg] = useState(false);
const logRef = useRef(null);
- // On mount: capture an nvm_api_key returned by the Nevermined App callback (query string),
- // persist it, and clean the URL — otherwise fall back to a previously stored key.
+ // On mount: capture an nvm_api_key returned by the Nevermined App callback, persist it, and clean
+ // the URL — otherwise fall back to a previously stored key.
+ //
+ // SECURITY NOTE: the App's /auth/cli flow currently returns the key as a QUERY param
+ // (?nvm_api_key=…), which lands in the showcase server's (and any proxy/CDN's) access logs on the
+ // redirect's request line — a live key in plaintext logs. The real fix is App-side: return it in
+ // the URL FRAGMENT (#nvm_api_key=…), which browsers never send to the server. We read both here so
+ // that change needs no update on this side; until then, see deploy/argocd README for the log-scrub note.
useEffect(() => {
try {
const params = new URLSearchParams(window.location.search);
- const returned = params.get(KEY_STORAGE);
+ const hashParams = new URLSearchParams(window.location.hash.replace(/^#/, ""));
+ const returned = params.get(KEY_STORAGE) || hashParams.get(KEY_STORAGE);
if (returned) {
localStorage.setItem(KEY_STORAGE, returned);
window.history.replaceState({}, "", cleanCallbackUrl());
diff --git a/showcase/lib/live-agent.mjs b/showcase/lib/live-agent.mjs
index 6bd0a325..e292a811 100644
--- a/showcase/lib/live-agent.mjs
+++ b/showcase/lib/live-agent.mjs
@@ -67,30 +67,53 @@ function resolveKey(reqApiKey) {
}
// ── per-key singletons ────────────────────────────────────────────────────────
+const DELEGATION_DURATION_SECS = 604800; // 7 days
+const DELEGATION_LIMIT_CENTS = 500; // $5 — scaled to a demo (calls cost 1..7 credits), on the VIEWER's account
+const MAX_KEYS = 200; // bound the per-key caches so they don't grow for the life of the process
+
const _payments = new Map(); // key -> Payments
-const _delegation = new Map(); // key -> delegationId
+const _delegation = new Map(); // key -> { id, expiresAt }
+
+// Simple FIFO bound — evict the oldest entry once over the cap.
+function capMap(m) {
+ while (m.size > MAX_KEYS) m.delete(m.keys().next().value);
+}
function paymentsFor(key) {
- if (!_payments.has(key)) _payments.set(key, Payments.getInstance({ nvmApiKey: key }));
+ if (!_payments.has(key)) {
+ _payments.set(key, Payments.getInstance({ nvmApiKey: key }));
+ capMap(_payments);
+ }
return _payments.get(key);
}
async function delegationFor(key) {
- if (!_delegation.has(key)) {
- const { delegationId } = await paymentsFor(key).delegation.createDelegation({
- provider: "erc4337",
- spendingLimitCents: 10000,
- durationSecs: 604800,
- currency: "usdc",
- });
- _delegation.set(key, delegationId);
- }
- return _delegation.get(key);
+ const cached = _delegation.get(key);
+ // Re-mint past (or near) expiry — a cached-forever delegationId would 502 every call after 7 days.
+ if (cached && cached.expiresAt > Date.now() + 60_000) return cached.id;
+ const { delegationId } = await paymentsFor(key).delegation.createDelegation({
+ provider: "erc4337",
+ spendingLimitCents: DELEGATION_LIMIT_CENTS,
+ durationSecs: DELEGATION_DURATION_SECS,
+ currency: "usdc",
+ });
+ _delegation.set(key, { id: delegationId, expiresAt: Date.now() + DELEGATION_DURATION_SECS * 1000 });
+ capMap(_delegation);
+ return delegationId;
+}
+// Drop a key's cached delegation so the next call re-mints (used after a delegation-expiry error).
+function invalidateDelegation(key) {
+ _delegation.delete(key);
}
+const CITY_STOPWORDS = new Set([
+ "How", "What", "Where", "When", "Why", "Who", "Is", "The", "Weather", "Forecast", "Show", "Give", "Tell", "Today",
+]);
function cityOf(message) {
const inCity = message.match(/\bin\s+([A-Za-zÀ-ſ][A-Za-zÀ-ſ .'-]+)/);
if (inCity) return inCity[1].trim().replace(/[.?!]+$/, "");
- const cap = message.match(/\b([A-Z][A-Za-zÀ-ſ]{2,})\b/);
- return cap ? cap[1] : "Lisbon";
+ // No "in " clause: take the LAST capitalised word that isn't a question/stop word,
+ // so "How is Madrid looking?" resolves to Madrid, not "How".
+ const caps = [...message.matchAll(/\b([A-Z][A-Za-zÀ-ſ]{2,})\b/g)].map((m) => m[1]).filter((w) => !CITY_STOPWORDS.has(w));
+ return caps.length ? caps[caps.length - 1] : "Lisbon";
}
// "5-day forecast" / "next 3 days" / "7 day" → the number of forecast days (pay-as-you-go).
@@ -227,6 +250,8 @@ export async function liveRespond(state, req) {
const next = { authorized: true, balance: s.balance - cfg.credits };
return { status: 200, body: { kind: "paid", answer, credits: cfg.credits, balance: next.balance }, state: next };
} catch (e) {
+ // If the delegation was rejected (e.g. expired — BCK.ROUTER.0003), drop it so the next call re-mints.
+ if (/deleg|expired|BCK\.ROUTER\.0003/i.test(e.message || "")) invalidateDelegation(key);
return { status: 502, body: { kind: "error", error: `live agent call failed: ${e.message}` }, state: s };
}
}
From cf14cf5f023dc6da2809f79504d0ad101e56a3c5 Mon Sep 17 00:00:00 2001
From: Aitor <1726644+aaitor@users.noreply.github.com>
Date: Sat, 5 Sep 2026 12:22:45 +0200
Subject: [PATCH 24/24] fix(http-ts,showcase): address PR #69 round-2 review
- smoke.ts: drop the deprecated `environment` option + NVM_ENVIRONMENT (the twin the round-1 fix missed).
- cityOf: bound the 'in ' capture so 'in Tokyo today' -> Tokyo while 'New York' still works.
- Remove dead NVM_ENVIRONMENT from both deploy manifests and the runbook (helm --set + rendered snippet).
---
http-simple-agent-ts/deploy/argocd/README.md | 3 ---
.../deploy/argocd/weather-x402-agent-staging.yaml | 2 --
.../deploy/argocd/weather-x402-agent.yaml | 2 --
http-simple-agent-ts/scripts/smoke.ts | 8 +++-----
showcase/lib/live-agent.mjs | 4 +++-
5 files changed, 6 insertions(+), 13 deletions(-)
diff --git a/http-simple-agent-ts/deploy/argocd/README.md b/http-simple-agent-ts/deploy/argocd/README.md
index b15aa83e..db9b88b8 100644
--- a/http-simple-agent-ts/deploy/argocd/README.md
+++ b/http-simple-agent-ts/deploy/argocd/README.md
@@ -106,7 +106,6 @@ helm template weather-x402-agent . -n agents \
--set replicaCount=1 \
--set initCommand="yarn start" \
--set ingress.rateLimitEnabled=true \
- --set env.NVM_ENVIRONMENT=sandbox \
--set env.NVM_API_KEY="gcp:secretmanager:projects/112425687177/secrets/tutorials-weather-nvm-api-key"
```
@@ -126,8 +125,6 @@ Rendered (helm v3.10.1), no template errors, four resources:
value: gcp:secretmanager:projects/112425687177/secrets/tutorials-weather-nvm-api-key
- name: OPENAI_API_KEY
value:
- - name: NVM_ENVIRONMENT
- value: sandbox
- name: AGENT_DID
value:
... (unrelated fixed keys for other agents, all empty here) ...
diff --git a/http-simple-agent-ts/deploy/argocd/weather-x402-agent-staging.yaml b/http-simple-agent-ts/deploy/argocd/weather-x402-agent-staging.yaml
index e09b7999..21109f4e 100644
--- a/http-simple-agent-ts/deploy/argocd/weather-x402-agent-staging.yaml
+++ b/http-simple-agent-ts/deploy/argocd/weather-x402-agent-staging.yaml
@@ -25,8 +25,6 @@ spec:
value: Always
- name: replicaCount
value: "1"
- - name: env.NVM_ENVIRONMENT
- value: sandbox
- name: env.NVM_API_KEY
value: gcp:secretmanager:projects/112425687177/secrets/tutorials-weather-nvm-api-key
- name: env.PLAN_ID_CREDITS
diff --git a/http-simple-agent-ts/deploy/argocd/weather-x402-agent.yaml b/http-simple-agent-ts/deploy/argocd/weather-x402-agent.yaml
index 6d67381d..78f55f2f 100644
--- a/http-simple-agent-ts/deploy/argocd/weather-x402-agent.yaml
+++ b/http-simple-agent-ts/deploy/argocd/weather-x402-agent.yaml
@@ -25,8 +25,6 @@ spec:
value: Always
- name: replicaCount
value: "1"
- - name: env.NVM_ENVIRONMENT
- value: sandbox
- name: env.NVM_API_KEY
value: gcp:secretmanager:projects/112425687177/secrets/tutorials-weather-nvm-api-key
- name: env.PLAN_ID_CREDITS
diff --git a/http-simple-agent-ts/scripts/smoke.ts b/http-simple-agent-ts/scripts/smoke.ts
index 6a73642d..b80a8a24 100644
--- a/http-simple-agent-ts/scripts/smoke.ts
+++ b/http-simple-agent-ts/scripts/smoke.ts
@@ -1,13 +1,11 @@
import "dotenv/config";
-import { Payments, EnvironmentName } from "@nevermined-io/payments";
+import { Payments } from "@nevermined-io/payments";
import { X402_HEADERS } from "@nevermined-io/payments/express";
const BASE = process.env.SERVER_URL || "http://localhost:3000";
const PLAN = process.env.PLAN_ID_CREDITS!;
-const payments = Payments.getInstance({
- nvmApiKey: process.env.NVM_API_KEY!,
- environment: (process.env.NVM_ENVIRONMENT || "sandbox") as EnvironmentName,
-});
+// Environment is derived from the API-key prefix (sandbox:/live:); no `environment` option.
+const payments = Payments.getInstance({ nvmApiKey: process.env.NVM_API_KEY! });
const assert = (c: boolean, m: string) => { if (!c) throw new Error("FAIL: " + m); };
async function main() {
diff --git a/showcase/lib/live-agent.mjs b/showcase/lib/live-agent.mjs
index e292a811..fcfd2ef7 100644
--- a/showcase/lib/live-agent.mjs
+++ b/showcase/lib/live-agent.mjs
@@ -108,7 +108,9 @@ const CITY_STOPWORDS = new Set([
"How", "What", "Where", "When", "Why", "Who", "Is", "The", "Weather", "Forecast", "Show", "Give", "Tell", "Today",
]);
function cityOf(message) {
- const inCity = message.match(/\bin\s+([A-Za-zÀ-ſ][A-Za-zÀ-ſ .'-]+)/);
+ // "in " — bound to one word plus an optional Capitalised second word ("New York"),
+ // so trailing lowercase words don't get swallowed ("in Tokyo today" -> "Tokyo", not "Tokyo today").
+ const inCity = message.match(/\bin\s+([A-Za-zÀ-ſ][A-Za-zÀ-ſ.'-]*(?:\s+[A-Z][A-Za-zÀ-ſ.'-]*)?)/);
if (inCity) return inCity[1].trim().replace(/[.?!]+$/, "");
// No "in " clause: take the LAST capitalised word that isn't a question/stop word,
// so "How is Madrid looking?" resolves to Madrid, not "How".