diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3635f4a..e2049a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,8 @@ name: CI on: pull_request: push: + branches: + - main permissions: {} @@ -32,5 +34,9 @@ jobs: run: pnpm run format:check - name: Build run: pnpm run build + - name: Lint + run: pnpm run lint + - name: Knip + run: pnpm run knip - name: Integration test run: pnpm run test:integration diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..bb1c308 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,64 @@ +import js from "@eslint/js"; +import tseslint from "typescript-eslint"; + +export default [ + { + ignores: ["dist/**"], + }, + js.configs.recommended, + { + files: ["**/*.{js,mjs,cjs,ts}"], + rules: { + curly: ["error", "all"], + "no-restricted-syntax": [ + "error", + { + selector: "CallExpression[callee.name='Boolean']", + message: + "Avoid truthiness coercion. Use an explicit condition or comparison instead.", + }, + { + selector: + "UnaryExpression[operator='!'] > BinaryExpression[operator='!=']", + message: + "Avoid negating comparisons. Use the inverse operator directly.", + }, + { + selector: + "UnaryExpression[operator='!'] > BinaryExpression[operator='!==']", + message: + "Avoid negating comparisons. Use the inverse operator directly.", + }, + ], + }, + }, + ...[ + ...tseslint.configs.strictTypeChecked, + ...tseslint.configs.stylisticTypeChecked, + ].map((config) => ({ + ...config, + files: ["**/*.ts"], + })), + { + files: ["**/*.ts"], + languageOptions: { + parserOptions: { + project: "./tsconfig.eslint.json", + tsconfigRootDir: import.meta.dirname, + }, + }, + rules: { + "@typescript-eslint/consistent-type-assertions": [ + "error", + { + assertionStyle: "never", + }, + ], + "@typescript-eslint/consistent-type-definitions": ["error", "type"], + "@typescript-eslint/prefer-readonly": "error", + "@typescript-eslint/strict-boolean-expressions": "error", + "@typescript-eslint/strict-void-return": "error", + "@typescript-eslint/switch-exhaustiveness-check": "error", + }, + }, +]; diff --git a/package.json b/package.json index d284a13..17a41a5 100644 --- a/package.json +++ b/package.json @@ -40,22 +40,28 @@ "build": "tsdown && tsc --emitDeclarationOnly", "format": "prettier --write .", "format:check": "prettier --check .", + "knip": "knip --strict --treat-config-hints-as-errors --treat-tag-hints-as-errors", + "lint": "eslint .", "test:integration": "pnpm run build && tsc --noEmit -p tsconfig.test.json && vitest run test/integration" }, "dependencies": { + "@langfuse/otel": "^5.10.1", "@opencode-ai/plugin": "^1.15.13", - "@opentelemetry/api": "^1.9.1" + "@opentelemetry/api": "^1.9.1", + "@opentelemetry/resources": "^2.10.0", + "@opentelemetry/sdk-trace-base": "^2.10.0", + "@opentelemetry/sdk-trace-node": "^2.10.0", + "effect": "^3.22.1" }, "devDependencies": { - "@langfuse/otel": "^5.4.1", - "@opentelemetry/resources": "^2.7.1", - "@opentelemetry/sdk-trace-base": "^2.7.1", - "@opentelemetry/sdk-trace-node": "^2.7.1", + "@eslint/js": "^10.0.1", "@types/node": "^26.1.2", - "effect": "^3.21.2", + "eslint": "^10.8.1", + "knip": "^6.32.2", "prettier": "^3.8.3", "tsdown": "0.22.14", "typescript": "^6.0.3", + "typescript-eslint": "^8.67.0", "vitest": "4.1.6" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9b2cb10..a5a1a6e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,56 +8,136 @@ importers: .: dependencies: + '@langfuse/otel': + specifier: ^5.10.1 + version: 5.10.1(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1))(@opentelemetry/exporter-trace-otlp-http@0.221.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.10.0(@opentelemetry/api@1.9.1)) '@opencode-ai/plugin': specifier: ^1.15.13 version: 1.15.13 '@opentelemetry/api': specifier: ^1.9.1 version: 1.9.1 - devDependencies: - '@langfuse/otel': - specifier: ^5.4.1 - version: 5.4.1(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/exporter-trace-otlp-http@0.218.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1)) '@opentelemetry/resources': - specifier: ^2.7.1 - version: 2.7.1(@opentelemetry/api@1.9.1) + specifier: ^2.10.0 + version: 2.10.0(@opentelemetry/api@1.9.1) '@opentelemetry/sdk-trace-base': - specifier: ^2.7.1 - version: 2.7.1(@opentelemetry/api@1.9.1) + specifier: ^2.10.0 + version: 2.10.0(@opentelemetry/api@1.9.1) '@opentelemetry/sdk-trace-node': - specifier: ^2.7.1 - version: 2.7.1(@opentelemetry/api@1.9.1) + specifier: ^2.10.0 + version: 2.10.0(@opentelemetry/api@1.9.1) + effect: + specifier: ^3.22.1 + version: 3.22.1 + devDependencies: + '@eslint/js': + specifier: ^10.0.1 + version: 10.0.1(eslint@10.8.1(jiti@2.7.0)) '@types/node': specifier: ^26.1.2 version: 26.1.2 - effect: - specifier: ^3.21.2 - version: 3.21.2 + eslint: + specifier: ^10.8.1 + version: 10.8.1(jiti@2.7.0) + knip: + specifier: ^6.32.2 + version: 6.32.2 prettier: specifier: ^3.8.3 version: 3.8.3 tsdown: specifier: 0.22.14 - version: 0.22.14(typescript@6.0.3) + version: 0.22.14(oxc-resolver@11.24.2)(typescript@6.0.3)(unrun@0.3.1) typescript: specifier: ^6.0.3 version: 6.0.3 + typescript-eslint: + specifier: ^8.67.0 + version: 8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3) vitest: specifier: 4.1.6 - version: 4.1.6(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(vite@8.2.0(@types/node@26.1.2)(yaml@2.9.0)) + version: 4.1.6(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(yaml@2.9.0)) packages: + '@emnapi/core@1.11.2': + resolution: {integrity: sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==} + + '@emnapi/runtime@1.11.2': + resolution: {integrity: sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==} + + '@emnapi/wasi-threads@1.2.2': + resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} + + '@eslint-community/eslint-utils@4.10.1': + resolution: {integrity: sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.23.5': + resolution: {integrity: sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/config-helpers@0.7.0': + resolution: {integrity: sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/core@1.2.1': + resolution: {integrity: sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/js@10.0.1': + resolution: {integrity: sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + peerDependencies: + eslint: ^10.0.0 + peerDependenciesMeta: + eslint: + optional: true + + '@eslint/object-schema@3.0.5': + resolution: {integrity: sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/plugin-kit@0.7.2': + resolution: {integrity: sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@humanfs/core@0.19.2': + resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.8': + resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==} + engines: {node: '>=18.18.0'} + + '@humanfs/types@0.15.0': + resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - '@langfuse/core@5.4.1': - resolution: {integrity: sha512-TjaRTr9fGqaWuyYKFSezKxN4DWAaK/lq//hRMw8rQKFkZUs6vTgUODxqZTFTR6np5VnLVw+eZLlnHROPKbXqdg==} + '@langfuse/core@5.10.1': + resolution: {integrity: sha512-W8UArizWSy1DdeLGTsTwJwl7bkA7OQQcGZW8RtoopXyJZ93O0rwG7wzzeiZjhjpj5OtWOUTEaJuNkwOrF31UDw==} peerDependencies: '@opentelemetry/api': ^1.9.0 - '@langfuse/otel@5.4.1': - resolution: {integrity: sha512-w69aVC2fTmd7hyCTaX8zhhivHlsGVgZ551XOf6yMSOi3k8tlDML4dinnjJUP/6qTvdH54NYcmAIp5KZRbkouxg==} + '@langfuse/otel@5.10.1': + resolution: {integrity: sha512-F2153e4PoJ1cN+5tM/xnsS44aQCQwK3p0nPk4NEpITV5pMTqiQVyvpkAvly8GKQ5Qjjr7heJ1dFtghW43ysyPQ==} engines: {node: '>=20'} peerDependencies: '@opentelemetry/api': ^1.9.0 @@ -95,6 +175,13 @@ packages: cpu: [x64] os: [win32] + '@napi-rs/wasm-runtime@1.2.3': + resolution: {integrity: sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==} + engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} + peerDependencies: + '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.4 + '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.4 + '@opencode-ai/plugin@1.15.13': resolution: {integrity: sha512-NFwZGhmxIPijtfz9swPJXDmhOpq4UWP8WjEE7GEMr7FwtJrK/hv6v36nFimed5+OKk+pQCrTJn/vhRW7Io72IA==} peerDependencies: @@ -112,81 +199,315 @@ packages: '@opencode-ai/sdk@1.15.13': resolution: {integrity: sha512-4TwojIoQ8EG6/mVBuUVYZXiFcwNmiiytEnjnvyuvSJjGwFIlw2YIBFxtSVC3FbwwbwHT63teh1RHiQUUC4U5xw==} - '@opentelemetry/api-logs@0.218.0': - resolution: {integrity: sha512-fmEWp5kXlGEc3i/lR698Hz41DfGyN4Tbe4g7L1AxSc7fF8Xeh/FQ9Quqpa9dVA413Q1Ad43QOLzU4JoXgbFPWw==} + '@opentelemetry/api-logs@0.221.0': + resolution: {integrity: sha512-OlanaW1vv7ufTqQ3/fPLI4arGt5ZoM+P8abOMki6uEYnpRazepSWDwDnnw+la7kE26SHVC18//SMccrDvLKOXQ==} engines: {node: '>=8.0.0'} '@opentelemetry/api@1.9.1': resolution: {integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==} engines: {node: '>=8.0.0'} - '@opentelemetry/context-async-hooks@2.7.1': - resolution: {integrity: sha512-OPFBYuXEn1E4ja3Y6eeA7O+ZnLBNcXTV5Cgsn1VaqBZ6hC5FnpZPLBNme1LJY8ZtF4aOujPKFoeWN4ik487KuQ==} + '@opentelemetry/context-async-hooks@2.10.0': + resolution: {integrity: sha512-bvyMcgLEkozzSzpEEEo1OMoeQ97bxj6Qs2uN3mPrSdDvObMI1myffD/BPqcLlzZO9//d1SqQA/WPw7Cz2AiqhA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' - '@opentelemetry/core@2.7.1': - resolution: {integrity: sha512-QAqIj32AtK6+pEVNG7EOVxHdE06RP+FM5qpiEJ4RtDcFIqKUZHYhl7/7UY5efhwmwNAg7j8QbJVBLxMerc0+gw==} + '@opentelemetry/core@2.10.0': + resolution: {integrity: sha512-/wNZ8twnEQQA4HoHu22+vcsdru6pWPWxW+7w+FlxT6Id7PE/WIbZmVKkte+PF72e0F2dnImFeHD2syyE1Mw6MQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' - '@opentelemetry/exporter-trace-otlp-http@0.218.0': - resolution: {integrity: sha512-8dqezsmPhtKitIK/eTipZhYl9EX2/gNQ5zUMhaz3uxEURwfkNf8IPvo6yNfrzbxdtpAOybS/+h7wmIWYqFSpiw==} + '@opentelemetry/exporter-trace-otlp-http@0.221.0': + resolution: {integrity: sha512-AySXiKoC+meiWm6zdVj5T2LnPDZuatveBby1cMOeQteIWsYXAUxs8Sru13G2pVSPrUXz6vF+og7QVBX6GdC/oQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/otlp-exporter-base@0.218.0': - resolution: {integrity: sha512-ZwqpkNL5W7RyGJPDZ9g06DvKp8KFTWPJPN12anpMQYSKpTSU0z3EIZuPq9vPGpS8siFyOqDYDAuCwlNO9FqgbA==} + '@opentelemetry/otlp-exporter-base@0.221.0': + resolution: {integrity: sha512-UFPIq80OH3Ns/oPFHRj14d4DTOxUo+MUFU8hUiCq5jTqFhdeJnfVSANHT+xp92409cA+oxzvlZCe6NM1wvCuBA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/otlp-transformer@0.218.0': - resolution: {integrity: sha512-CFaKH87WAzjuJ4awowTTLzUvMfaRfiOFG5+qm5S5ncyalRtN4ecQ+YmuANJSCrVPuvZFEkUgKhBPBndxi3rHsQ==} + '@opentelemetry/otlp-transformer@0.221.0': + resolution: {integrity: sha512-lg6lkOU08Az23jVcn/0Els9HP+V8PnR4Km6p0KgpTggS0n/WuhnmY64rSh83Of9iR9nD+dpWr6adlcX8KzAwjg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/resources@2.7.1': - resolution: {integrity: sha512-DeT6KKolmC4e/dRQvMQ/RwlnzhaqeiFOXY5ngoOPJ07GgVVKxZOg9EcrNZb5aTzUn+iCrJldAgOfQm1O/QfPAQ==} + '@opentelemetry/resources@2.10.0': + resolution: {integrity: sha512-q6MMm2zhggzsHVNbabYwut+a6nbuQQe3URUoxaojM/8K1IBfwwPzvxIjNi2/lI1TFe+fMHMW9MWhrtDLEXEnkA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.3.0 <1.10.0' - '@opentelemetry/sdk-logs@0.218.0': - resolution: {integrity: sha512-QvnNdugatFTVCJXH0Mcu7GOOJSylA9j127kIezOE4YwTI4YbowRons2K4WZTv5FMS8T4q9P0NdaRHdkSmeAIag==} + '@opentelemetry/sdk-logs@0.221.0': + resolution: {integrity: sha512-FaDcazjyMp7TZZZAsqbo4IkovP0UegoCu0EBkiNt+qCqvUf7FPAsfcrZ3+ZEkKgXZ/jHafop+JoGPDk3A0SmLg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.4.0 <1.10.0' - '@opentelemetry/sdk-metrics@2.7.1': - resolution: {integrity: sha512-MpDJdkiFDs3Pm1RHO3KByuZbuBdJEXEAkiC0+yJdsZGVCdf1RpHR6n+LHDcS7ffmfrt5kVCzJSCfm4z2C7v0uQ==} + '@opentelemetry/sdk-metrics@2.10.0': + resolution: {integrity: sha512-t6r1VSvXNtSDnPXU1FbZeetJb7yyovHmgu0wRSoftxtE0g2rSNhQZQUy69sRUCL+iioJpX8SN/S6wq6ZtvLySQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.9.0 <1.10.0' - '@opentelemetry/sdk-trace-base@2.7.1': - resolution: {integrity: sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==} + '@opentelemetry/sdk-trace-base@2.10.0': + resolution: {integrity: sha512-GuYQQT7QD2EeO8lcZLRQzcbOyhqAzL+6WWTKTU9mSUBYBazkEDl+VrQcXQhbB08OWM9anD1aHleVadzulpOaUQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.3.0 <1.10.0' - '@opentelemetry/sdk-trace-node@2.7.1': - resolution: {integrity: sha512-pCpQxU68lV+I9s9svqMyVu5iHdDDUnqUpSxqwyCU8A9ejEsSnMPCbearwsUO4yk08ZJzAIUCFuReMdVQvHrdvg==} + '@opentelemetry/sdk-trace-node@2.10.0': + resolution: {integrity: sha512-GZK/G6oZyBLGlH1pUgeDch7D91KoHd2uotUGIkWCPi9GI5T9X0p4L7nNAMDR1BQjkRYoDqo+ddfVx9t5Uhys+Q==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' - '@opentelemetry/semantic-conventions@1.41.1': - resolution: {integrity: sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==} + '@opentelemetry/sdk-trace@2.10.0': + resolution: {integrity: sha512-MfQGq3GRmTh5fM/y+OjaO0vj6+luCB1XO2gfXCalKCfgKw0eHL++sm75DNweC6ohlp+aFvACqeE0fYayqdRaoQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/semantic-conventions@1.43.0': + resolution: {integrity: sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==} engines: {node: '>=14'} + '@oxc-parser/binding-android-arm-eabi@0.143.0': + resolution: {integrity: sha512-n9uozULWflPqBtdmI8lAabLqGKNgLVNN0ZH8HfgCwpKGNtzRzauB76jTiW/3YLkcA7N1zskpi9GdVnZuu1SAvg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxc-parser/binding-android-arm64@0.143.0': + resolution: {integrity: sha512-9BbdjHETk6O3zH/DDid9IgBtF0GlpLabNKN231uraXpRDSfY+iiZxTP5bk1Z63GBownVdhdINFIeddmMz4MzpQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxc-parser/binding-darwin-arm64@0.143.0': + resolution: {integrity: sha512-gh+6ecoHUy4/sUcolBl/1qPXKBbYNxFY0Pk0ujgQvINTMSftJY7o4yb8gOkDJPeZeB8+a+u7xTe6umoP8N5HFA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxc-parser/binding-darwin-x64@0.143.0': + resolution: {integrity: sha512-qd1hl2d+lXgHv/VQ/M9qm8TrMC5T4RqDBwtOnl+1D0QMjwcz+8AaB4JSg8STgeag0GP6a6L74XEGAsrTSJWNzQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxc-parser/binding-freebsd-x64@0.143.0': + resolution: {integrity: sha512-M5XXcNa7aOqLPKTR41msfghKu2yQ4xWvCm11/gwU0JzOzHNk5sgW//rVEjJ+LO48+VDAMzXTSzurUVxIDKwozw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxc-parser/binding-linux-arm-gnueabihf@0.143.0': + resolution: {integrity: sha512-T/GXusuOkPNQhCQCSBbcU/N8j0rAypuDBl1IyFK+lyYT594XsVz80clPC/OtbSSpBGyJxj8uYEfctxVuxVYoww==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm-musleabihf@0.143.0': + resolution: {integrity: sha512-oKu4RcBlXSqo3OC62dp6YTnQaZIurNDpCX3BnAM3+bJxt7s8J2TJKMnC0UYer1qhlRaDCg6wkTaTw+2IlsZ12w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm64-gnu@0.143.0': + resolution: {integrity: sha512-WJBbD186AZmMGaSIhlktC+rPl8L3peCTXAh88Ih9uEvK0en2mPojGyCGYiL6mHtV1RPV3JyfJW5t6n5hh0lXhA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-arm64-musl@0.143.0': + resolution: {integrity: sha512-t1AcYOwEzgceadT4v5e+vaCCb0AncCA3v5AyzfBAz/tMq11qzVccXKzNHtkWdjBsgvTKwRkaUF3QvT4kot8vcQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-linux-ppc64-gnu@0.143.0': + resolution: {integrity: sha512-RsnO/NoD8376LMJq8JS8TwI0ieNaFRTuNe2GVJntQg6gwZNMENZsEbknHdVwjpOmxdGLGodcwaGSbAeRr5Bgjw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-riscv64-gnu@0.143.0': + resolution: {integrity: sha512-48fSVfR9TZi5CASZFyv0VC6z6BCoeihFsX031mAD/oSH7d9PYsPgIqza7d9mjP7Z2KTEpTFyH6SIu0Ui6R1vdg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-riscv64-musl@0.143.0': + resolution: {integrity: sha512-T8CpdD+SfE01DnIOD4HpVxu0ZJOfMJ/VhCvikKfaXAxkZ+9veyLM/D2hpi7Y2hFUyPmVQO3FNZHmYzV/WlVR4g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-linux-s390x-gnu@0.143.0': + resolution: {integrity: sha512-QLdeMsCcacenPEFsfxnBUDF1y6opyz5+fmOz9bfD5Y7fiGCMupUCuB3KTPQhNwshIG1P9fPqar9MHxuBDd4bwQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-x64-gnu@0.143.0': + resolution: {integrity: sha512-659ujfqLy6k7cuH3sbzhd8b+ztSq+i6E2E9pG78Q0BmHjAExfGIdgc8cGgMdwAozDXeZFHkJ+LXYJdWsaGdgyw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-x64-musl@0.143.0': + resolution: {integrity: sha512-/Mw/9j4TfZcnKphPrzOE6t4MMknXadcAAuVUlDRTF/ETWB5xOgQvOJV2Mh9We/bWxZdoxaGAdc+hy4GuYwQ2yQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-openharmony-arm64@0.143.0': + resolution: {integrity: sha512-8rIKWR2BFuifbIK/1XB9wTaSdtuJ25dlE7ZQYDnEwj/2xH2vHsxnvIjHT3ZjSVuLLwGGlSslIG/fbOJ8TV8rTw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxc-parser/binding-win32-arm64-msvc@0.143.0': + resolution: {integrity: sha512-5U9kQYMfRRI6Zq7KDxgbIP0RMnKrfn3gLepRMgJuRkPSUALTiRCk9d/uyhb4lGDjUdzwK7mBkKqhLgzBPCmLpQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxc-parser/binding-win32-ia32-msvc@0.143.0': + resolution: {integrity: sha512-25P7AaHk4R88Yv2XH4gToDVmh0cOu+bEURQU10CRrmvgabfRArSGAP5osmwUKeSUHj0VS50upbpbRWWW/m7mHA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxc-parser/binding-win32-x64-msvc@0.143.0': + resolution: {integrity: sha512-ORMh3JE1s6V7ySicdRK7vgaDQnn5o+UHg9ct989PlWHbel8O9ARrmWXM6kZjrBMtNucxNayQ8g69G0VfWzhANw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@oxc-project/types@0.142.0': resolution: {integrity: sha512-7W+2q5AKQVU36fkaryontrHn3YDt1RyUYXatw9i5H8ocYe2sPKSFB6eS8WNPeRKiN1qAWWZUPm7gwFzJGrccqQ==} + '@oxc-project/types@0.143.0': + resolution: {integrity: sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==} + + '@oxc-resolver/binding-android-arm-eabi@11.24.2': + resolution: {integrity: sha512-y09e0L0SRI2OA2tUIrjBgoV3eH5hvUKXNkJqXmNo5V2WxIjyC7I7aJfRLMEVpA8yi95f90gFDvO0VMgrDw+vwA==} + cpu: [arm] + os: [android] + + '@oxc-resolver/binding-android-arm64@11.24.2': + resolution: {integrity: sha512-cl4icWaZFnLdg8m6qtnh5rBMuGbxc/ptStFHLeCNwr+2cZjkjNwQu/jYRS0CHlnPecOJMpuS5M6/BH+0J/YkEg==} + cpu: [arm64] + os: [android] + + '@oxc-resolver/binding-darwin-arm64@11.24.2': + resolution: {integrity: sha512-At29QEMF6HajbQvgY8K6OXnHD1x9rad74xBEfmCB6ZqCGsdq75aK7tOYcTbOanMy8qdIBrfL3SMr3p/lfSlb9w==} + cpu: [arm64] + os: [darwin] + + '@oxc-resolver/binding-darwin-x64@11.24.2': + resolution: {integrity: sha512-A5Kqr1EUj4oIL5CF4WRssq/o5P0Y11cwoFouMRmQ7YnC/A8V93nv1nb7aSU8HwcgmXropjLNkVTl4MN87cu28Q==} + cpu: [x64] + os: [darwin] + + '@oxc-resolver/binding-freebsd-x64@11.24.2': + resolution: {integrity: sha512-R5xkRBRRz7ceH/P5Jrc6G7FmdUdgpLYyESFAUDVTNQ9K0sGPxcp4ljiwEwEqsvNcQ4sYbMRrWcHHBCu7ksAJVw==} + cpu: [x64] + os: [freebsd] + + '@oxc-resolver/binding-linux-arm-gnueabihf@11.24.2': + resolution: {integrity: sha512-k/RuYL4L/R58IBn3wT5ma3Wh4k62bp1eYCFRWCmMsasUOqL+H6sW0VGFadEzKWXFFlz+2uIMoeMk9ySSZJHgbg==} + cpu: [arm] + os: [linux] + + '@oxc-resolver/binding-linux-arm-musleabihf@11.24.2': + resolution: {integrity: sha512-bnHAak3ujYfH5pKk4NieFNbvYvernfoQDgwLddbZ3OtMYrem87/qjlA+u+aKG0oZcqSLGCful/6/CEA+aeAgaA==} + cpu: [arm] + os: [linux] + + '@oxc-resolver/binding-linux-arm64-gnu@11.24.2': + resolution: {integrity: sha512-vDT3KHgzYp47gmtNOqL2VNhCyl5Zv643eyxm//A68J8DeUGXrvD1pZFiaT4jSfe+RInfnn1R2yVHye4enx6RnA==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxc-resolver/binding-linux-arm64-musl@11.24.2': + resolution: {integrity: sha512-+kMlQvbzfyEYtu5FcjE4p+ttBLpKW4d/AsAsuE69BxV6V4twZJeIQZFfD8gh/wqglY0MkPSezWXQH0jBV13MUw==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxc-resolver/binding-linux-ppc64-gnu@11.24.2': + resolution: {integrity: sha512-shjfMhmZ3gq9fv/w7bi3PnZlgOPG+2QAOFf0BJF0EgBSIGZ6PMLN2zbGEblTUYB/NKVDRyYhE2ff3dJ1QqNPkA==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxc-resolver/binding-linux-riscv64-gnu@11.24.2': + resolution: {integrity: sha512-zGelwFR5oRo+b69k8Lrzun86DyUHzfKN6cnjbR9l7Z7NIRznOE/2ZvPa1IUKqAL2PzAXOdwkfVqNvO1H2RlpAw==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxc-resolver/binding-linux-riscv64-musl@11.24.2': + resolution: {integrity: sha512-qxZ1SWCXJY0eyhAlP6Lmo9F2Nrtx7EkYj9oCgL8apDPCwXwCEDA2U697bbT81JIc2IrVjxO4KX6WU2N+oN9Z4w==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxc-resolver/binding-linux-s390x-gnu@11.24.2': + resolution: {integrity: sha512-sGCecF3cx2DFlH4t/z7ApnOnXqN48p5p5mlHDEnHTAukQa2P+qMVE4CwyWE9W+q/m3QJ7kKfGrIjax31f44oFQ==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxc-resolver/binding-linux-x64-gnu@11.24.2': + resolution: {integrity: sha512-k/VlMMcSzMlahb3/fENM4rTlsJ0s3fFROA0KXPBmKggqmTSaE383sl8F3KCOXPLmVsYfW6hCitMhXCEtNeZxxg==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxc-resolver/binding-linux-x64-musl@11.24.2': + resolution: {integrity: sha512-8hbnZyNi97b/8wapYaIF9+t9GmZKBW2vunaOc3h9HGJptH7b7XpvZqOTBSm/MpTjr7H497BlgOaSfLUdhmy2bw==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxc-resolver/binding-openharmony-arm64@11.24.2': + resolution: {integrity: sha512-MvyGik3a6pVgZ0t/kWlbmFxFLmXQJwgLsY2eYFHLpy0wGwRbfzeIGgDwQ3kXqE30z+kSXennRkCrT7TUvkptNg==} + cpu: [arm64] + os: [openharmony] + + '@oxc-resolver/binding-wasm32-wasi@11.24.2': + resolution: {integrity: sha512-vHcssMPwO08RTvj/c0iOBz90attxyG3wQJ0dTcyEQK43LRpcdLWZlV5feBhv6Isn6ahbQIzHbCgfa81+RiML0Q==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@oxc-resolver/binding-win32-arm64-msvc@11.24.2': + resolution: {integrity: sha512-uokJqro2iBqkFvJdKQLP7d8/BUmFwESQFVmIJUQKj1Xn1a/LysJoe1vmeECLF5b3jsV8CAL5sEMJXX6SdK9Nhg==} + cpu: [arm64] + os: [win32] + + '@oxc-resolver/binding-win32-x64-msvc@11.24.2': + resolution: {integrity: sha512-UqGPmo56KDfLlfXFAFIrNflHT8tFxWGEivWg3Zeyp4Uy2NlKN1FGPr6/BxcLGG3+kZ6Wp14g5Uj+n71boqZfiw==} + cpu: [x64] + os: [win32] + '@quansync/fs@1.0.0': resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} @@ -286,18 +607,86 @@ packages: '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@tybys/wasm-util@0.10.3': + resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/esrecurse@4.3.1': + resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} + '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/node@26.1.2': resolution: {integrity: sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg==} + '@typescript-eslint/eslint-plugin@8.67.0': + resolution: {integrity: sha512-Un7Heoyj65NREbKAyIrFxeM143NZpExWmy1Nep4DLeQOeLlTeumPjoNKnBrU5D5moWXbPJgRa5Uwcdu0faVNGQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.67.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/parser@8.67.0': + resolution: {integrity: sha512-fUBfTuuEulWqX6V8+O3PtScV01tzYYRUDTAirHFKoRAt7nOzoGiPt0M/bB47wWNy0coOOcgEwAMUtBpykMxl6w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/project-service@8.67.0': + resolution: {integrity: sha512-cvE8c7ulYeXN9fYuszhCeCsbzyVEXuhrRCybnBre7TUmqb5nRmBfQAwCj0O3WJFDeyAZt4VYv51vMCC9LHSdYw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/scope-manager@8.67.0': + resolution: {integrity: sha512-EgvsleTwS4E+WzzSvem8fAUubLwatMNF1B5hHSLQxcvs7q2dtRhGyujHwLJSYlG41niJ7GP24Aha2+0mb1b2kg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.67.0': + resolution: {integrity: sha512-vV+LUSv5njUWsknE71fqKTlXUva+R76SaeORd6Zojcunk/6DvKFXONU3BrAs2H49mbygUXt6gbYunzwqNwlhdg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/type-utils@8.67.0': + resolution: {integrity: sha512-aVWDXbRmdXO9siTfX4ditQI1T9+zVcNazT48EJCD0v40/9RIFoUgZ05CmGEq9H2gixRpjUn/iplwvlcvutJW/Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/types@8.67.0': + resolution: {integrity: sha512-sBtgslww8nsMYUjhdPBiSyUqSzT8uR6g93A2QXnQC8+cGdjz0CyaOdqHDRJb1AtORbZCNUJBBeFA/tNR2uQmww==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.67.0': + resolution: {integrity: sha512-EKQBCE9yNlRJYm7jdTW5AhDacDUmSwQb0FAJAmK2EKYrNXIsa2vxcSZx6PvJ/dEdI6lS+Y9W+EXckLj0iPFGcw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/utils@8.67.0': + resolution: {integrity: sha512-U9D1FdwEWBwok3hxxSdhclMb0twvt9QnjIQ0VfQ1AiX2epnpSgv2ubVDsayOFyY8K6FX+AQ7E0FKWVG3iKsj1A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/visitor-keys@8.67.0': + resolution: {integrity: sha512-fkv8dHRDqfGtTHuJeebdrQ7cX6Ad4WAS00rgHh9UGvMycF1mjBfsxry1XsLIFhWZ6Judlh6UdzK+TYlbpCXgnA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@vitest/expect@4.1.6': resolution: {integrity: sha512-7EHDquPthALSV0jhhjgEW8FXaviMx7rSqu8W6oqCoAuOhKov814P99QDV1pxMA3QPv21YudvJngIhjrNI4opLg==} @@ -462,6 +851,19 @@ packages: '@yuku-toolchain/types@0.8.3': resolution: {integrity: sha512-9LN3HYs3A9qSPVFunsxlbfwBcUgexti3TmhOzIxB/UH8zFuaHQJXTRDcN17DW6cp1GsyZtiZA7f18uIra36Jag==} + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.18.0: + resolution: {integrity: sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.15.0: + resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} + ansis@4.3.1: resolution: {integrity: sha512-BJ8/l4R5LRE7hW9WdSuGYrLSHi2ynxeFpDFbH0K/CgNeY/tyhk+vO6TYxXC5r5CpUhNVX310xzPsN/H9lCdfOA==} engines: {node: '>=14'} @@ -470,6 +872,14 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + brace-expansion@5.0.9: + resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==} + engines: {node: 20 || >=22} + cac@7.0.0: resolution: {integrity: sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==} engines: {node: '>=20.19.0'} @@ -485,6 +895,18 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + defu@6.1.7: resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} @@ -501,8 +923,8 @@ packages: oxc-resolver: optional: true - effect@3.21.2: - resolution: {integrity: sha512-rXd2FGDM8KdjSIrc+mqEELo7ScW7xTVxEf1iInmPSpIde9/nyGuFM710cjTo7/EreGXiUX2MOonPpprbz2XHCg==} + effect@3.22.1: + resolution: {integrity: sha512-TNoXushmPOBAjJlthF5d2QwnX2xBPEtcNJr5XKNKbRLbDvBcOYkXlYDfvGfSA0zriwLFuCll5MDtNMAdZL17PQ==} effect@4.0.0-beta.66: resolution: {integrity: sha512-4arEr62cziFa8BBVDUwJCJJmaVepXf/kRg7KtC0h8+bufngscrHbwWFhr9c+HonwOF+31U3iD3xUJmw9KzX7Dw==} @@ -514,9 +936,55 @@ packages: es-module-lexer@2.3.1: resolution: {integrity: sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==} + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-scope@9.1.2: + resolution: {integrity: sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@5.0.1: + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + eslint@10.8.1: + resolution: {integrity: sha512-wqA7W2jbsC/BnV9Iv1UZpKVFkO1AdNoSmYW8NWG4HNOBbkAMvIqDZ27pI2f07dqn583NcIC44ckjAcOXDL1QbQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@11.2.0: + resolution: {integrity: sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + expect-type@1.4.0: resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} engines: {node: '>=12.0.0'} @@ -529,6 +997,18 @@ packages: resolution: {integrity: sha512-GOJ158CUMnN6cSahsv4+ExARvIDuzzinFjkp0E9WtiBa5zcVeLozVkWaE4IzFcc+Y48Wp1EDlUZsXRyAztQcSg==} engines: {node: '>=12.17.0'} + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fd-package-json@2.0.0: + resolution: {integrity: sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ==} + fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} @@ -538,35 +1018,107 @@ packages: picomatch: optional: true + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + find-my-way-ts@0.1.6: resolution: {integrity: sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA==} + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.4.4: + resolution: {integrity: sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==} + + formatly@0.3.0: + resolution: {integrity: sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w==} + engines: {node: '>=18.3.0'} + hasBin: true + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + get-tsconfig@4.14.1: + resolution: {integrity: sha512-Dz/6HxkrxgNehhxLVeyv8sad9UzF2xBVeaKBQNDfJ5XiSXmp2gTR0eO0RWiT2NCKS5aGP9jjkOMggTN90qU50A==} + get-tsconfig@5.0.0-beta.5: resolution: {integrity: sha512-/6gFNr0N04nob252sTQxyFLi3eKFRqIg1I87YcqAMT1i6SQrSF6KujUEQrtrjMV0H/eejTCltLdDSTEMzHbnsQ==} engines: {node: '>=20.20.0'} + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + hookable@6.1.1: resolution: {integrity: sha512-U9LYDy1CwhMCnprUfeAZWZGByVbhd54hwepegYTK7Pi5NvqEj63ifz5z+xukznehT7i6NIZRu89Ay1AZmRsLEQ==} + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.6: + resolution: {integrity: sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==} + engines: {node: '>= 4'} + import-without-cache@0.4.0: resolution: {integrity: sha512-NkJQA7oZ4YHQhd2+H3BoRFKF3d/XNsiKpHZCQEMH9pDX27hQQLsTyOocyRgaIVtf8gHX3Nt3LPkR4e5EdtPAGQ==} engines: {node: ^22.18.0 || >=24.0.0} + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + ini@6.0.0: resolution: {integrity: sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==} engines: {node: ^20.17.0 || >=22.9.0} + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + knip@6.32.2: + resolution: {integrity: sha512-WXTXbmocrw7gqm1A1TQvFN0OgJ7hUSU6E1g6SPRIzzHFogUBhXByc7cYeOFVtJ2uODg7DP4VbESYBYnfbtBYsg==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + kubernetes-types@1.30.0: resolution: {integrity: sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q==} + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + lightningcss-android-arm64@1.33.0: resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} engines: {node: '>= 12.0.0'} @@ -641,9 +1193,20 @@ packages: resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} engines: {node: '>= 12.0.0'} + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + minimatch@10.2.6: + resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} + engines: {node: 18 || 20 || >=22} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + msgpackr-extract@3.0.4: resolution: {integrity: sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw==} hasBin: true @@ -659,6 +1222,9 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + node-gyp-build-optional-packages@5.2.2: resolution: {integrity: sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==} hasBin: true @@ -667,6 +1233,29 @@ packages: resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==} engines: {node: '>=12.20.0'} + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + oxc-parser@0.143.0: + resolution: {integrity: sha512-ov0NzaDCOInknS7mP1cwKdJERt3utPW8ldjtdUXQ8Ty0GEFD08wk422vCUN0d7pST6kqtV7dxoI9w1Zi0l/9TA==} + engines: {node: ^20.19.0 || >=22.12.0} + + oxc-resolver@11.24.2: + resolution: {integrity: sha512-FY91FiDBj7ls5MsFS9jN3tjz2o0/zsdSsymlakySaBwVJZorHhkWyICLZMKxlu1R9vYo+sd3z1jwb4J8x7bNDw==} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -685,11 +1274,19 @@ packages: resolution: {integrity: sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==} engines: {node: ^10 || ^12 || >=14} + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + prettier@3.8.3: resolution: {integrity: sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==} engines: {node: '>=14'} hasBin: true + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + pure-rand@6.1.0: resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} @@ -726,6 +1323,11 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -737,6 +1339,10 @@ packages: siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + smol-toml@1.8.0: + resolution: {integrity: sha512-kCZr2V3ch9i00x8zXRhjUNVcjG9ijES5dDudkXvUVCT5QlJNQWElSJdZqyPemffHoLNUYwOcou0Fy+ojN0uHSQ==} + engines: {node: '>= 18'} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -747,6 +1353,10 @@ packages: std-env@4.2.0: resolution: {integrity: sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==} + strip-json-comments@5.0.3: + resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} + engines: {node: '>=14.16'} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -770,6 +1380,12 @@ packages: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true + ts-api-utils@2.5.0: + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + tsdown@0.22.14: resolution: {integrity: sha512-ule7Y+fsAN2iZbLDoo7C4KYljFJNJJ+fLshyn+9gozeTspVersWHxwdGB+Dm2hzA38s6muFnUTl0jK3vJm9ifQ==} engines: {node: ^22.18.0 || >=24.11.0} @@ -804,17 +1420,48 @@ packages: unrun: optional: true + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + typescript-eslint@8.67.0: + resolution: {integrity: sha512-S2udFs8tCKEKffuJ4TB1idGUZiXdCPGi3IPBGWXarbLQ5UPXORV8QEVzJ4gCRduURMb5EkpNCdjbk0eDIuI8Yg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + typescript@6.0.3: resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} engines: {node: '>=14.17'} hasBin: true + unbash@4.0.10: + resolution: {integrity: sha512-b7zoBQvpWp0vuN5q2vK2RRBR2SvuruQAs50DApdDveBSn3eSYd84IaHodFqQIMlvY9K2VnyBUEXgwOBuGU9GBg==} + engines: {node: '>=14'} + unconfig-core@7.5.0: resolution: {integrity: sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==} undici-types@8.3.0: resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==} + unrun@0.3.1: + resolution: {integrity: sha512-onIck/oNnCaytwths1ZVp1LK2Gq2hPoyFhiHebObuUXqR3S0uHuLLaBK8K6mRRgV7Ptip8AnNvaUsgzwWwBZuA==} + engines: {node: ^22.13.0 || >=24.0.0} + hasBin: true + peerDependencies: + synckit: ^0.11.11 + peerDependenciesMeta: + synckit: + optional: true + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + uuid@13.0.2: resolution: {integrity: sha512-vzi9uRZ926x4XV73S/4qQaTwPXM2JBj6/6lI/byHH1jOpCzb0zDbfytgA9LcN/hzb2l7WQSQnxITOVx5un/wGw==} hasBin: true @@ -907,48 +1554,129 @@ packages: jsdom: optional: true + walk-up-path@4.0.0: + resolution: {integrity: sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==} + engines: {node: 20 || >=22} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true - why-is-node-running@2.3.0: - resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} - engines: {node: '>=8'} - hasBin: true + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + yaml@2.9.0: + resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==} + engines: {node: '>= 14.6'} + hasBin: true + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yuku-ast@0.8.3: + resolution: {integrity: sha512-8x34yU5uhHUnJXzy2Qvjvec/vE9BzS0/2khVT1MsLmSLO/P8Q1Wp8IxHv+IhD+HMYETk6kherOSvP4JPWw2joQ==} + + yuku-codegen@0.8.3: + resolution: {integrity: sha512-okdo5bb+TfebQa4JOjz9QxeT34D6CcBxu8dxaPUdFEKRdLkp+D2Fah2OanepK+XTyPXdmAJzAo9iXvYvZ/5rmg==} + + yuku-parser@0.8.3: + resolution: {integrity: sha512-KPQcpF9aj77ywlJBIkQWCQ9DObdxnCA8AJdUOmA5CZZx042Xt4+dvbQmPJfWxF3E+KG5dVAZ2fBKuDJ8VsKWgA==} + + zod@4.1.8: + resolution: {integrity: sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ==} + + zod@4.4.3: + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + +snapshots: + + '@emnapi/core@1.11.2': + dependencies: + '@emnapi/wasi-threads': 1.2.2 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.11.2': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.2': + dependencies: + tslib: 2.8.1 + optional: true + + '@eslint-community/eslint-utils@4.10.1(eslint@10.8.1(jiti@2.7.0))': + dependencies: + eslint: 10.8.1(jiti@2.7.0) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.2': {} + + '@eslint/config-array@0.23.5': + dependencies: + '@eslint/object-schema': 3.0.5 + debug: 4.4.3 + minimatch: 10.2.6 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.7.0': + dependencies: + '@eslint/core': 1.2.1 + + '@eslint/core@1.2.1': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/js@10.0.1(eslint@10.8.1(jiti@2.7.0))': + optionalDependencies: + eslint: 10.8.1(jiti@2.7.0) - yaml@2.9.0: - resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==} - engines: {node: '>= 14.6'} - hasBin: true + '@eslint/object-schema@3.0.5': {} - yuku-ast@0.8.3: - resolution: {integrity: sha512-8x34yU5uhHUnJXzy2Qvjvec/vE9BzS0/2khVT1MsLmSLO/P8Q1Wp8IxHv+IhD+HMYETk6kherOSvP4JPWw2joQ==} + '@eslint/plugin-kit@0.7.2': + dependencies: + '@eslint/core': 1.2.1 + levn: 0.4.1 - yuku-codegen@0.8.3: - resolution: {integrity: sha512-okdo5bb+TfebQa4JOjz9QxeT34D6CcBxu8dxaPUdFEKRdLkp+D2Fah2OanepK+XTyPXdmAJzAo9iXvYvZ/5rmg==} + '@humanfs/core@0.19.2': + dependencies: + '@humanfs/types': 0.15.0 - yuku-parser@0.8.3: - resolution: {integrity: sha512-KPQcpF9aj77ywlJBIkQWCQ9DObdxnCA8AJdUOmA5CZZx042Xt4+dvbQmPJfWxF3E+KG5dVAZ2fBKuDJ8VsKWgA==} + '@humanfs/node@0.16.8': + dependencies: + '@humanfs/core': 0.19.2 + '@humanfs/types': 0.15.0 + '@humanwhocodes/retry': 0.4.3 - zod@4.1.8: - resolution: {integrity: sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ==} + '@humanfs/types@0.15.0': {} -snapshots: + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} '@jridgewell/sourcemap-codec@1.5.5': {} - '@langfuse/core@5.4.1(@opentelemetry/api@1.9.1)': + '@langfuse/core@5.10.1(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@langfuse/otel@5.4.1(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/exporter-trace-otlp-http@0.218.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))': + '@langfuse/otel@5.10.1(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1))(@opentelemetry/exporter-trace-otlp-http@0.221.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.10.0(@opentelemetry/api@1.9.1))': dependencies: - '@langfuse/core': 5.4.1(@opentelemetry/api@1.9.1) + '@langfuse/core': 5.10.1(@opentelemetry/api@1.9.1) '@opentelemetry/api': 1.9.1 - '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) - '@opentelemetry/exporter-trace-otlp-http': 0.218.0(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/core': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-trace-otlp-http': 0.221.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.10.0(@opentelemetry/api@1.9.1) '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4': optional: true @@ -968,6 +1696,13 @@ snapshots: '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4': optional: true + '@napi-rs/wasm-runtime@1.2.3(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + dependencies: + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@tybys/wasm-util': 0.10.3 + optional: true + '@opencode-ai/plugin@1.15.13': dependencies: '@opencode-ai/sdk': 1.15.13 @@ -978,84 +1713,210 @@ snapshots: dependencies: cross-spawn: 7.0.6 - '@opentelemetry/api-logs@0.218.0': + '@opentelemetry/api-logs@0.221.0': dependencies: '@opentelemetry/api': 1.9.1 '@opentelemetry/api@1.9.1': {} - '@opentelemetry/context-async-hooks@2.7.1(@opentelemetry/api@1.9.1)': + '@opentelemetry/context-async-hooks@2.10.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1)': + '@opentelemetry/core@2.10.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/semantic-conventions': 1.41.1 + '@opentelemetry/semantic-conventions': 1.43.0 - '@opentelemetry/exporter-trace-otlp-http@0.218.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/exporter-trace-otlp-http@0.221.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) - '@opentelemetry/otlp-exporter-base': 0.218.0(@opentelemetry/api@1.9.1) - '@opentelemetry/otlp-transformer': 0.218.0(@opentelemetry/api@1.9.1) - '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.221.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.221.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace': 2.10.0(@opentelemetry/api@1.9.1) - '@opentelemetry/otlp-exporter-base@0.218.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/otlp-exporter-base@0.221.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) - '@opentelemetry/otlp-transformer': 0.218.0(@opentelemetry/api@1.9.1) + '@opentelemetry/core': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.221.0(@opentelemetry/api@1.9.1) - '@opentelemetry/otlp-transformer@0.218.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/otlp-transformer@0.221.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.221.0 + '@opentelemetry/core': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-logs': 0.221.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace': 2.10.0(@opentelemetry/api@1.9.1) + + '@opentelemetry/resources@2.10.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/api-logs': 0.218.0 - '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) - '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-logs': 0.218.0(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-metrics': 2.7.1(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/core': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.43.0 - '@opentelemetry/resources@2.7.1(@opentelemetry/api@1.9.1)': + '@opentelemetry/sdk-logs@0.221.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) - '@opentelemetry/semantic-conventions': 1.41.1 + '@opentelemetry/api-logs': 0.221.0 + '@opentelemetry/core': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.43.0 - '@opentelemetry/sdk-logs@0.218.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/sdk-metrics@2.10.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/api-logs': 0.218.0 - '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) - '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) - '@opentelemetry/semantic-conventions': 1.41.1 + '@opentelemetry/core': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.10.0(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-metrics@2.7.1(@opentelemetry/api@1.9.1)': + '@opentelemetry/sdk-trace-base@2.10.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) - '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/core': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.43.0 - '@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1)': + '@opentelemetry/sdk-trace-node@2.10.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) - '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) - '@opentelemetry/semantic-conventions': 1.41.1 + '@opentelemetry/context-async-hooks': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/core': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.10.0(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-trace-node@2.7.1(@opentelemetry/api@1.9.1)': + '@opentelemetry/sdk-trace@2.10.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/context-async-hooks': 2.7.1(@opentelemetry/api@1.9.1) - '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) - '@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/core': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.10.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.43.0 + + '@opentelemetry/semantic-conventions@1.43.0': {} + + '@oxc-parser/binding-android-arm-eabi@0.143.0': + optional: true + + '@oxc-parser/binding-android-arm64@0.143.0': + optional: true + + '@oxc-parser/binding-darwin-arm64@0.143.0': + optional: true + + '@oxc-parser/binding-darwin-x64@0.143.0': + optional: true + + '@oxc-parser/binding-freebsd-x64@0.143.0': + optional: true + + '@oxc-parser/binding-linux-arm-gnueabihf@0.143.0': + optional: true + + '@oxc-parser/binding-linux-arm-musleabihf@0.143.0': + optional: true + + '@oxc-parser/binding-linux-arm64-gnu@0.143.0': + optional: true + + '@oxc-parser/binding-linux-arm64-musl@0.143.0': + optional: true + + '@oxc-parser/binding-linux-ppc64-gnu@0.143.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-gnu@0.143.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-musl@0.143.0': + optional: true + + '@oxc-parser/binding-linux-s390x-gnu@0.143.0': + optional: true + + '@oxc-parser/binding-linux-x64-gnu@0.143.0': + optional: true + + '@oxc-parser/binding-linux-x64-musl@0.143.0': + optional: true + + '@oxc-parser/binding-openharmony-arm64@0.143.0': + optional: true + + '@oxc-parser/binding-win32-arm64-msvc@0.143.0': + optional: true + + '@oxc-parser/binding-win32-ia32-msvc@0.143.0': + optional: true - '@opentelemetry/semantic-conventions@1.41.1': {} + '@oxc-parser/binding-win32-x64-msvc@0.143.0': + optional: true '@oxc-project/types@0.142.0': {} + '@oxc-project/types@0.143.0': {} + + '@oxc-resolver/binding-android-arm-eabi@11.24.2': + optional: true + + '@oxc-resolver/binding-android-arm64@11.24.2': + optional: true + + '@oxc-resolver/binding-darwin-arm64@11.24.2': + optional: true + + '@oxc-resolver/binding-darwin-x64@11.24.2': + optional: true + + '@oxc-resolver/binding-freebsd-x64@11.24.2': + optional: true + + '@oxc-resolver/binding-linux-arm-gnueabihf@11.24.2': + optional: true + + '@oxc-resolver/binding-linux-arm-musleabihf@11.24.2': + optional: true + + '@oxc-resolver/binding-linux-arm64-gnu@11.24.2': + optional: true + + '@oxc-resolver/binding-linux-arm64-musl@11.24.2': + optional: true + + '@oxc-resolver/binding-linux-ppc64-gnu@11.24.2': + optional: true + + '@oxc-resolver/binding-linux-riscv64-gnu@11.24.2': + optional: true + + '@oxc-resolver/binding-linux-riscv64-musl@11.24.2': + optional: true + + '@oxc-resolver/binding-linux-s390x-gnu@11.24.2': + optional: true + + '@oxc-resolver/binding-linux-x64-gnu@11.24.2': + optional: true + + '@oxc-resolver/binding-linux-x64-musl@11.24.2': + optional: true + + '@oxc-resolver/binding-openharmony-arm64@11.24.2': + optional: true + + '@oxc-resolver/binding-wasm32-wasi@11.24.2': + dependencies: + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@napi-rs/wasm-runtime': 1.2.3(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + optional: true + + '@oxc-resolver/binding-win32-arm64-msvc@11.24.2': + optional: true + + '@oxc-resolver/binding-win32-x64-msvc@11.24.2': + optional: true + '@quansync/fs@1.0.0': dependencies: quansync: 1.0.0 @@ -1106,6 +1967,11 @@ snapshots: '@standard-schema/spec@1.1.0': {} + '@tybys/wasm-util@0.10.3': + dependencies: + tslib: 2.8.1 + optional: true + '@types/chai@5.2.3': dependencies: '@types/deep-eql': 4.0.2 @@ -1113,12 +1979,107 @@ snapshots: '@types/deep-eql@4.0.2': {} + '@types/esrecurse@4.3.1': {} + '@types/estree@1.0.9': {} + '@types/json-schema@7.0.15': {} + '@types/node@26.1.2': dependencies: undici-types: 8.3.0 + '@typescript-eslint/eslint-plugin@8.67.0(@typescript-eslint/parser@8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3))(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.67.0 + '@typescript-eslint/type-utils': 8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/utils': 8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.67.0 + eslint: 10.8.1(jiti@2.7.0) + ignore: 7.0.6 + natural-compare: 1.4.0 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.67.0 + '@typescript-eslint/types': 8.67.0 + '@typescript-eslint/typescript-estree': 8.67.0(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.67.0 + debug: 4.4.3 + eslint: 10.8.1(jiti@2.7.0) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.67.0(typescript@6.0.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.67.0(typescript@6.0.3) + '@typescript-eslint/types': 8.67.0 + debug: 4.4.3 + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.67.0': + dependencies: + '@typescript-eslint/types': 8.67.0 + '@typescript-eslint/visitor-keys': 8.67.0 + + '@typescript-eslint/tsconfig-utils@8.67.0(typescript@6.0.3)': + dependencies: + typescript: 6.0.3 + + '@typescript-eslint/type-utils@8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)': + dependencies: + '@typescript-eslint/types': 8.67.0 + '@typescript-eslint/typescript-estree': 8.67.0(typescript@6.0.3) + '@typescript-eslint/utils': 8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3) + debug: 4.4.3 + eslint: 10.8.1(jiti@2.7.0) + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.67.0': {} + + '@typescript-eslint/typescript-estree@8.67.0(typescript@6.0.3)': + dependencies: + '@typescript-eslint/project-service': 8.67.0(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.67.0(typescript@6.0.3) + '@typescript-eslint/types': 8.67.0 + '@typescript-eslint/visitor-keys': 8.67.0 + debug: 4.4.3 + minimatch: 10.2.6 + semver: 7.8.5 + tinyglobby: 0.2.17 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3)': + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@10.8.1(jiti@2.7.0)) + '@typescript-eslint/scope-manager': 8.67.0 + '@typescript-eslint/types': 8.67.0 + '@typescript-eslint/typescript-estree': 8.67.0(typescript@6.0.3) + eslint: 10.8.1(jiti@2.7.0) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.67.0': + dependencies: + '@typescript-eslint/types': 8.67.0 + eslint-visitor-keys: 5.0.1 + '@vitest/expect@4.1.6': dependencies: '@standard-schema/spec': 1.1.0 @@ -1128,13 +2089,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.1 - '@vitest/mocker@4.1.6(vite@8.2.0(@types/node@26.1.2)(yaml@2.9.0))': + '@vitest/mocker@4.1.6(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.6 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.2.0(@types/node@26.1.2)(yaml@2.9.0) + vite: 8.2.0(@types/node@26.1.2)(jiti@2.7.0)(yaml@2.9.0) '@vitest/pretty-format@4.1.6': dependencies: @@ -1234,10 +2195,29 @@ snapshots: '@yuku-toolchain/types@0.8.3': {} + acorn-jsx@5.3.2(acorn@8.18.0): + dependencies: + acorn: 8.18.0 + + acorn@8.18.0: {} + + ajv@6.15.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + ansis@4.3.1: {} assertion-error@2.0.1: {} + balanced-match@4.0.4: {} + + brace-expansion@5.0.9: + dependencies: + balanced-match: 4.0.4 + cac@7.0.0: {} chai@6.2.2: {} @@ -1250,13 +2230,21 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + debug@4.4.3: + dependencies: + ms: 2.1.3 + + deep-is@0.1.4: {} + defu@6.1.7: {} detect-libc@2.1.2: {} - dts-resolver@3.0.0: {} + dts-resolver@3.0.0(oxc-resolver@11.24.2): + optionalDependencies: + oxc-resolver: 11.24.2 - effect@3.21.2: + effect@3.22.1: dependencies: '@standard-schema/spec': 1.1.0 fast-check: 3.23.2 @@ -1278,10 +2266,78 @@ snapshots: es-module-lexer@2.3.1: {} + escape-string-regexp@4.0.0: {} + + eslint-scope@9.1.2: + dependencies: + '@types/esrecurse': 4.3.1 + '@types/estree': 1.0.9 + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@5.0.1: {} + + eslint@10.8.1(jiti@2.7.0): + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@10.8.1(jiti@2.7.0)) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.23.5 + '@eslint/config-helpers': 0.7.0 + '@eslint/core': 1.2.1 + '@eslint/plugin-kit': 0.7.2 + '@humanfs/node': 0.16.8 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.9 + ajv: 6.15.0 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 9.1.2 + eslint-visitor-keys: 5.0.1 + espree: 11.2.0 + esquery: 1.7.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + minimatch: 10.2.6 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.7.0 + transitivePeerDependencies: + - supports-color + + espree@11.2.0: + dependencies: + acorn: 8.18.0 + acorn-jsx: 5.3.2(acorn@8.18.0) + eslint-visitor-keys: 5.0.1 + + esquery@1.7.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + estree-walker@3.0.3: dependencies: '@types/estree': 1.0.9 + esutils@2.0.3: {} + expect-type@1.4.0: {} fast-check@3.23.2: @@ -1292,29 +2348,112 @@ snapshots: dependencies: pure-rand: 8.4.0 + fast-deep-equal@3.1.3: {} + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fd-package-json@2.0.0: + dependencies: + walk-up-path: 4.0.0 + fdir@6.5.0(picomatch@4.0.5): optionalDependencies: picomatch: 4.0.5 + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + find-my-way-ts@0.1.6: {} + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.4.4 + keyv: 4.5.4 + + flatted@3.4.4: {} + + formatly@0.3.0: + dependencies: + fd-package-json: 2.0.0 + fsevents@2.3.3: optional: true + get-tsconfig@4.14.1: + dependencies: + resolve-pkg-maps: 1.0.0 + get-tsconfig@5.0.0-beta.5: dependencies: resolve-pkg-maps: 1.0.0 + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + hookable@6.1.1: {} + ignore@5.3.2: {} + + ignore@7.0.6: {} + import-without-cache@0.4.0: {} + imurmurhash@0.1.4: {} + ini@6.0.0: {} + is-extglob@2.1.1: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + isexe@2.0.0: {} + jiti@2.7.0: {} + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + knip@6.32.2: + dependencies: + fdir: 6.5.0(picomatch@4.0.5) + formatly: 0.3.0 + get-tsconfig: 4.14.1 + jiti: 2.7.0 + oxc-parser: 0.143.0 + oxc-resolver: 11.24.2 + picomatch: 4.0.5 + smol-toml: 1.8.0 + strip-json-comments: 5.0.3 + tinyglobby: 0.2.17 + unbash: 4.0.10 + yaml: 2.9.0 + zod: 4.4.3 + kubernetes-types@1.30.0: {} + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + lightningcss-android-arm64@1.33.0: optional: true @@ -1364,10 +2503,20 @@ snapshots: lightningcss-win32-arm64-msvc: 1.33.0 lightningcss-win32-x64-msvc: 1.33.0 + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + minimatch@10.2.6: + dependencies: + brace-expansion: 5.0.9 + + ms@2.1.3: {} + msgpackr-extract@3.0.4: dependencies: node-gyp-build-optional-packages: 5.2.2 @@ -1388,6 +2537,8 @@ snapshots: nanoid@3.3.17: {} + natural-compare@1.4.0: {} + node-gyp-build-optional-packages@5.2.2: dependencies: detect-libc: 2.1.2 @@ -1395,6 +2546,71 @@ snapshots: obug@2.1.4: {} + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + oxc-parser@0.143.0: + dependencies: + '@oxc-project/types': 0.143.0 + optionalDependencies: + '@oxc-parser/binding-android-arm-eabi': 0.143.0 + '@oxc-parser/binding-android-arm64': 0.143.0 + '@oxc-parser/binding-darwin-arm64': 0.143.0 + '@oxc-parser/binding-darwin-x64': 0.143.0 + '@oxc-parser/binding-freebsd-x64': 0.143.0 + '@oxc-parser/binding-linux-arm-gnueabihf': 0.143.0 + '@oxc-parser/binding-linux-arm-musleabihf': 0.143.0 + '@oxc-parser/binding-linux-arm64-gnu': 0.143.0 + '@oxc-parser/binding-linux-arm64-musl': 0.143.0 + '@oxc-parser/binding-linux-ppc64-gnu': 0.143.0 + '@oxc-parser/binding-linux-riscv64-gnu': 0.143.0 + '@oxc-parser/binding-linux-riscv64-musl': 0.143.0 + '@oxc-parser/binding-linux-s390x-gnu': 0.143.0 + '@oxc-parser/binding-linux-x64-gnu': 0.143.0 + '@oxc-parser/binding-linux-x64-musl': 0.143.0 + '@oxc-parser/binding-openharmony-arm64': 0.143.0 + '@oxc-parser/binding-win32-arm64-msvc': 0.143.0 + '@oxc-parser/binding-win32-ia32-msvc': 0.143.0 + '@oxc-parser/binding-win32-x64-msvc': 0.143.0 + + oxc-resolver@11.24.2: + optionalDependencies: + '@oxc-resolver/binding-android-arm-eabi': 11.24.2 + '@oxc-resolver/binding-android-arm64': 11.24.2 + '@oxc-resolver/binding-darwin-arm64': 11.24.2 + '@oxc-resolver/binding-darwin-x64': 11.24.2 + '@oxc-resolver/binding-freebsd-x64': 11.24.2 + '@oxc-resolver/binding-linux-arm-gnueabihf': 11.24.2 + '@oxc-resolver/binding-linux-arm-musleabihf': 11.24.2 + '@oxc-resolver/binding-linux-arm64-gnu': 11.24.2 + '@oxc-resolver/binding-linux-arm64-musl': 11.24.2 + '@oxc-resolver/binding-linux-ppc64-gnu': 11.24.2 + '@oxc-resolver/binding-linux-riscv64-gnu': 11.24.2 + '@oxc-resolver/binding-linux-riscv64-musl': 11.24.2 + '@oxc-resolver/binding-linux-s390x-gnu': 11.24.2 + '@oxc-resolver/binding-linux-x64-gnu': 11.24.2 + '@oxc-resolver/binding-linux-x64-musl': 11.24.2 + '@oxc-resolver/binding-openharmony-arm64': 11.24.2 + '@oxc-resolver/binding-wasm32-wasi': 11.24.2 + '@oxc-resolver/binding-win32-arm64-msvc': 11.24.2 + '@oxc-resolver/binding-win32-x64-msvc': 11.24.2 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + path-exists@4.0.0: {} + path-key@3.1.1: {} pathe@2.0.3: {} @@ -1409,8 +2625,12 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + prelude-ls@1.2.1: {} + prettier@3.8.3: {} + punycode@2.3.1: {} + pure-rand@6.1.0: {} pure-rand@8.4.0: {} @@ -1419,9 +2639,9 @@ snapshots: resolve-pkg-maps@1.0.0: {} - rolldown-plugin-dts@0.27.14(rolldown@1.2.2)(typescript@6.0.3): + rolldown-plugin-dts@0.27.14(oxc-resolver@11.24.2)(rolldown@1.2.2)(typescript@6.0.3): dependencies: - dts-resolver: 3.0.0 + dts-resolver: 3.0.0(oxc-resolver@11.24.2) get-tsconfig: 5.0.0-beta.5 obug: 2.1.4 rolldown: 1.2.2 @@ -1453,6 +2673,8 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.2.2 '@rolldown/binding-win32-x64-msvc': 1.2.2 + semver@7.8.5: {} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -1461,12 +2683,16 @@ snapshots: siginfo@2.0.0: {} + smol-toml@1.8.0: {} + source-map-js@1.2.1: {} stackback@0.0.2: {} std-env@4.2.0: {} + strip-json-comments@5.0.3: {} + tinybench@2.9.0: {} tinyexec@1.3.0: {} @@ -1482,7 +2708,11 @@ snapshots: tree-kill@1.2.2: {} - tsdown@0.22.14(typescript@6.0.3): + ts-api-utils@2.5.0(typescript@6.0.3): + dependencies: + typescript: 6.0.3 + + tsdown@0.22.14(oxc-resolver@11.24.2)(typescript@6.0.3)(unrun@0.3.1): dependencies: ansis: 4.3.1 cac: 7.0.0 @@ -1493,7 +2723,7 @@ snapshots: obug: 2.1.4 picomatch: 4.0.5 rolldown: 1.2.2 - rolldown-plugin-dts: 0.27.14(rolldown@1.2.2)(typescript@6.0.3) + rolldown-plugin-dts: 0.27.14(oxc-resolver@11.24.2)(rolldown@1.2.2)(typescript@6.0.3) tinyexec: 1.3.0 tinyglobby: 0.2.17 tree-kill: 1.2.2 @@ -1501,14 +2731,35 @@ snapshots: verkit: 0.3.2 optionalDependencies: typescript: 6.0.3 + unrun: 0.3.1 transitivePeerDependencies: - '@typescript/native-preview' - '@volar/typescript' - oxc-resolver - vue-tsc + tslib@2.8.1: + optional: true + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + typescript-eslint@8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.67.0(@typescript-eslint/parser@8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3))(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/parser': 8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/typescript-estree': 8.67.0(typescript@6.0.3) + '@typescript-eslint/utils': 8.67.0(eslint@10.8.1(jiti@2.7.0))(typescript@6.0.3) + eslint: 10.8.1(jiti@2.7.0) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + typescript@6.0.3: {} + unbash@4.0.10: {} + unconfig-core@7.5.0: dependencies: '@quansync/fs': 1.0.0 @@ -1516,11 +2767,20 @@ snapshots: undici-types@8.3.0: {} + unrun@0.3.1: + dependencies: + rolldown: 1.2.2 + optional: true + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + uuid@13.0.2: {} verkit@0.3.2: {} - vite@8.2.0(@types/node@26.1.2)(yaml@2.9.0): + vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(yaml@2.9.0): dependencies: lightningcss: 1.33.0 picomatch: 4.0.5 @@ -1530,12 +2790,13 @@ snapshots: optionalDependencies: '@types/node': 26.1.2 fsevents: 2.3.3 + jiti: 2.7.0 yaml: 2.9.0 - vitest@4.1.6(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(vite@8.2.0(@types/node@26.1.2)(yaml@2.9.0)): + vitest@4.1.6(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.6 - '@vitest/mocker': 4.1.6(vite@8.2.0(@types/node@26.1.2)(yaml@2.9.0)) + '@vitest/mocker': 4.1.6(vite@8.2.0(@types/node@26.1.2)(jiti@2.7.0)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.6 '@vitest/runner': 4.1.6 '@vitest/snapshot': 4.1.6 @@ -1552,7 +2813,7 @@ snapshots: tinyexec: 1.3.0 tinyglobby: 0.2.17 tinyrainbow: 3.1.1 - vite: 8.2.0(@types/node@26.1.2)(yaml@2.9.0) + vite: 8.2.0(@types/node@26.1.2)(jiti@2.7.0)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@opentelemetry/api': 1.9.1 @@ -1560,6 +2821,8 @@ snapshots: transitivePeerDependencies: - msw + walk-up-path@4.0.0: {} + which@2.0.2: dependencies: isexe: 2.0.0 @@ -1569,8 +2832,12 @@ snapshots: siginfo: 2.0.0 stackback: 0.0.2 + word-wrap@1.2.5: {} + yaml@2.9.0: {} + yocto-queue@0.1.0: {} + yuku-ast@0.8.3: dependencies: '@yuku-toolchain/types': 0.8.3 @@ -1611,3 +2878,5 @@ snapshots: '@yuku-parser/binding-win32-x64': 0.8.3 zod@4.1.8: {} + + zod@4.4.3: {} diff --git a/src/index.ts b/src/index.ts index a0f0c41..4a965c4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -114,7 +114,12 @@ const loadLangfuseCredentials = Effect.gen(function* () { const publicKey = process.env.LANGFUSE_PUBLIC_KEY; const secretKey = process.env.LANGFUSE_SECRET_KEY; - if (publicKey && secretKey) { + if ( + publicKey !== undefined && + publicKey !== "" && + secretKey !== undefined && + secretKey !== "" + ) { return { publicKey, secretKey, @@ -134,12 +139,12 @@ const loadLangfuseCredentials = Effect.gen(function* () { ); const credentials = yield* Effect.tryPromise({ - try: async () => JSON.parse(await readFile(configPath, "utf8")), + try: async () => + Schema.decodeUnknownSync(Schema.parseJson(LangfuseCredentialsSchema))( + await readFile(configPath, "utf8"), + ), catch: () => new MissingLangfuseCredentials(), - }).pipe( - Effect.flatMap(Schema.decodeUnknown(LangfuseCredentialsSchema)), - Effect.mapError(() => new MissingLangfuseCredentials()), - ); + }).pipe(Effect.mapError(() => new MissingLangfuseCredentials())); if (!credentials.publicKey || !credentials.secretKey) { return yield* Effect.fail(new MissingLangfuseCredentials()); @@ -157,7 +162,7 @@ const eventHook = (event: OpencodeEvent, shutdown?: () => Promise) => langfuse.endActiveGenerationSteps(sessionID); langfuse.endActiveTurnObservations(sessionID); - if (sessionID) { + if (sessionID !== undefined && sessionID !== "") { langfuse.clearSessionTraceState(sessionID); } else { langfuse.clearTraceState(); @@ -195,7 +200,7 @@ const eventHook = (event: OpencodeEvent, shutdown?: () => Promise) => }); } - if (event.type === "session.error" && event.properties.sessionID) { + if (event.type === "session.error" && event.properties.sessionID != null) { langfuse.traceSessionError({ sessionID: event.properties.sessionID, error: event.properties.error, @@ -270,7 +275,7 @@ const eventHook = (event: OpencodeEvent, shutdown?: () => Promise) => if ( event.type === "session.next.tool.called" && - event.properties.assistantMessageID + event.properties.assistantMessageID != null ) { langfuse.rememberToolCall({ callID: event.properties.callID, @@ -335,7 +340,7 @@ const eventHook = (event: OpencodeEvent, shutdown?: () => Promise) => started: message.time.created, }); - if (!message.time.completed) { + if (message.time.completed === undefined) { return; } @@ -426,7 +431,9 @@ const flattenMcpContent = (content: readonly unknown[]) => { for (const part of content) { const decoded = Schema.decodeUnknownOption(McpContentSchema)(part); - if (Option.isNone(decoded)) continue; + if (Option.isNone(decoded)) { + continue; + } if (decoded.value.type === "text") { textParts.push(decoded.value.text); @@ -474,11 +481,7 @@ const createShutdownOnce = (langfuse: LangfuseClient) => { let shutdownPromise: Promise | undefined; return () => { - if (!shutdownPromise) { - shutdownPromise = Effect.runPromise(langfuse.shutdown); - } - - return shutdownPromise; + return (shutdownPromise ??= Effect.runPromise(langfuse.shutdown)); }; }; @@ -585,7 +588,7 @@ const main = Effect.gen(function* () { runHook( "config", Effect.gen(function* () { - if (!config.experimental?.openTelemetry) { + if (config.experimental?.openTelemetry !== true) { yield* log( "warn", "[Tracing disabled] Please enable `experimental.openTelemetry` in your opencode.jsonc to use the Langfuse plugin", @@ -644,7 +647,7 @@ const main = Effect.gen(function* () { tools = yield* Effect.promise(() => pendingTools); } - yield* Effect.sync(() => + yield* Effect.sync(() => { langfuse.traceUserMessage({ sessionID: input.sessionID, messageID: input.messageID, @@ -652,8 +655,8 @@ const main = Effect.gen(function* () { model: input.model, parts: output.parts, tools, - }), - ); + }); + }); }), ), @@ -661,13 +664,14 @@ const main = Effect.gen(function* () { runHook( "tool.execute.before", Effect.try({ - try: () => + try: () => { langfuse.traceToolStart({ sessionID: input.sessionID, callID: input.callID, tool: input.tool, args: output.args, - }), + }); + }, catch: (error) => error, }), ), @@ -686,7 +690,7 @@ const main = Effect.gen(function* () { } if (normalized.isError) { - yield* Effect.sync(() => + yield* Effect.sync(() => { langfuse.traceToolError({ sessionID: input.sessionID, callID: input.callID, @@ -696,13 +700,13 @@ const main = Effect.gen(function* () { normalized.output || `MCP tool "${input.tool}" returned an error`, completed: Date.now(), - }), - ); + }); + }); return; } yield* Effect.try({ - try: () => + try: () => { langfuse.traceToolEnd({ sessionID: input.sessionID, callID: input.callID, @@ -710,7 +714,8 @@ const main = Effect.gen(function* () { args: input.args, title: normalized.title, output: normalized.output, - }), + }); + }, catch: (error) => error, }); }), @@ -720,7 +725,7 @@ const main = Effect.gen(function* () { return hooks; }); -export const LangfusePlugin: Plugin = async ({ client }) => { +const LangfusePlugin: Plugin = async ({ client }) => { const clientLayer = Layer.succeed(OpencodeClientService, client); return Effect.runPromise(main.pipe(Effect.provide(clientLayer))); diff --git a/src/langfuse.ts b/src/langfuse.ts index 4da0de1..1a29667 100644 --- a/src/langfuse.ts +++ b/src/langfuse.ts @@ -2,11 +2,7 @@ import { LangfuseSpanProcessor } from "@langfuse/otel"; import type { Hooks } from "@opencode-ai/plugin"; import { SpanStatusCode, context, trace } from "@opentelemetry/api"; import type { Span as ApiSpan, Tracer } from "@opentelemetry/api"; -import type { - ReadableSpan, - Span, - SpanProcessor, -} from "@opentelemetry/sdk-trace-base"; +import type { Span, SpanProcessor } from "@opentelemetry/sdk-trace-base"; import { defaultResource, detectResources, @@ -110,7 +106,7 @@ export class LangfuseClient { endActiveToolObservations(sessionID?: string, error?: SessionErrorInfo) { for (const [callID, observation] of this.traceState .activeToolObservations) { - if (sessionID && observation.sessionID !== sessionID) { + if (sessionID != null && observation.sessionID !== sessionID) { continue; } @@ -138,7 +134,7 @@ export class LangfuseClient { ]); for (const step of activeSteps) { - if (sessionID && step.sessionID !== sessionID) { + if (sessionID != null && step.sessionID !== sessionID) { continue; } @@ -157,7 +153,7 @@ export class LangfuseClient { for (const [activeSessionID, step] of this.traceState .activeGenerationSteps) { - if (!sessionID || step.sessionID === sessionID) { + if (sessionID == null || step.sessionID === sessionID) { this.traceState.activeGenerationSteps.delete(activeSessionID); this.traceState.generationParentSpans.delete(activeSessionID); } @@ -165,7 +161,7 @@ export class LangfuseClient { for (const [messageID, step] of this.traceState .activeGenerationStepsByMessageId) { - if (!sessionID || step.sessionID === sessionID) { + if (sessionID == null || step.sessionID === sessionID) { this.traceState.activeGenerationStepsByMessageId.delete(messageID); } } @@ -178,7 +174,7 @@ export class LangfuseClient { ]); for (const observation of observations) { - if (sessionID && observation.sessionID !== sessionID) { + if (sessionID != null && observation.sessionID !== sessionID) { continue; } @@ -187,14 +183,14 @@ export class LangfuseClient { for (const [messageID, observation] of this.traceState .turnObservationsByMessageId) { - if (!sessionID || observation.sessionID === sessionID) { + if (sessionID == null || observation.sessionID === sessionID) { this.traceState.turnObservationsByMessageId.delete(messageID); } } for (const [activeSessionID, observation] of this.traceState .latestTurnObservationsBySession) { - if (!sessionID || observation.sessionID === sessionID) { + if (sessionID == null || observation.sessionID === sessionID) { this.traceState.latestTurnObservationsBySession.delete(activeSessionID); } } @@ -204,7 +200,7 @@ export class LangfuseClient { sessionID: string; parentSessionID?: string; }) { - if (input.parentSessionID) { + if (input.parentSessionID != null) { this.traceState.sessionParentIds.set( input.sessionID, input.parentSessionID, @@ -279,7 +275,7 @@ export class LangfuseClient { this.traceState.tracedReasoningIds.add(reasoningTraceKey); - if (!input.messageID) { + if (input.messageID == null) { return; } @@ -332,22 +328,23 @@ export class LangfuseClient { snapshot?: string; }) { const messageID = input.assistantMessageID; - const existingMessageStep = messageID - ? this.traceState.activeGenerationStepsByMessageId.get(messageID) - : undefined; + const existingMessageStep = + messageID != null + ? this.traceState.activeGenerationStepsByMessageId.get(messageID) + : undefined; const existingStep = this.traceState.activeGenerationSteps.get( input.sessionID, ); if ( - messageID && + messageID != null && !existingMessageStep && this.traceState.generationSpansByMessageId.has(messageID) ) { return; } - if (existingMessageStep && messageID) { + if (existingMessageStep && messageID != null) { const updatedStep = { ...existingMessageStep, agent: input.agent, @@ -366,8 +363,8 @@ export class LangfuseClient { "langfuse.observation.metadata", JSON.stringify({ agent: updatedStep.agent, - providerID: updatedStep.model?.providerID, - variant: updatedStep.model?.variant, + providerID: updatedStep.model.providerID, + variant: updatedStep.model.variant, snapshot: updatedStep.snapshot, }), ); @@ -383,7 +380,7 @@ export class LangfuseClient { return; } - if (existingStep && !existingStep.messageID && messageID) { + if (existingStep && existingStep.messageID == null && messageID != null) { const updatedStep = { ...existingStep, sessionID: input.sessionID, @@ -422,7 +419,7 @@ export class LangfuseClient { return; } - if (!messageID && existingStep) { + if (messageID == null && existingStep) { return; } @@ -461,7 +458,7 @@ export class LangfuseClient { span, snapshot: input.snapshot, }); - if (messageID) { + if (messageID != null) { const step = this.traceState.activeGenerationSteps.get(input.sessionID); if (step) { this.traceState.activeGenerationStepsByMessageId.set(messageID, step); @@ -481,7 +478,7 @@ export class LangfuseClient { tools?: ToolDefinition[]; }) { if ( - input.messageID && + input.messageID != null && this.traceState.tracedMessageIds.has(input.messageID) ) { return; @@ -493,7 +490,7 @@ export class LangfuseClient { role: "user" as const, content: input.parts.map((part) => { if (part.type === "text") { - return { type: part.type, text: part.text ?? "" }; + return { type: part.type, text: part.text }; } if (part.type === "file") { @@ -530,7 +527,7 @@ export class LangfuseClient { const generationInput = [ { ...formattedMessage, - ...(input.tools?.length ? { tools: input.tools } : {}), + ...((input.tools?.length ?? 0) > 0 ? { tools: input.tools } : {}), }, ]; @@ -539,7 +536,7 @@ export class LangfuseClient { generationInput, ); - if (input.messageID) { + if (input.messageID != null) { this.traceState.tracedMessageIds.add(input.messageID); } @@ -585,7 +582,7 @@ export class LangfuseClient { messageID: input.messageID, } satisfies TurnObservation; - if (input.messageID) { + if (input.messageID != null) { this.traceState.turnObservationsByMessageId.set( input.messageID, observation, @@ -620,9 +617,11 @@ export class LangfuseClient { }); }; - parentSpan - ? context.with(trace.setSpan(context.active(), parentSpan), startTurn) - : startTurn(); + if (parentSpan) { + context.with(trace.setSpan(context.active(), parentSpan), startTurn); + } else { + startTurn(); + } } rememberAssistantPart(part: MessagePart) { @@ -710,7 +709,8 @@ export class LangfuseClient { ); const step = this.traceState.activeGenerationStepsByMessageId.get(input.messageID) ?? - (activeStep?.messageID === input.messageID || !activeStep?.messageID + (activeStep?.messageID === input.messageID || + activeStep?.messageID == null ? activeStep : undefined); @@ -830,15 +830,16 @@ export class LangfuseClient { const activeStep = this.traceState.activeGenerationSteps.get( input.sessionID, ); - const step = input.assistantMessageID - ? (this.traceState.activeGenerationStepsByMessageId.get( - input.assistantMessageID, - ) ?? - (activeStep?.messageID === input.assistantMessageID || - !activeStep?.messageID - ? activeStep - : undefined)) - : activeStep; + const step = + input.assistantMessageID != null + ? (this.traceState.activeGenerationStepsByMessageId.get( + input.assistantMessageID, + ) ?? + (activeStep?.messageID === input.assistantMessageID || + activeStep?.messageID == null + ? activeStep + : undefined)) + : activeStep; if (step) { step.span.setAttribute( @@ -861,7 +862,7 @@ export class LangfuseClient { step.span.recordException(input.error); step.span.end(new Date(input.completed)); const messageID = input.assistantMessageID ?? step.messageID; - if (messageID) { + if (messageID != null) { this.traceState.activeGenerationStepsByMessageId.delete(messageID); } @@ -936,7 +937,7 @@ export class LangfuseClient { turn.span.end(); - if (turn.messageID) { + if (turn.messageID != null) { this.traceState.turnObservationsByMessageId.delete(turn.messageID); } @@ -1065,8 +1066,8 @@ export class LangfuseClient { if ( !this.traceState.activeToolObservations.has(input.callID) && - input.sessionID && - input.tool + input.sessionID != null && + input.tool != null ) { this.traceToolStart({ sessionID: input.sessionID, @@ -1097,15 +1098,13 @@ export class LangfuseClient { }); span.recordException({ message: input.error }); span.end(new Date(input.completed)); - if (observation) { - this.rememberToolResult({ - sessionID: observation.sessionID, - callID: input.callID, - tool: input.tool ?? observation.tool, - content: input.error, - messageID: input.messageID, - }); - } + this.rememberToolResult({ + sessionID: observation.sessionID, + callID: input.callID, + tool: input.tool ?? observation.tool, + content: input.error, + messageID: input.messageID, + }); this.traceState.activeToolObservations.delete(input.callID); this.traceState.finalizedToolCallIds.add(input.callID); this.traceState.toolMessageIdsByCallId.delete(input.callID); @@ -1159,7 +1158,7 @@ export class LangfuseClient { private getTurnObservation(sessionID: string, messageID: string | undefined) { return ( - (messageID + (messageID != null ? this.traceState.turnObservationsByMessageId.get(messageID) : undefined) ?? this.traceState.latestTurnObservationsBySession.get(sessionID) @@ -1169,7 +1168,7 @@ export class LangfuseClient { private getSessionParentSpan(sessionID: string) { const parentSessionID = this.traceState.sessionParentIds.get(sessionID); - if (!parentSessionID) { + if (parentSessionID == null) { return undefined; } @@ -1186,7 +1185,7 @@ export class LangfuseClient { messageID?: string, ) { const parentSpan = - (messageID + (messageID != null ? this.traceState.generationSpansByMessageId.get(messageID) : undefined) ?? this.traceState.activeGenerationSteps.get(sessionID)?.span ?? @@ -1204,14 +1203,14 @@ export class LangfuseClient { const content = parts .filter( (part): part is Extract => - part.type === "text" && Boolean(part.text), + part.type === "text" && part.text !== "", ) .map((part) => part.text) .join(""); const thinking = parts .filter( (part): part is Extract => - part.type === "reasoning" && Boolean(part.text), + part.type === "reasoning" && part.text !== "", ) .map((part) => ({ type: "thinking" as const, content: part.text })); const toolCallsById = new Map( @@ -1249,7 +1248,7 @@ export class LangfuseClient { this.traceState.generationInputsBySession.delete(sessionID); this.traceState.toolResultSourceMessageIdsBySession.delete(sessionID); - if (!sourceMessageID) { + if (sourceMessageID == null) { return input; } @@ -1279,7 +1278,7 @@ export class LangfuseClient { }); this.traceState.generationInputsBySession.set(input.sessionID, toolResults); - if (messageID) { + if (messageID != null) { this.traceState.toolResultSourceMessageIdsBySession.set( input.sessionID, messageID, @@ -1294,7 +1293,6 @@ export class LangfuseClient { if ( "data" in error && - error.data && typeof error.data === "object" && "message" in error.data && typeof error.data.message === "string" @@ -1350,7 +1348,7 @@ function getCompletedReasoningTimestamp(part: MessagePart) { return undefined; } -export type FormattedMessagePart = +type FormattedMessagePart = | { type: string; text: string } | { type: string; filename?: string; url?: string } | { type: string; name?: string } @@ -1358,14 +1356,14 @@ export type FormattedMessagePart = | { type: string; tool?: string; title?: string } | { type: string }; -export type SessionError = Extract< +type SessionError = Extract< Parameters>[0]["event"], { type: "session.error" } >["properties"]["error"]; export type SessionErrorInfo = NonNullable; -export type UserMessageInput = { +type UserMessageInput = { role: "user"; content: FormattedMessagePart[]; tools?: ToolDefinition[]; @@ -1418,20 +1416,20 @@ export class LangfuseClientService extends EffectContext.Tag( const makeUserIdSpanProcessor = (userId: string) => ({ - onStart: (span: Span, _parentContext: unknown) => { + onStart: (span: Span) => { span.setAttribute("langfuse.user.id", userId); }, - onEnd: (_span: ReadableSpan) => {}, + onEnd: () => undefined, shutdown: () => Promise.resolve(), forceFlush: () => Promise.resolve(), }) satisfies SpanProcessor; const makePluginVersionSpanProcessor = () => ({ - onStart: (span: Span, _parentContext: unknown) => { + onStart: (span: Span) => { span.setAttribute("langfuse.plugin.version", PLUGIN_VERSION); }, - onEnd: (_span: ReadableSpan) => {}, + onEnd: () => undefined, shutdown: () => Promise.resolve(), forceFlush: () => Promise.resolve(), }) satisfies SpanProcessor; @@ -1439,7 +1437,7 @@ const makePluginVersionSpanProcessor = () => // Langfuse's OTEL processor may auto-mark exported spans as app roots, this overrides that. const makeAppRootSpanProcessor = (tracerName: string) => ({ - onStart: (span: Span, _parentContext: unknown) => { + onStart: (span: Span) => { if (span.instrumentationScope.name !== tracerName) { return; } @@ -1449,7 +1447,7 @@ const makeAppRootSpanProcessor = (tracerName: string) => span.name === "opencode.turn", ); }, - onEnd: (_span: ReadableSpan) => {}, + onEnd: () => undefined, shutdown: () => Promise.resolve(), forceFlush: () => Promise.resolve(), }) satisfies SpanProcessor; @@ -1503,20 +1501,24 @@ export const createLangfuseClient = (input: { resource: defaultResource() .merge(detectResources({ detectors: [envDetector] })) .merge( - input.serviceName + input.serviceName != null ? resourceFromAttributes({ "service.name": input.serviceName }) : null, ), spanProcessors: [ makePluginVersionSpanProcessor(), - ...(input.userId ? [makeUserIdSpanProcessor(input.userId)] : []), + ...(input.userId != null + ? [makeUserIdSpanProcessor(input.userId)] + : []), processor, makeAppRootSpanProcessor(traceState.tracerName), ], }); let isShutdown = false; - yield* Effect.sync(() => provider.register()); + yield* Effect.sync(() => { + provider.register(); + }); return new LangfuseClient({ baseUrl: input.baseUrl, diff --git a/src/utils.ts b/src/utils.ts index 6d8f6d8..8c68f40 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -6,7 +6,7 @@ export const log = (level: "info" | "warn" | "error", message: string) => Effect.gen(function* () { const opencode = yield* OpencodeClientService; - yield* Effect.sync(() => + yield* Effect.tryPromise(() => opencode.app.log({ body: { service: "langfuse", level, message }, }), diff --git a/test/integration/plugin.test.ts b/test/integration/plugin.test.ts index 61d296f..dddbe94 100644 --- a/test/integration/plugin.test.ts +++ b/test/integration/plugin.test.ts @@ -3,6 +3,7 @@ import { createServer } from "node:http"; import type { IncomingHttpHeaders, Server } from "node:http"; import { trace } from "@opentelemetry/api"; +import { Schema } from "effect"; import { afterAll, afterEach, @@ -13,37 +14,56 @@ import { test, } from "vitest"; -interface OtlpValue { - stringValue?: string; - boolValue?: boolean; - intValue?: number; -} - -interface OtlpSpan { - name: string; - traceId: string; - spanId: string; - parentSpanId?: string; - startTimeUnixNano: string; - endTimeUnixNano: string; - attributes: Array<{ key: string; value: OtlpValue }>; - status?: { code?: number; message?: string }; - events?: Array<{ name: string }>; -} - -interface CapturedRequest { +const OtlpValueSchema = Schema.Struct({ + stringValue: Schema.optional(Schema.String), + boolValue: Schema.optional(Schema.Boolean), + intValue: Schema.optional(Schema.Number), +}); +const OtlpAttributeSchema = Schema.Struct({ + key: Schema.String, + value: OtlpValueSchema, +}); +const OtlpSpanSchema = Schema.Struct({ + name: Schema.String, + traceId: Schema.String, + spanId: Schema.String, + parentSpanId: Schema.optional(Schema.String), + startTimeUnixNano: Schema.String, + endTimeUnixNano: Schema.String, + attributes: Schema.Array(OtlpAttributeSchema), + status: Schema.optional( + Schema.Struct({ + code: Schema.optional(Schema.Number), + message: Schema.optional(Schema.String), + }), + ), + events: Schema.optional(Schema.Array(Schema.Struct({ name: Schema.String }))), +}); +const CapturedRequestBodySchema = Schema.Struct({ + resourceSpans: Schema.Array( + Schema.Struct({ + resource: Schema.optional( + Schema.Struct({ + attributes: Schema.optional(Schema.Array(OtlpAttributeSchema)), + }), + ), + scopeSpans: Schema.Array( + Schema.Struct({ spans: Schema.Array(OtlpSpanSchema) }), + ), + }), + ), +}); + +type OtlpSpan = typeof OtlpSpanSchema.Type; + +type CapturedRequest = { method?: string; url?: string; headers: IncomingHttpHeaders; - body: { - resourceSpans: Array<{ - resource?: { attributes?: Array<{ key: string; value: OtlpValue }> }; - scopeSpans: Array<{ spans: OtlpSpan[] }>; - }>; - }; -} + body: typeof CapturedRequestBodySchema.Type; +}; -type Plugin = (typeof import("../../dist/index.js"))["default"]; +type Plugin = (typeof import("../../src/index.js"))["default"]; type PluginHooks = Awaited>; type PluginEvent = Parameters>[0]["event"]; type SessionNextEvent = @@ -127,13 +147,48 @@ type TestPluginEvent = }; }; -const packageJson = JSON.parse( - readFileSync(new URL("../../package.json", import.meta.url), "utf8"), -) as { version?: unknown }; - -if (typeof packageJson.version !== "string") { - throw new Error("Expected package.json to contain a version"); -} +const PluginEventSchema = Schema.declare( + (input): input is PluginEvent => + typeof input === "object" && + input !== null && + "type" in input && + "properties" in input, +); + +const PluginClientSchema = Schema.declare( + (input): input is Parameters[0]["client"] => + typeof input === "object" && + input !== null && + "app" in input && + "tool" in input, +); + +const PluginInputSchema = Schema.declare( + (input): input is Parameters[0] => + typeof input === "object" && input !== null && "client" in input, +); + +const PluginModuleSchema = Schema.declare( + (input): input is { default: Plugin } => + typeof input === "object" && + input !== null && + "default" in input && + typeof input.default === "function", +); + +const McpToolOutputSchema = Schema.declare( + ( + input, + ): input is Parameters>[1] => + typeof input === "object" && + input !== null && + "content" in input && + Array.isArray(input.content), +); + +const packageJson = Schema.decodeUnknownSync( + Schema.parseJson(Schema.Struct({ version: Schema.String })), +)(readFileSync(new URL("../../package.json", import.meta.url), "utf8")); const packageVersion = packageJson.version; @@ -189,7 +244,7 @@ const getJsonAttribute = (span: OtlpSpan, key: string) => { throw new Error(`Expected ${span.name} attribute ${key} to be JSON`); } - return JSON.parse(value) as unknown; + return Schema.decodeUnknownSync(Schema.parseJson(Schema.Unknown))(value); }; const getSpan = (spans: OtlpSpan[], name: string) => { @@ -222,7 +277,9 @@ const getSessionSpan = (spans: OtlpSpan[], name: string, sessionID: string) => { const emitEvent = async (event: TestPluginEvent) => { // These events are emitted by current OpenCode versions but are not yet part of // the PluginEvent union exported by our pinned @opencode-ai/plugin version. - await hooks.event?.({ event: event as PluginEvent }); + await hooks.event?.({ + event: Schema.decodeUnknownSync(PluginEventSchema)(event), + }); }; const flushSession = async (sessionID: string) => { @@ -338,7 +395,7 @@ const completeGeneration = async (input: { completed: number; text?: string; }) => { - if (input.text) { + if (input.text !== undefined && input.text !== "") { await emitEvent({ type: "message.part.updated", properties: { @@ -381,7 +438,7 @@ const completeGeneration = async (input: { const createHooks = async (baseUrl: string) => { process.env.LANGFUSE_BASE_URL = baseUrl; - const client = { + const client = Schema.decodeUnknownSync(PluginClientSchema)({ app: { log: () => Promise.resolve(), }, @@ -417,9 +474,9 @@ const createHooks = async (baseUrl: string) => { }); }, }, - } as unknown as Parameters[0]["client"]; + }); - return plugin({ client } as Parameters[0]); + return plugin(Schema.decodeUnknownSync(PluginInputSchema)({ client })); }; const disposeHooks = async () => { @@ -439,17 +496,21 @@ beforeAll(async () => { server = createServer((request, response) => { const chunks: Buffer[] = []; - request.on("error", (error) => collectorErrors.push(error)); - request.on("data", (chunk: Buffer) => chunks.push(chunk)); + request.on("error", (error) => { + collectorErrors.push(error); + }); + request.on("data", (chunk: Buffer) => { + chunks.push(chunk); + }); request.on("end", () => { try { requests.push({ method: request.method, url: request.url, headers: request.headers, - body: JSON.parse( - Buffer.concat(chunks).toString("utf8"), - ) as CapturedRequest["body"], + body: Schema.decodeUnknownSync( + Schema.parseJson(CapturedRequestBodySchema), + )(Buffer.concat(chunks).toString("utf8")), }); response.writeHead(collectorStatus, { "content-type": "application/json", @@ -465,23 +526,27 @@ beforeAll(async () => { await new Promise((resolve, reject) => { server.once("error", reject); - server.listen(0, "127.0.0.1", () => resolve()); + server.listen(0, "127.0.0.1", () => { + resolve(); + }); }); const address = server.address(); - if (!address || typeof address === "string") { + if (address === null || typeof address === "string") { throw new Error("Expected the test collector to listen on a TCP port"); } process.env.LANGFUSE_PUBLIC_KEY = "pk-test"; process.env.LANGFUSE_SECRET_KEY = "sk-test"; - collectorBaseUrl = `http://127.0.0.1:${address.port}`; + collectorBaseUrl = `http://127.0.0.1:${address.port.toString()}`; process.env.LANGFUSE_BASE_URL = collectorBaseUrl; process.env.LANGFUSE_ENVIRONMENT = "integration-test"; process.env.LANGFUSE_USER_ID = "test-user"; delete process.env.LANGFUSE_BASEURL; - ({ default: plugin } = await import("../../dist/index.js")); + const builtPluginUrl = new URL("../../dist/index.js", import.meta.url); + const builtPlugin: unknown = await import(builtPluginUrl.href); + plugin = Schema.decodeUnknownSync(PluginModuleSchema)(builtPlugin).default; }); beforeEach(async () => { @@ -500,9 +565,15 @@ afterEach(async () => { afterAll(async () => { try { - await new Promise((resolve, reject) => - server.close((error) => (error ? reject(error) : resolve())), - ); + await new Promise((resolve, reject) => { + server.close((error) => { + if (error) { + reject(error); + } else { + resolve(); + } + }); + }); } finally { for (const [name, value] of Object.entries({ LANGFUSE_PUBLIC_KEY: originalEnvironment.publicKey, @@ -513,7 +584,7 @@ afterAll(async () => { LANGFUSE_USER_ID: originalEnvironment.userId, })) { if (value === undefined) { - delete process.env[name]; + Reflect.deleteProperty(process.env, name); } else { process.env[name] = value; } @@ -521,7 +592,7 @@ afterAll(async () => { } }); -describe.sequential("built plugin", () => { +describe("built plugin", { concurrent: false }, () => { test("exports a complete multi-turn OpenCode session", async () => { const sessionID = "happy-session"; const started = startedAt; @@ -597,12 +668,15 @@ describe.sequential("built plugin", () => { (span) => span.name === "opencode.turn" || span.name === "opencode.message.user", )) { - expect(getJsonAttribute(span, "langfuse.observation.input")).toEqual([ - { - role: "user", - content: expect.any(Array), - }, - ]); + const input = Schema.decodeUnknownSync( + Schema.Array( + Schema.Struct({ + role: Schema.Literal("user"), + content: Schema.Array(Schema.Unknown), + }), + ), + )(getJsonAttribute(span, "langfuse.observation.input")); + expect(input).toHaveLength(1); } for (const turn of spans.filter((span) => span.name === "opencode.turn")) { expect(getAttributes(turn)).toMatchObject({ @@ -767,7 +841,7 @@ describe.sequential("built plugin", () => { tool: "mcp_test_tool", args: { query: "test" }, }, - { + Schema.decodeUnknownSync(McpToolOutputSchema)({ content: [ { type: "text", text: "MCP tool result" }, { @@ -779,9 +853,7 @@ describe.sequential("built plugin", () => { }, { type: "image", mimeType: "image/png", data: "aW1hZ2U=" }, ], - } as unknown as Parameters< - NonNullable - >[1], + }), ); const failedMcpCallID = "nested-observations-failed-mcp-call"; await hooks["tool.execute.before"]?.( @@ -795,12 +867,10 @@ describe.sequential("built plugin", () => { tool: "mcp_failing_tool", args: { query: "fail" }, }, - { + Schema.decodeUnknownSync(McpToolOutputSchema)({ content: [{ type: "text", text: "MCP tool failed" }], isError: true, - } as unknown as Parameters< - NonNullable - >[1], + }), ); await emitEvent({ type: "message.part.updated", @@ -1088,10 +1158,10 @@ describe.sequential("built plugin", () => { const userMessageID = "out-of-order-tool-parenting-user"; const started = startedAt; const generations = [1, 2, 3].map((index) => ({ - assistantMessageID: `out-of-order-tool-parenting-assistant-${index}`, - stepID: `out-of-order-tool-parenting-step-${index}`, - tool: `out-of-order-tool-${index}`, - callID: `out-of-order-tool-parenting-call-${index}`, + assistantMessageID: `out-of-order-tool-parenting-assistant-${index.toString()}`, + stepID: `out-of-order-tool-parenting-step-${index.toString()}`, + tool: `out-of-order-tool-${index.toString()}`, + callID: `out-of-order-tool-parenting-call-${index.toString()}`, })); const executeTool = async (generation: (typeof generations)[number]) => { @@ -1214,8 +1284,12 @@ describe.sequential("built plugin", () => { ); }); - expect(span).toBeDefined(); - return span!; + if (!span) { + throw new Error( + `Expected generation for ${generation.assistantMessageID}`, + ); + } + return span; }); const toolSpans = generations.map((generation) => getSpan(spans, generation.tool), @@ -1362,12 +1436,16 @@ describe.sequential("built plugin", () => { }); const firstGeneration = findGeneration(firstAssistantMessageID); const secondGeneration = findGeneration(secondAssistantMessageID); - expect(firstGeneration).toBeDefined(); - expect(secondGeneration).toBeDefined(); + if (!firstGeneration) { + throw new Error("Expected the first generation"); + } + if (!secondGeneration) { + throw new Error("Expected the second generation"); + } const toolSpans = spans.filter((span) => span.name === "bash"); expect(toolSpans).toHaveLength(1); - expect(toolSpans[0].parentSpanId).toBe(firstGeneration!.spanId); + expect(toolSpans[0].parentSpanId).toBe(firstGeneration.spanId); expect(toolSpans[0].startTimeUnixNano).toBe( (BigInt(toolStarted) * 1_000_000n).toString(), ); @@ -1384,7 +1462,7 @@ describe.sequential("built plugin", () => { output: "07f9a68 Fix tool observation parenting", }); expect( - getJsonAttribute(secondGeneration!, "langfuse.observation.input"), + getJsonAttribute(secondGeneration, "langfuse.observation.input"), ).toEqual([ { role: "assistant", @@ -1615,7 +1693,7 @@ describe.sequential("built plugin", () => { const spanIds = new Set(spans.map((span) => span.spanId)); for (const span of spans) { - if (span.parentSpanId) { + if (span.parentSpanId !== undefined && span.parentSpanId !== "") { expect(spanIds.has(span.parentSpanId)).toBe(true); } } @@ -1653,21 +1731,29 @@ describe.sequential("built plugin", () => { cache_write: 1, total: 17, }); - expect(getJsonAttribute(generation, "langfuse.observation.output")).toEqual( - [ - expect.objectContaining({ - role: "assistant", - content: expect.stringContaining("Recovered answer"), - tool_calls: [ - { - id: "stream-error-retry-call-1", - name: "bash", - arguments: JSON.stringify({ command: "echo retry" }), - }, - ], + const output = Schema.decodeUnknownSync( + Schema.Array( + Schema.Struct({ + role: Schema.Literal("assistant"), + content: Schema.String, + tool_calls: Schema.Array( + Schema.Struct({ + id: Schema.String, + name: Schema.String, + arguments: Schema.String, + }), + ), }), - ], - ); + ), + )(getJsonAttribute(generation, "langfuse.observation.output")); + expect(output[0].content).toContain("Recovered answer"); + expect(output[0].tool_calls).toEqual([ + { + id: "stream-error-retry-call-1", + name: "bash", + arguments: JSON.stringify({ command: "echo retry" }), + }, + ]); expect(getSpan(spans, "bash").parentSpanId).toBe(generation.spanId); expect(getSpan(spans, "grep").parentSpanId).toBe(generation.spanId); @@ -1734,21 +1820,31 @@ describe.sequential("built plugin", () => { const retry = await flushSession(retrySessionID); expect(toolListCalls).toBe(2); - expect( + const input = Schema.decodeUnknownSync( + Schema.Array( + Schema.Struct({ + role: Schema.Literal("user"), + content: Schema.Array( + Schema.Struct({ + type: Schema.Literal("text"), + text: Schema.String, + }), + ), + tools: Schema.Array(Schema.Struct({ name: Schema.String })), + }), + ), + )( getJsonAttribute( getSpan(retry.spans, "opencode.generation"), "langfuse.observation.input", ), - ).toEqual([ - { - role: "user", - content: [{ type: "text", text: "Retry tool discovery" }], - tools: expect.arrayContaining([ - expect.objectContaining({ name: "read" }), - expect.objectContaining({ name: "webfetch" }), - ]), - }, + ); + expect(input[0].content).toEqual([ + { type: "text", text: "Retry tool discovery" }, ]); + expect(input[0].tools.map((tool) => tool.name)).toEqual( + expect.arrayContaining(["read", "webfetch"]), + ); }); test("preserves step metadata when the assistant message arrives later", async () => { @@ -2028,17 +2124,19 @@ describe.sequential("built plugin", () => { process.env.OTEL_EXPORTER_OTLP_TRACES_TIMEOUT; process.env.OTEL_EXPORTER_OTLP_TRACES_TIMEOUT = "100"; const unavailableServer = createServer(); - unavailableServer.on("connection", (socket) => socket.destroy()); + unavailableServer.on("connection", (socket) => { + socket.destroy(); + }); await new Promise((resolve, reject) => { unavailableServer.once("error", reject); unavailableServer.listen(0, "127.0.0.1", resolve); }); const address = unavailableServer.address(); - if (!address || typeof address === "string") { + if (address === null || typeof address === "string") { throw new Error("Expected the unavailable collector to use a TCP port"); } hooksDisposed = false; - hooks = await createHooks(`http://127.0.0.1:${address.port}`); + hooks = await createHooks(`http://127.0.0.1:${address.port.toString()}`); try { await sendUserMessage({ sessionID: "unreachable-collector-session", @@ -2057,11 +2155,15 @@ describe.sequential("built plugin", () => { } finally { try { await disposeHooks(); - await new Promise((resolve, reject) => - unavailableServer.close((error) => - error ? reject(error) : resolve(), - ), - ); + await new Promise((resolve, reject) => { + unavailableServer.close((error) => { + if (error) { + reject(error); + } else { + resolve(); + } + }); + }); } finally { if (originalExporterTimeout === undefined) { delete process.env.OTEL_EXPORTER_OTLP_TRACES_TIMEOUT; @@ -2134,7 +2236,7 @@ describe.sequential("built plugin", () => { } finally { for (const [name, value] of Object.entries(originalValues)) { if (value === undefined) { - delete process.env[name]; + Reflect.deleteProperty(process.env, name); } else { process.env[name] = value; } diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json new file mode 100644 index 0000000..899ad5d --- /dev/null +++ b/tsconfig.eslint.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.test.json", + "include": ["src/**/*.ts", "test/**/*.ts", "tsdown.config.ts"] +}