diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..040e25f
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,47 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.java]
+indent_style = space
+indent_size = 4
+max_line_length = 120
+
+[*.xml]
+indent_style = space
+indent_size = 4
+
+[*.{yml,yaml}]
+indent_style = space
+indent_size = 2
+
+[*.json]
+indent_style = space
+indent_size = 2
+
+[*.properties]
+indent_style = space
+indent_size = 4
+
+[*.md]
+trim_trailing_whitespace = false
+
+[*.{sh,bash}]
+indent_style = space
+indent_size = 2
+
+[{mvnw,gradlew}]
+end_of_line = lf
+
+[mvnw.cmd]
+end_of_line = crlf
+
+[gradlew.bat]
+end_of_line = crlf
+
+[Makefile]
+indent_style = tab
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..6b1485e
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,49 @@
+version: 2
+updates:
+ # Maven dependencies
+ - package-ecosystem: maven
+ directory: /
+ schedule:
+ interval: weekly
+ day: monday
+ open-pull-requests-limit: 10
+ groups:
+ junit:
+ patterns:
+ - "org.junit*"
+ - "org.assertj*"
+ - "org.mockito*"
+ jackson:
+ patterns:
+ - "com.fasterxml.jackson*"
+ maven-plugins:
+ patterns:
+ - "org.apache.maven.plugins*"
+ - "com.puppycrawl.tools*"
+ - "com.github.spotbugs*"
+ - "org.jacoco*"
+ logging:
+ patterns:
+ - "org.slf4j*"
+ - "ch.qos.logback*"
+
+ # Gradle dependencies
+ - package-ecosystem: gradle
+ directory: /
+ schedule:
+ interval: weekly
+ day: monday
+ open-pull-requests-limit: 5
+ groups:
+ gradle-plugins:
+ patterns:
+ - "com.github.spotbugs*"
+ - "com.github.johnrengelman*"
+
+ # GitHub Actions
+ - package-ecosystem: github-actions
+ directory: /
+ schedule:
+ interval: weekly
+ day: monday
+ open-pull-requests-limit: 5
diff --git a/.github/workflows/cache-cleanup.yml b/.github/workflows/cache-cleanup.yml
new file mode 100644
index 0000000..6529118
--- /dev/null
+++ b/.github/workflows/cache-cleanup.yml
@@ -0,0 +1,74 @@
+name: Cache Cleanup
+
+on:
+ pull_request:
+ types: [closed]
+ schedule:
+ - cron: '0 3 * * 0' # Sundays at 03:00 UTC
+ workflow_dispatch:
+
+permissions:
+ actions: write
+ contents: read
+
+jobs:
+ cleanup-pr-caches:
+ name: Clean Up PR Caches
+ if: github.event_name == 'pull_request'
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Delete caches for closed PR branch
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ BRANCH: refs/pull/${{ github.event.pull_request.number }}/merge
+ run: |
+ echo "Deleting caches for branch: $BRANCH"
+ gh actions-cache list --branch "$BRANCH" --limit 100 | \
+ cut -f1 | \
+ while read -r key; do
+ if [ -n "$key" ]; then
+ echo "Deleting cache: $key"
+ gh actions-cache delete "$key" --branch "$BRANCH" --confirm || true
+ fi
+ done
+
+ cleanup-stale-caches:
+ name: Clean Up Stale Caches
+ if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: List and clean stale caches
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ echo "=== Current cache usage ==="
+ gh actions-cache list --limit 100 --sort last-used --order asc
+
+ # Get all open PR branch refs
+ OPEN_BRANCHES=$(gh pr list --state open --json headRefName --jq '.[].headRefName')
+
+ # Delete caches for branches that no longer have open PRs
+ gh actions-cache list --limit 100 --sort last-used --order asc | while IFS=$'\t' read -r key size branch; do
+ # Skip main branch caches
+ if [ "$branch" = "refs/heads/main" ]; then
+ continue
+ fi
+
+ # Extract branch name from ref
+ branch_name="${branch#refs/heads/}"
+
+ # Check if branch has an open PR
+ if ! echo "$OPEN_BRANCHES" | grep -qx "$branch_name"; then
+ echo "Deleting stale cache: $key (branch: $branch)"
+ gh actions-cache delete "$key" --branch "$branch" --confirm || true
+ fi
+ done
+
+ echo "=== Cache usage after cleanup ==="
+ gh actions-cache list --limit 100 --sort last-used --order desc
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..84a0597
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,112 @@
+name: CI
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+permissions:
+ contents: read
+ checks: write
+
+jobs:
+ maven:
+ name: Build (Maven, Java ${{ matrix.java }})
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ java: ['21', '23']
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Set up JDK ${{ matrix.java }}
+ uses: actions/setup-java@v4
+ with:
+ java-version: ${{ matrix.java }}
+ distribution: temurin
+ cache: maven
+
+ - name: Build & verify
+ run: ./mvnw verify -Pcoverage -B --no-transfer-progress
+
+ - name: Upload test reports
+ if: always()
+ uses: actions/upload-artifact@v4
+ with:
+ name: maven-test-reports-java-${{ matrix.java }}
+ path: '**/target/surefire-reports/*.xml'
+ retention-days: 14
+
+ - name: Upload coverage reports
+ if: matrix.java == '21'
+ uses: actions/upload-artifact@v4
+ with:
+ name: maven-coverage-reports
+ path: '**/target/site/jacoco/'
+ retention-days: 14
+
+ - name: Publish test results
+ if: always()
+ uses: dorny/test-reporter@v1
+ with:
+ name: Test Results (Maven, Java ${{ matrix.java }})
+ path: '**/target/surefire-reports/*.xml'
+ reporter: java-junit
+
+ gradle:
+ name: Build (Gradle, Java ${{ matrix.java }})
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ java: ['21', '23']
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Set up JDK ${{ matrix.java }}
+ uses: actions/setup-java@v4
+ with:
+ java-version: ${{ matrix.java }}
+ distribution: temurin
+ cache: gradle
+
+ - name: Build & verify
+ run: ./gradlew build --no-daemon --warning-mode all
+
+ - name: Upload test reports
+ if: always()
+ uses: actions/upload-artifact@v4
+ with:
+ name: gradle-test-reports-java-${{ matrix.java }}
+ path: '**/build/reports/tests/'
+ retention-days: 14
+
+ eval-tests:
+ name: Eval Tests (LLM-backed)
+ needs: maven
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Set up JDK 21
+ uses: actions/setup-java@v4
+ with:
+ java-version: '21'
+ distribution: temurin
+ cache: maven
+
+ - name: Run eval tests
+ env:
+ OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
+ run: ./mvnw test -Peval-tests -B --no-transfer-progress
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 0000000..3b7b44f
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,39 @@
+name: CodeQL
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main]
+ schedule:
+ - cron: '0 6 * * 6' # Saturdays at 06:00 UTC
+
+permissions:
+ security-events: write
+ contents: read
+
+jobs:
+ analyze:
+ name: CodeQL Analysis
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Set up JDK 21
+ uses: actions/setup-java@v4
+ with:
+ java-version: '21'
+ distribution: temurin
+ cache: maven
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v3
+ with:
+ languages: java-kotlin
+
+ - name: Build
+ run: ./mvnw compile -B --no-transfer-progress -DskipTests
+
+ - name: Perform CodeQL analysis
+ uses: github/codeql-action/analyze@v3
diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml
new file mode 100644
index 0000000..86a6e3f
--- /dev/null
+++ b/.github/workflows/dependency-review.yml
@@ -0,0 +1,23 @@
+name: Dependency Review
+
+on:
+ pull_request:
+ branches: [main]
+
+permissions:
+ contents: read
+ pull-requests: write
+
+jobs:
+ dependency-review:
+ name: Dependency Review
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Dependency review
+ uses: actions/dependency-review-action@v4
+ with:
+ fail-on-severity: high
+ comment-summary-in-pr: on-failure
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..4732314
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,87 @@
+name: Release
+
+on:
+ push:
+ tags:
+ - 'v*'
+ workflow_dispatch:
+ inputs:
+ version:
+ description: 'Release version (e.g. 0.1.0)'
+ required: true
+
+permissions:
+ contents: write
+ packages: write
+
+jobs:
+ release:
+ name: Build & Publish Release
+ runs-on: ubuntu-latest
+ environment: release
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Set up JDK 21
+ uses: actions/setup-java@v4
+ with:
+ java-version: '21'
+ distribution: temurin
+ cache: maven
+ server-id: ossrh
+ server-username: MAVEN_USERNAME
+ server-password: MAVEN_PASSWORD
+ gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
+ gpg-passphrase: GPG_PASSPHRASE
+
+ - name: Determine version
+ id: version
+ run: |
+ if [ "${{ github.event_name }}" = "push" ]; then
+ echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
+ else
+ echo "version=${{ inputs.version }}" >> "$GITHUB_OUTPUT"
+ fi
+
+ - name: Set release version
+ run: |
+ ./mvnw versions:set -DnewVersion="${{ steps.version.outputs.version }}" -B --no-transfer-progress
+
+ - name: Maven build & verify
+ run: ./mvnw verify -B --no-transfer-progress
+
+ - name: Gradle build & verify
+ run: ./gradlew build --no-daemon
+
+ - name: Deploy to Maven Central
+ env:
+ MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}
+ MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
+ GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
+ run: |
+ ./mvnw deploy -Prelease -DskipTests -B --no-transfer-progress
+
+ - name: Publish Gradle plugin
+ env:
+ GRADLE_PUBLISH_KEY: ${{ secrets.GRADLE_PUBLISH_KEY }}
+ GRADLE_PUBLISH_SECRET: ${{ secrets.GRADLE_PUBLISH_SECRET }}
+ run: |
+ ./gradlew :agenteval-gradle-plugin:publishPlugins \
+ -Pgradle.publish.key=$GRADLE_PUBLISH_KEY \
+ -Pgradle.publish.secret=$GRADLE_PUBLISH_SECRET \
+ --no-daemon
+ continue-on-error: true
+
+ - name: Create GitHub release
+ uses: softprops/action-gh-release@v2
+ with:
+ tag_name: ${{ github.event_name == 'push' && github.ref_name || format('v{0}', inputs.version) }}
+ name: AgentEval ${{ steps.version.outputs.version }}
+ generate_release_notes: true
+ draft: false
+ prerelease: ${{ contains(steps.version.outputs.version, '-') }}
+ files: |
+ agenteval-core/target/agenteval-core-*.jar
+ agenteval-junit5/target/agenteval-junit5-*.jar
+ agenteval-metrics/target/agenteval-metrics-*.jar
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
new file mode 100644
index 0000000..5cf6833
--- /dev/null
+++ b/.github/workflows/stale.yml
@@ -0,0 +1,32 @@
+name: Stale Issues & PRs
+
+on:
+ schedule:
+ - cron: '0 9 * * *' # Daily at 09:00 UTC
+
+permissions:
+ issues: write
+ pull-requests: write
+
+jobs:
+ stale:
+ name: Mark Stale Issues & PRs
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/stale@v9
+ with:
+ days-before-stale: 60
+ days-before-close: 14
+ stale-issue-label: stale
+ stale-pr-label: stale
+ stale-issue-message: >
+ This issue has been automatically marked as stale because it has not
+ had recent activity. It will be closed in 14 days if no further
+ activity occurs. If this issue is still relevant, please comment or
+ remove the stale label.
+ stale-pr-message: >
+ This pull request has been automatically marked as stale because it
+ has not had recent activity. It will be closed in 14 days if no
+ further activity occurs.
+ exempt-issue-labels: pinned,security,bug
+ exempt-pr-labels: pinned,security
diff --git a/.gitignore b/.gitignore
index 48503cb..939a1a9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,6 +35,9 @@ build/
.idea/
*.iml
+# Maven wrapper jar (downloaded on demand)
+.mvn/wrapper/maven-wrapper.jar
+
# Misc
.vscode
CLAUDE.md
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..ffcab66
--- /dev/null
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,3 @@
+wrapperVersion=3.3.4
+distributionType=only-script
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..2d76d10
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,43 @@
+repos:
+ # Standard file checks
+ - repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v5.0.0
+ hooks:
+ - id: trailing-whitespace
+ exclude: '\.md$'
+ - id: end-of-file-fixer
+ - id: check-yaml
+ - id: check-xml
+ - id: check-json
+ - id: check-merge-conflict
+ - id: check-added-large-files
+ args: ['--maxkb=500']
+ - id: mixed-line-ending
+ args: ['--fix=lf']
+
+ # EditorConfig compliance
+ - repo: https://github.com/editorconfig-checker/editorconfig-checker.python
+ rev: 3.2.1
+ hooks:
+ - id: editorconfig-checker
+ alias: ec
+ exclude: '(\.jar|\.class|gradlew\.bat|mvnw\.cmd)$'
+
+ # Local hooks
+ - repo: local
+ hooks:
+ # Checkstyle via Maven (runs only when Java files change)
+ - id: checkstyle
+ name: checkstyle
+ entry: ./mvnw checkstyle:check -q -B --no-transfer-progress
+ language: system
+ types: [java]
+ pass_filenames: false
+
+ # Detect accidentally committed secrets
+ - id: no-credentials
+ name: no-credentials
+ entry: '(?i)(api[_-]?key|secret[_-]?key|password|passwd|credential|token)\s*[:=]\s*["\x27][A-Za-z0-9+/=_-]{16,}'
+ language: pygrep
+ types: [text]
+ exclude: '(\.pre-commit-config\.yaml|CLAUDE\.md|agent-eval-feature-spec\.md|\.github/)$'
diff --git a/agenteval-bom/pom.xml b/agenteval-bom/pom.xml
new file mode 100644
index 0000000..9653cb7
--- /dev/null
+++ b/agenteval-bom/pom.xml
@@ -0,0 +1,104 @@
+
+
+ 4.0.0
+
+ com.agenteval
+ agenteval-bom
+ 0.1.0-SNAPSHOT
+ pom
+
+ AgentEval BOM
+ Bill of Materials for AgentEval dependency management
+ https://github.com/agenteval/agenteval
+
+
+
+ Apache License, Version 2.0
+ https://www.apache.org/licenses/LICENSE-2.0
+
+
+
+
+
+
+
+ com.agenteval
+ agenteval-core
+ ${project.version}
+
+
+
+
+ com.agenteval
+ agenteval-judge
+ ${project.version}
+
+
+
+
+ com.agenteval
+ agenteval-metrics
+ ${project.version}
+
+
+
+
+ com.agenteval
+ agenteval-embeddings
+ ${project.version}
+
+
+
+
+ com.agenteval
+ agenteval-junit5
+ ${project.version}
+
+
+
+
+ com.agenteval
+ agenteval-datasets
+ ${project.version}
+
+
+
+
+ com.agenteval
+ agenteval-reporting
+ ${project.version}
+
+
+
+
+ com.agenteval
+ agenteval-spring-ai
+ ${project.version}
+
+
+ com.agenteval
+ agenteval-langchain4j
+ ${project.version}
+
+
+ com.agenteval
+ agenteval-langgraph4j
+ ${project.version}
+
+
+ com.agenteval
+ agenteval-mcp
+ ${project.version}
+
+
+
+
+ com.agenteval
+ agenteval-redteam
+ ${project.version}
+
+
+
+
diff --git a/agenteval-core/src/main/java/com/agenteval/core/config/AgentEvalConfig.java b/agenteval-core/src/main/java/com/agenteval/core/config/AgentEvalConfig.java
index db4b0dd..b90004a 100644
--- a/agenteval-core/src/main/java/com/agenteval/core/config/AgentEvalConfig.java
+++ b/agenteval-core/src/main/java/com/agenteval/core/config/AgentEvalConfig.java
@@ -2,6 +2,7 @@
import com.agenteval.core.cost.PricingModel;
import com.agenteval.core.embedding.EmbeddingModel;
+import com.agenteval.core.judge.CachingJudgeModel;
import com.agenteval.core.judge.JudgeModel;
import com.agenteval.core.eval.ProgressCallback;
@@ -123,6 +124,10 @@ public Builder progressCallback(ProgressCallback callback) {
}
public AgentEvalConfig build() {
+ if (cacheJudgeResults && judgeModel != null
+ && !(judgeModel instanceof CachingJudgeModel)) {
+ judgeModel = new CachingJudgeModel(judgeModel);
+ }
return new AgentEvalConfig(this);
}
}
diff --git a/agenteval-core/src/main/java/com/agenteval/core/judge/CachingJudgeModel.java b/agenteval-core/src/main/java/com/agenteval/core/judge/CachingJudgeModel.java
new file mode 100644
index 0000000..6e7662c
--- /dev/null
+++ b/agenteval-core/src/main/java/com/agenteval/core/judge/CachingJudgeModel.java
@@ -0,0 +1,70 @@
+package com.agenteval.core.judge;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * Decorator that caches judge responses to avoid redundant LLM calls
+ * for identical evaluation prompts.
+ *
+ *
Cache keys are the full prompt strings. Cached responses include
+ * the score, reason, and token usage from the original call.
+ *
+ * Thread-safe — safe for use with parallel evaluation via virtual threads.
+ *
+ * {@code
+ * JudgeModel cached = new CachingJudgeModel(delegate);
+ * // Second call with same prompt returns cached result without LLM call
+ * JudgeResponse r1 = cached.judge("evaluate...");
+ * JudgeResponse r2 = cached.judge("evaluate..."); // cache hit
+ * }
+ */
+public final class CachingJudgeModel implements JudgeModel {
+
+ private static final Logger LOG = LoggerFactory.getLogger(CachingJudgeModel.class);
+
+ private final JudgeModel delegate;
+ private final ConcurrentMap cache;
+
+ public CachingJudgeModel(JudgeModel delegate) {
+ this.delegate = Objects.requireNonNull(delegate, "delegate must not be null");
+ this.cache = new ConcurrentHashMap<>();
+ }
+
+ @Override
+ public JudgeResponse judge(String prompt) {
+ JudgeResponse cached = cache.get(prompt);
+ if (cached != null) {
+ LOG.debug("Cache hit for judge prompt (length={})", prompt.length());
+ return cached;
+ }
+
+ LOG.debug("Cache miss for judge prompt (length={})", prompt.length());
+ JudgeResponse response = delegate.judge(prompt);
+ cache.put(prompt, response);
+ return response;
+ }
+
+ @Override
+ public String modelId() {
+ return delegate.modelId();
+ }
+
+ /**
+ * Returns the number of cached entries.
+ */
+ public int cacheSize() {
+ return cache.size();
+ }
+
+ /**
+ * Clears all cached judge responses.
+ */
+ public void clearCache() {
+ cache.clear();
+ }
+}
diff --git a/agenteval-datasets/build.gradle.kts b/agenteval-datasets/build.gradle.kts
index cac4a72..eb967e5 100644
--- a/agenteval-datasets/build.gradle.kts
+++ b/agenteval-datasets/build.gradle.kts
@@ -2,6 +2,7 @@ dependencies {
api(project(":agenteval-core"))
implementation(project(":agenteval-judge"))
implementation(libs.jackson.databind)
+ implementation(libs.jackson.dataformat.yaml)
implementation(libs.jackson.datatype.jsr310)
implementation(libs.slf4j.api)
testImplementation(libs.mockito.core)
diff --git a/agenteval-datasets/pom.xml b/agenteval-datasets/pom.xml
index 1fd2b9a..9bab315 100644
--- a/agenteval-datasets/pom.xml
+++ b/agenteval-datasets/pom.xml
@@ -1,7 +1,7 @@
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
@@ -32,6 +32,10 @@
com.fasterxml.jackson.datatype
jackson-datatype-jsr310
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-yaml
+
org.slf4j
slf4j-api
diff --git a/agenteval-datasets/src/main/java/com/agenteval/datasets/DatasetFormat.java b/agenteval-datasets/src/main/java/com/agenteval/datasets/DatasetFormat.java
index 96a8d97..e0dc928 100644
--- a/agenteval-datasets/src/main/java/com/agenteval/datasets/DatasetFormat.java
+++ b/agenteval-datasets/src/main/java/com/agenteval/datasets/DatasetFormat.java
@@ -6,7 +6,7 @@
* Supported dataset file formats.
*/
public enum DatasetFormat {
- JSON, JSONL, CSV;
+ JSON, JSONL, CSV, YAML;
/**
* Auto-detects the dataset format from a file path extension.
@@ -27,8 +27,10 @@ public static DatasetFormat detect(Path path) {
return JSON;
} else if (name.endsWith(".csv")) {
return CSV;
+ } else if (name.endsWith(".yaml") || name.endsWith(".yml")) {
+ return YAML;
}
throw new DatasetException("Unsupported dataset format: " + name
- + ". Supported extensions: .json, .jsonl, .csv");
+ + ". Supported extensions: .json, .jsonl, .csv, .yaml, .yml");
}
}
diff --git a/agenteval-datasets/src/main/java/com/agenteval/datasets/DatasetLoaders.java b/agenteval-datasets/src/main/java/com/agenteval/datasets/DatasetLoaders.java
index 0fecb62..1216d66 100644
--- a/agenteval-datasets/src/main/java/com/agenteval/datasets/DatasetLoaders.java
+++ b/agenteval-datasets/src/main/java/com/agenteval/datasets/DatasetLoaders.java
@@ -3,6 +3,7 @@
import com.agenteval.datasets.csv.CsvDatasetLoader;
import com.agenteval.datasets.json.JsonDatasetLoader;
import com.agenteval.datasets.jsonl.JsonlDatasetLoader;
+import com.agenteval.datasets.yaml.YamlDatasetLoader;
import java.nio.file.Path;
@@ -30,6 +31,7 @@ public static EvalDataset forPath(Path path) {
case JSON -> new JsonDatasetLoader().load(path);
case JSONL -> new JsonlDatasetLoader().load(path);
case CSV -> new CsvDatasetLoader().load(path);
+ case YAML -> new YamlDatasetLoader().load(path);
};
}
}
diff --git a/agenteval-datasets/src/main/java/com/agenteval/datasets/EvalDataset.java b/agenteval-datasets/src/main/java/com/agenteval/datasets/EvalDataset.java
index e6612ec..4e2bbac 100644
--- a/agenteval-datasets/src/main/java/com/agenteval/datasets/EvalDataset.java
+++ b/agenteval-datasets/src/main/java/com/agenteval/datasets/EvalDataset.java
@@ -70,6 +70,7 @@ public void save(Path path, DatasetFormat format) {
case JSON -> new JsonDatasetWriter().write(this, path);
case JSONL -> new JsonlDatasetWriter().write(this, path);
case CSV -> new CsvDatasetWriter().write(this, path);
+ case YAML -> throw new DatasetException("YAML format is read-only");
default -> throw new DatasetException("Unsupported format: " + format);
}
}
diff --git a/agenteval-datasets/src/main/java/com/agenteval/datasets/yaml/YamlDatasetLoader.java b/agenteval-datasets/src/main/java/com/agenteval/datasets/yaml/YamlDatasetLoader.java
new file mode 100644
index 0000000..c8a0837
--- /dev/null
+++ b/agenteval-datasets/src/main/java/com/agenteval/datasets/yaml/YamlDatasetLoader.java
@@ -0,0 +1,88 @@
+package com.agenteval.datasets.yaml;
+
+import com.agenteval.core.model.AgentTestCase;
+import com.agenteval.datasets.DatasetException;
+import com.agenteval.datasets.DatasetLoader;
+import com.agenteval.datasets.EvalDataset;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+
+/**
+ * Loads evaluation datasets from YAML files (read-only).
+ *
+ * Supports two formats:
+ *
+ * - Envelope format: top-level object with {@code name}, {@code testCases} keys
+ * - Bare list format: a YAML sequence of test case objects
+ *
+ *
+ * {@code
+ * EvalDataset dataset = new YamlDatasetLoader().load(Path.of("golden-set.yaml"));
+ * }
+ */
+public final class YamlDatasetLoader implements DatasetLoader {
+
+ private static final Logger LOG = LoggerFactory.getLogger(YamlDatasetLoader.class);
+ private static final TypeReference> TEST_CASE_LIST =
+ new TypeReference<>() { };
+
+ private final ObjectMapper yamlMapper;
+
+ public YamlDatasetLoader() {
+ this(new ObjectMapper(new YAMLFactory()));
+ }
+
+ public YamlDatasetLoader(ObjectMapper yamlMapper) {
+ this.yamlMapper = yamlMapper;
+ }
+
+ @Override
+ public EvalDataset load(Path path) {
+ LOG.debug("Loading YAML dataset from {}", path);
+ try (InputStream in = Files.newInputStream(path)) {
+ return load(in);
+ } catch (IOException e) {
+ throw new DatasetException("Failed to load YAML dataset from " + path, e);
+ }
+ }
+
+ @Override
+ public EvalDataset load(InputStream inputStream) {
+ LOG.debug("Loading YAML dataset from input stream");
+ try {
+ byte[] bytes = inputStream.readAllBytes();
+ return parse(bytes);
+ } catch (IOException e) {
+ throw new DatasetException("Failed to load YAML dataset from input stream", e);
+ }
+ }
+
+ private EvalDataset parse(byte[] bytes) throws IOException {
+ // Try envelope format first (object with name/testCases)
+ try {
+ EvalDataset dataset = yamlMapper.readValue(bytes, EvalDataset.class);
+ if (dataset.getTestCases() != null && !dataset.getTestCases().isEmpty()) {
+ LOG.debug("Detected envelope format");
+ return dataset;
+ }
+ } catch (IOException ignored) {
+ // fall through to bare list
+ }
+
+ // Try bare list format
+ LOG.debug("Detected bare list format");
+ List testCases = yamlMapper.readValue(bytes, TEST_CASE_LIST);
+ return EvalDataset.builder()
+ .testCases(testCases)
+ .build();
+ }
+}
diff --git a/agenteval-judge/src/main/java/com/agenteval/judge/provider/AbstractHttpJudgeModel.java b/agenteval-judge/src/main/java/com/agenteval/judge/provider/AbstractHttpJudgeModel.java
index 6ba0a64..f9b8c98 100644
--- a/agenteval-judge/src/main/java/com/agenteval/judge/provider/AbstractHttpJudgeModel.java
+++ b/agenteval-judge/src/main/java/com/agenteval/judge/provider/AbstractHttpJudgeModel.java
@@ -19,7 +19,10 @@
* delegates to {@link #buildRequest(String)} and {@link #parseResponse(HttpJudgeResponse)}
* which subclasses implement for provider-specific formats.
*/
-public abstract class AbstractHttpJudgeModel implements JudgeModel {
+public abstract sealed class AbstractHttpJudgeModel implements JudgeModel
+ permits OpenAiJudgeModel, AnthropicJudgeModel, GoogleJudgeModel,
+ OllamaJudgeModel, AzureOpenAiJudgeModel, BedrockJudgeModel,
+ CustomHttpJudgeModel {
private static final Logger LOG = LoggerFactory.getLogger(AbstractHttpJudgeModel.class);
diff --git a/agenteval-junit5/src/main/java/com/agenteval/junit5/annotation/EvalTimeout.java b/agenteval-junit5/src/main/java/com/agenteval/junit5/annotation/EvalTimeout.java
new file mode 100644
index 0000000..b2b11ae
--- /dev/null
+++ b/agenteval-junit5/src/main/java/com/agenteval/junit5/annotation/EvalTimeout.java
@@ -0,0 +1,39 @@
+package com.agenteval.junit5.annotation;
+
+import com.agenteval.junit5.extension.AgentEvalExtension;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Sets the maximum time allowed for metric evaluation to complete.
+ *
+ * If the evaluation (including LLM judge calls) exceeds the specified
+ * duration, the test fails with a timeout error.
+ *
+ * {@code
+ * @AgentTest
+ * @EvalTimeout(value = 30, unit = TimeUnit.SECONDS)
+ * @Metric(value = FaithfulnessMetric.class, threshold = 0.8)
+ * void testWithTimeout(AgentTestCase testCase) { ... }
+ * }
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@ExtendWith(AgentEvalExtension.class)
+public @interface EvalTimeout {
+
+ /**
+ * The timeout duration.
+ */
+ long value();
+
+ /**
+ * The time unit for the timeout. Defaults to {@link TimeUnit#SECONDS}.
+ */
+ TimeUnit unit() default TimeUnit.SECONDS;
+}
diff --git a/agenteval-junit5/src/main/java/com/agenteval/junit5/annotation/GoldenSet.java b/agenteval-junit5/src/main/java/com/agenteval/junit5/annotation/GoldenSet.java
new file mode 100644
index 0000000..14410aa
--- /dev/null
+++ b/agenteval-junit5/src/main/java/com/agenteval/junit5/annotation/GoldenSet.java
@@ -0,0 +1,33 @@
+package com.agenteval.junit5.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Injects a golden dataset into a parameterized test parameter.
+ *
+ * Applied to a method parameter of type {@code EvalDataset} or
+ * {@code List} to automatically load and inject a golden
+ * dataset from the specified path.
+ *
+ * {@code
+ * @AgentTest
+ * void testWithGoldenSet(@GoldenSet("src/test/resources/golden.json") EvalDataset dataset) {
+ * for (var testCase : dataset.testCases()) {
+ * testCase.setActualOutput(agent.ask(testCase.getInput()));
+ * }
+ * }
+ * }
+ */
+@Target(ElementType.PARAMETER)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface GoldenSet {
+
+ /**
+ * Path to the golden dataset file (JSON, JSONL, CSV, or YAML).
+ * Resolved relative to the project root or classpath.
+ */
+ String value();
+}
diff --git a/agenteval-junit5/src/main/java/com/agenteval/junit5/annotation/JudgeModelConfig.java b/agenteval-junit5/src/main/java/com/agenteval/junit5/annotation/JudgeModelConfig.java
new file mode 100644
index 0000000..79a5ddd
--- /dev/null
+++ b/agenteval-junit5/src/main/java/com/agenteval/junit5/annotation/JudgeModelConfig.java
@@ -0,0 +1,48 @@
+package com.agenteval.junit5.annotation;
+
+import com.agenteval.junit5.extension.AgentEvalExtension;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Overrides the judge LLM for a specific test class or method.
+ *
+ * When placed on a test class, all {@code @AgentTest} methods in that class
+ * use the specified judge. When placed on a method, it overrides the class-level
+ * configuration for that method only.
+ *
+ * {@code
+ * @JudgeModelConfig(provider = "openai", model = "gpt-4o-mini")
+ * class FastEvalTests {
+ *
+ * @AgentTest
+ * @JudgeModelConfig(provider = "anthropic", model = "claude-sonnet-4-20250514")
+ * void highQualityTest(AgentTestCase testCase) { ... }
+ * }
+ * }
+ */
+@Target({ElementType.TYPE, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@ExtendWith(AgentEvalExtension.class)
+public @interface JudgeModelConfig {
+
+ /**
+ * The judge provider name (e.g., "openai", "anthropic", "ollama").
+ */
+ String provider();
+
+ /**
+ * The model identifier (e.g., "gpt-4o", "claude-sonnet-4-20250514").
+ */
+ String model();
+
+ /**
+ * API key for the judge provider. Defaults to empty string,
+ * which means the key is read from the standard environment variable.
+ */
+ String apiKey() default "";
+}
diff --git a/agenteval-junit5/src/main/java/com/agenteval/junit5/assertion/AgentTestCaseAssert.java b/agenteval-junit5/src/main/java/com/agenteval/junit5/assertion/AgentTestCaseAssert.java
index 625977c..9cf8254 100644
--- a/agenteval-junit5/src/main/java/com/agenteval/junit5/assertion/AgentTestCaseAssert.java
+++ b/agenteval-junit5/src/main/java/com/agenteval/junit5/assertion/AgentTestCaseAssert.java
@@ -107,6 +107,41 @@ public AgentTestCaseAssert hasOutput() {
return this;
}
+ /**
+ * Asserts that the test case has exactly the given number of tool calls.
+ */
+ public AgentTestCaseAssert toolCallCount(int expectedCount) {
+ int actual = testCase.getToolCalls().size();
+ if (actual != expectedCount) {
+ throw new AssertionError("Expected " + expectedCount
+ + " tool call(s) but found " + actual);
+ }
+ return this;
+ }
+
+ /**
+ * Asserts that the actual output matches the expected JSON schema
+ * by attempting to deserialize it into the given class.
+ *
+ * @param schemaClass the class representing the expected schema
+ */
+ public AgentTestCaseAssert outputMatchesSchema(Class> schemaClass) {
+ String actual = testCase.getActualOutput();
+ if (actual == null || actual.isBlank()) {
+ throw new AssertionError("Expected output matching schema "
+ + schemaClass.getSimpleName() + ", but output was empty");
+ }
+ try {
+ com.fasterxml.jackson.databind.ObjectMapper mapper =
+ new com.fasterxml.jackson.databind.ObjectMapper();
+ mapper.readValue(actual, schemaClass);
+ } catch (Exception e) {
+ throw new AssertionError("Output does not match schema "
+ + schemaClass.getSimpleName() + ": " + e.getMessage());
+ }
+ return this;
+ }
+
/**
* Returns the underlying test case for further inspection.
*/
diff --git a/agenteval-junit5/src/main/java/com/agenteval/junit5/extension/AgentEvalExtension.java b/agenteval-junit5/src/main/java/com/agenteval/junit5/extension/AgentEvalExtension.java
index f1bdfa1..b2357e0 100644
--- a/agenteval-junit5/src/main/java/com/agenteval/junit5/extension/AgentEvalExtension.java
+++ b/agenteval-junit5/src/main/java/com/agenteval/junit5/extension/AgentEvalExtension.java
@@ -5,6 +5,11 @@
import com.agenteval.core.metric.EvalMetric;
import com.agenteval.core.model.AgentTestCase;
import com.agenteval.core.model.EvalScore;
+import com.agenteval.datasets.DatasetLoaders;
+import com.agenteval.datasets.EvalDataset;
+import com.agenteval.junit5.annotation.EvalTimeout;
+import com.agenteval.junit5.annotation.GoldenSet;
+import com.agenteval.junit5.annotation.JudgeModelConfig;
import com.agenteval.junit5.annotation.Metric;
import com.agenteval.junit5.annotation.Metrics;
import org.junit.jupiter.api.extension.AfterEachCallback;
@@ -18,14 +23,22 @@
import org.slf4j.LoggerFactory;
import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
/**
* JUnit 5 extension that provides {@link AgentTestCase} parameter resolution,
* captures test case instances via invocation interception, and evaluates
* declared {@link Metric} annotations after each test.
*
+ * Supports {@link GoldenSet} parameter injection, {@link JudgeModelConfig}
+ * overrides, and {@link EvalTimeout} for time-limited evaluations.
+ *
* Registered automatically via {@code @AgentTest}, {@code @Metric},
* or {@code @Metrics} meta-annotations. Can also be registered explicitly:
*
@@ -65,13 +78,34 @@ public static AgentEvalExtension withConfig(AgentEvalConfig config) {
@Override
public boolean supportsParameter(ParameterContext parameterContext,
- ExtensionContext extensionContext) {
- return parameterContext.getParameter().getType() == AgentTestCase.class;
+ ExtensionContext extensionContext) {
+ Parameter param = parameterContext.getParameter();
+ if (param.getType() == AgentTestCase.class) {
+ return true;
+ }
+ if (param.isAnnotationPresent(GoldenSet.class)) {
+ return param.getType() == EvalDataset.class
+ || param.getType() == List.class;
+ }
+ return false;
}
@Override
public Object resolveParameter(ParameterContext parameterContext,
- ExtensionContext extensionContext) {
+ ExtensionContext extensionContext) {
+ Parameter param = parameterContext.getParameter();
+
+ // Handle @GoldenSet injection
+ if (param.isAnnotationPresent(GoldenSet.class)) {
+ GoldenSet goldenSet = param.getAnnotation(GoldenSet.class);
+ EvalDataset dataset = DatasetLoaders.forPath(Path.of(goldenSet.value()));
+ if (param.getType() == List.class) {
+ return dataset.getTestCases();
+ }
+ return dataset;
+ }
+
+ // Default: resolve AgentTestCase
var store = extensionContext.getStore(NS);
AgentTestCase testCase = store.get(TEST_CASE_KEY, AgentTestCase.class);
if (testCase == null) {
@@ -85,22 +119,22 @@ public Object resolveParameter(ParameterContext parameterContext,
@Override
public void interceptTestMethod(Invocation invocation,
- ReflectiveInvocationContext invocationContext,
- ExtensionContext extensionContext) throws Throwable {
+ ReflectiveInvocationContext invocationContext,
+ ExtensionContext extensionContext) throws Throwable {
captureTestCase(invocationContext, extensionContext);
invocation.proceed();
}
@Override
public void interceptTestTemplateMethod(Invocation invocation,
- ReflectiveInvocationContext invocationContext,
- ExtensionContext extensionContext) throws Throwable {
+ ReflectiveInvocationContext invocationContext,
+ ExtensionContext extensionContext) throws Throwable {
captureTestCase(invocationContext, extensionContext);
invocation.proceed();
}
private void captureTestCase(ReflectiveInvocationContext invocationContext,
- ExtensionContext extensionContext) {
+ ExtensionContext extensionContext) {
for (Object arg : invocationContext.getArguments()) {
if (arg instanceof AgentTestCase tc) {
extensionContext.getStore(NS).put(TEST_CASE_KEY, tc);
@@ -122,7 +156,45 @@ public void afterEach(ExtensionContext context) {
return;
}
- JudgeModel judgeModel = resolveJudgeModel();
+ JudgeModel judgeModel = resolveJudgeModel(context);
+
+ // Check for @EvalTimeout
+ EvalTimeout timeout = context.getTestMethod()
+ .map(m -> m.getAnnotation(EvalTimeout.class))
+ .orElse(null);
+
+ if (timeout != null) {
+ evaluateWithTimeout(metricAnnotations, testCase, judgeModel,
+ timeout.value(), timeout.unit());
+ } else {
+ evaluateMetrics(metricAnnotations, testCase, judgeModel);
+ }
+ }
+
+ private void evaluateWithTimeout(List metricAnnotations,
+ AgentTestCase testCase, JudgeModel judgeModel,
+ long duration, TimeUnit unit) {
+ try {
+ CompletableFuture.runAsync(() ->
+ evaluateMetrics(metricAnnotations, testCase, judgeModel)
+ ).get(duration, unit);
+ } catch (TimeoutException e) {
+ throw new AssertionError(String.format(
+ "Metric evaluation timed out after %d %s", duration, unit));
+ } catch (java.util.concurrent.ExecutionException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof AssertionError ae) {
+ throw ae;
+ }
+ throw new AssertionError("Metric evaluation failed: " + cause.getMessage(), cause);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new AssertionError("Metric evaluation interrupted", e);
+ }
+ }
+
+ private void evaluateMetrics(List metricAnnotations,
+ AgentTestCase testCase, JudgeModel judgeModel) {
List failures = new ArrayList<>();
for (Metric metricAnn : metricAnnotations) {
@@ -165,10 +237,49 @@ private List findMetricAnnotations(ExtensionContext context) {
.orElse(List.of());
}
- private JudgeModel resolveJudgeModel() {
+ /**
+ * Resolves the judge model, checking for {@code @JudgeModelConfig} override
+ * on the method first, then on the class, then falling back to the config.
+ */
+ private JudgeModel resolveJudgeModel(ExtensionContext context) {
+ // Check method-level @JudgeModelConfig
+ JudgeModelConfig methodLevel = context.getTestMethod()
+ .map(m -> m.getAnnotation(JudgeModelConfig.class))
+ .orElse(null);
+ if (methodLevel != null) {
+ return createJudgeFromAnnotation(methodLevel);
+ }
+
+ // Check class-level @JudgeModelConfig
+ JudgeModelConfig classLevel = context.getTestClass()
+ .map(c -> c.getAnnotation(JudgeModelConfig.class))
+ .orElse(null);
+ if (classLevel != null) {
+ return createJudgeFromAnnotation(classLevel);
+ }
+
+ // Fall back to config
if (config != null) {
return config.judgeModel();
}
return null;
}
+
+ private JudgeModel createJudgeFromAnnotation(JudgeModelConfig annotation) {
+ String apiKey = annotation.apiKey().isEmpty()
+ ? resolveApiKeyFromEnv(annotation.provider())
+ : annotation.apiKey();
+
+ return JudgeModelResolver.resolve(annotation.provider(), annotation.model(), apiKey);
+ }
+
+ private String resolveApiKeyFromEnv(String provider) {
+ return switch (provider.toLowerCase()) {
+ case "openai" -> System.getenv("OPENAI_API_KEY");
+ case "anthropic" -> System.getenv("ANTHROPIC_API_KEY");
+ case "google" -> System.getenv("GOOGLE_API_KEY");
+ case "azure" -> System.getenv("AZURE_OPENAI_API_KEY");
+ default -> null;
+ };
+ }
}
diff --git a/agenteval-junit5/src/main/java/com/agenteval/junit5/extension/DatasetArgumentsProvider.java b/agenteval-junit5/src/main/java/com/agenteval/junit5/extension/DatasetArgumentsProvider.java
index 660733d..ae90ea4 100644
--- a/agenteval-junit5/src/main/java/com/agenteval/junit5/extension/DatasetArgumentsProvider.java
+++ b/agenteval-junit5/src/main/java/com/agenteval/junit5/extension/DatasetArgumentsProvider.java
@@ -6,6 +6,7 @@
import com.agenteval.datasets.csv.CsvDatasetLoader;
import com.agenteval.datasets.json.JsonDatasetLoader;
import com.agenteval.datasets.jsonl.JsonlDatasetLoader;
+import com.agenteval.datasets.yaml.YamlDatasetLoader;
import com.agenteval.junit5.annotation.DatasetSource;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.provider.Arguments;
@@ -45,6 +46,7 @@ public Stream extends Arguments> provideArguments(ExtensionContext context) {
case JSON -> new JsonDatasetLoader().load(is);
case JSONL -> new JsonlDatasetLoader().load(is);
case CSV -> new CsvDatasetLoader().load(is);
+ case YAML -> new YamlDatasetLoader().load(is);
};
return dataset.getTestCases().stream().map(Arguments::of);
}
diff --git a/agenteval-junit5/src/main/java/com/agenteval/junit5/extension/JudgeModelResolver.java b/agenteval-junit5/src/main/java/com/agenteval/junit5/extension/JudgeModelResolver.java
new file mode 100644
index 0000000..cd301c6
--- /dev/null
+++ b/agenteval-junit5/src/main/java/com/agenteval/junit5/extension/JudgeModelResolver.java
@@ -0,0 +1,88 @@
+package com.agenteval.junit5.extension;
+
+import com.agenteval.core.judge.JudgeModel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Constructor;
+
+/**
+ * Resolves a {@link JudgeModel} from provider name, model ID, and API key.
+ *
+ * Attempts to load the appropriate judge model implementation from
+ * the {@code agenteval-judge} module via reflection, falling back to a
+ * no-op model if the provider class is not on the classpath.
+ */
+final class JudgeModelResolver {
+
+ private static final Logger LOG = LoggerFactory.getLogger(JudgeModelResolver.class);
+
+ private static final String JUDGE_PACKAGE = "com.agenteval.judge.provider.";
+
+ private JudgeModelResolver() {}
+
+ /**
+ * Resolves a judge model for the given provider and model ID.
+ *
+ * @param provider the provider name (e.g., "openai", "anthropic")
+ * @param model the model identifier
+ * @param apiKey the API key (may be null)
+ * @return a configured JudgeModel instance
+ */
+ static JudgeModel resolve(String provider, String model, String apiKey) {
+ String className = resolveClassName(provider);
+ try {
+ Class> clazz = Class.forName(className);
+ return instantiate(clazz, model, apiKey);
+ } catch (ClassNotFoundException e) {
+ LOG.warn("Judge provider class '{}' not found on classpath. "
+ + "Add agenteval-judge dependency.", className);
+ throw new MetricFactory.MetricInstantiationException(
+ "Judge provider '" + provider + "' not found. "
+ + "Ensure agenteval-judge is on the classpath.");
+ }
+ }
+
+ private static String resolveClassName(String provider) {
+ return switch (provider.toLowerCase()) {
+ case "openai" -> JUDGE_PACKAGE + "OpenAiJudgeModel";
+ case "anthropic" -> JUDGE_PACKAGE + "AnthropicJudgeModel";
+ case "google" -> JUDGE_PACKAGE + "GoogleJudgeModel";
+ case "ollama" -> JUDGE_PACKAGE + "OllamaJudgeModel";
+ case "azure", "azure_openai" -> JUDGE_PACKAGE + "AzureOpenAiJudgeModel";
+ case "bedrock" -> JUDGE_PACKAGE + "BedrockJudgeModel";
+ default -> JUDGE_PACKAGE + "CustomHttpJudgeModel";
+ };
+ }
+
+ private static JudgeModel instantiate(Class> clazz, String model, String apiKey) {
+ // Try (String modelId, String apiKey)
+ try {
+ Constructor> ctor = clazz.getDeclaredConstructor(String.class, String.class);
+ return (JudgeModel) ctor.newInstance(model, apiKey);
+ } catch (NoSuchMethodException ignored) {
+ // fall through
+ } catch (Exception e) {
+ throw new MetricFactory.MetricInstantiationException(
+ "Failed to instantiate judge: " + e.getMessage(), e);
+ }
+
+ // Try JudgeConfig-based constructor via builder if available
+ try {
+ Class> configClass = Class.forName("com.agenteval.judge.config.JudgeConfig");
+ Object configBuilder = configClass.getMethod("builder").invoke(null);
+ Class> builderClass = configBuilder.getClass();
+ builderClass.getMethod("modelId", String.class).invoke(configBuilder, model);
+ if (apiKey != null) {
+ builderClass.getMethod("apiKey", String.class).invoke(configBuilder, apiKey);
+ }
+ Object judgeConfig = builderClass.getMethod("build").invoke(configBuilder);
+ Constructor> ctor = clazz.getDeclaredConstructor(configClass);
+ return (JudgeModel) ctor.newInstance(judgeConfig);
+ } catch (Exception e) {
+ throw new MetricFactory.MetricInstantiationException(
+ "Failed to instantiate judge model for provider "
+ + clazz.getSimpleName() + ": " + e.getMessage(), e);
+ }
+ }
+}
diff --git a/agenteval-mcp/src/main/java/com/agenteval/mcp/McpSchemaValidator.java b/agenteval-mcp/src/main/java/com/agenteval/mcp/McpSchemaValidator.java
index db664be..a17d9c2 100644
--- a/agenteval-mcp/src/main/java/com/agenteval/mcp/McpSchemaValidator.java
+++ b/agenteval-mcp/src/main/java/com/agenteval/mcp/McpSchemaValidator.java
@@ -94,8 +94,8 @@ private static String jsonType(Object value) {
if (value instanceof Integer || value instanceof Long) return "integer";
if (value instanceof Number) return "number";
if (value instanceof Boolean) return "boolean";
- if (value instanceof List) return "array";
- if (value instanceof Map) return "object";
+ if (value instanceof List>) return "array";
+ if (value instanceof Map, ?>) return "object";
return "unknown";
}
}
diff --git a/agenteval-metrics/src/main/java/com/agenteval/metrics/agent/ToolResultUtilizationMetric.java b/agenteval-metrics/src/main/java/com/agenteval/metrics/agent/ToolResultUtilizationMetric.java
index a943d99..030b314 100644
--- a/agenteval-metrics/src/main/java/com/agenteval/metrics/agent/ToolResultUtilizationMetric.java
+++ b/agenteval-metrics/src/main/java/com/agenteval/metrics/agent/ToolResultUtilizationMetric.java
@@ -21,7 +21,7 @@
public final class ToolResultUtilizationMetric implements EvalMetric {
private static final String NAME = "ToolResultUtilization";
- private static final double DEFAULT_THRESHOLD = 0.6;
+ private static final double DEFAULT_THRESHOLD = 0.7;
private final EmbeddingModel embeddingModel;
private final double threshold;
diff --git a/agenteval-metrics/src/main/java/com/agenteval/metrics/conversation/ConversationResolutionMetric.java b/agenteval-metrics/src/main/java/com/agenteval/metrics/conversation/ConversationResolutionMetric.java
index 5fa83c4..79512f7 100644
--- a/agenteval-metrics/src/main/java/com/agenteval/metrics/conversation/ConversationResolutionMetric.java
+++ b/agenteval-metrics/src/main/java/com/agenteval/metrics/conversation/ConversationResolutionMetric.java
@@ -17,7 +17,7 @@ public final class ConversationResolutionMetric extends LLMConversationMetric {
private static final String NAME = "ConversationResolution";
private static final String PROMPT_PATH =
"com/agenteval/metrics/prompts/conversation-resolution.txt";
- private static final double DEFAULT_THRESHOLD = 0.7;
+ private static final double DEFAULT_THRESHOLD = 0.5;
private final String successCriteria;
diff --git a/agenteval-metrics/src/main/java/com/agenteval/metrics/conversation/LLMConversationMetric.java b/agenteval-metrics/src/main/java/com/agenteval/metrics/conversation/LLMConversationMetric.java
index 6709a2f..47252d8 100644
--- a/agenteval-metrics/src/main/java/com/agenteval/metrics/conversation/LLMConversationMetric.java
+++ b/agenteval-metrics/src/main/java/com/agenteval/metrics/conversation/LLMConversationMetric.java
@@ -20,7 +20,9 @@
* Follows the same template method pattern as {@code LLMJudgeMetric},
* but operates on {@link ConversationTestCase} instead of {@code AgentTestCase}.
*/
-public abstract class LLMConversationMetric implements ConversationMetric {
+public abstract sealed class LLMConversationMetric implements ConversationMetric
+ permits ConversationCoherenceMetric, ContextRetentionMetric,
+ ConversationResolutionMetric {
private static final Logger LOG = LoggerFactory.getLogger(LLMConversationMetric.class);
diff --git a/agenteval-metrics/src/main/java/com/agenteval/metrics/conversation/TopicDriftDetectionMetric.java b/agenteval-metrics/src/main/java/com/agenteval/metrics/conversation/TopicDriftDetectionMetric.java
index bd5a1eb..713e800 100644
--- a/agenteval-metrics/src/main/java/com/agenteval/metrics/conversation/TopicDriftDetectionMetric.java
+++ b/agenteval-metrics/src/main/java/com/agenteval/metrics/conversation/TopicDriftDetectionMetric.java
@@ -19,7 +19,7 @@
public final class TopicDriftDetectionMetric implements ConversationMetric {
private static final String NAME = "TopicDriftDetection";
- private static final double DEFAULT_THRESHOLD = 0.6;
+ private static final double DEFAULT_THRESHOLD = 0.5;
private final EmbeddingModel embeddingModel;
private final double threshold;
diff --git a/agenteval-metrics/src/test/java/com/agenteval/metrics/conversation/ConversationResolutionMetricTest.java b/agenteval-metrics/src/test/java/com/agenteval/metrics/conversation/ConversationResolutionMetricTest.java
index 0944985..1267f2d 100644
--- a/agenteval-metrics/src/test/java/com/agenteval/metrics/conversation/ConversationResolutionMetricTest.java
+++ b/agenteval-metrics/src/test/java/com/agenteval/metrics/conversation/ConversationResolutionMetricTest.java
@@ -107,6 +107,6 @@ void shouldUseDefaultThreshold() {
.build();
EvalScore score = metric.evaluate(testCase);
- assertThat(score.threshold()).isEqualTo(0.7);
+ assertThat(score.threshold()).isEqualTo(0.5);
}
}
diff --git a/build.gradle.kts b/build.gradle.kts
index 1fa7ab8..9209aaf 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -7,6 +7,7 @@ plugins {
subprojects {
apply(plugin = "java-library")
apply(plugin = "checkstyle")
+ apply(plugin = "jacoco")
group = "com.agenteval"
version = "0.1.0-SNAPSHOT"
@@ -52,6 +53,16 @@ subprojects {
}
tasks.withType {
- useJUnitPlatform()
+ useJUnitPlatform {
+ excludeTags("eval")
+ }
+ }
+
+ tasks.named("jacocoTestReport") {
+ dependsOn(tasks.named("test"))
+ reports {
+ xml.required = true
+ html.required = true
+ }
}
}
diff --git a/docs/package-lock.json b/docs/package-lock.json
index 8a219b5..19e4758 100644
--- a/docs/package-lock.json
+++ b/docs/package-lock.json
@@ -8,8 +8,8 @@
"name": "docs",
"version": "0.0.0",
"dependencies": {
- "@docusaurus/core": "3.9.2",
- "@docusaurus/preset-classic": "3.9.2",
+ "@docusaurus/core": "^3.5.2",
+ "@docusaurus/preset-classic": "^3.5.2",
"@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0",
"prism-react-renderer": "^2.3.0",
@@ -27,15 +27,15 @@
}
},
"node_modules/@algolia/abtesting": {
- "version": "1.15.2",
- "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.15.2.tgz",
- "integrity": "sha512-rF7vRVE61E0QORw8e2NNdnttcl3jmFMWS9B4hhdga12COe+lMa26bQLfcBn/Nbp9/AF/8gXdaRCPsVns3CnjsA==",
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.16.0.tgz",
+ "integrity": "sha512-alHFZ68/i9qLC/muEB07VQ9r7cB8AvCcGX6dVQi2PNHhc/ZQRmmFAv8KK1ay4UiseGSFr7f0nXBKsZ/jRg7e4g==",
"license": "MIT",
"dependencies": {
- "@algolia/client-common": "5.49.2",
- "@algolia/requester-browser-xhr": "5.49.2",
- "@algolia/requester-fetch": "5.49.2",
- "@algolia/requester-node-http": "5.49.2"
+ "@algolia/client-common": "5.50.0",
+ "@algolia/requester-browser-xhr": "5.50.0",
+ "@algolia/requester-fetch": "5.50.0",
+ "@algolia/requester-node-http": "5.50.0"
},
"engines": {
"node": ">= 14.0.0"
@@ -74,99 +74,99 @@
}
},
"node_modules/@algolia/client-abtesting": {
- "version": "5.49.2",
- "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.49.2.tgz",
- "integrity": "sha512-XyvKCm0RRmovMI/ChaAVjTwpZhXdbgt3iZofK914HeEHLqD1MUFFVLz7M0+Ou7F56UkHXwRbpHwb9xBDNopprQ==",
+ "version": "5.50.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.50.0.tgz",
+ "integrity": "sha512-mfgUdLQNxOAvCZUGzPQxjahEWEPuQkKlV0ZtGmePOa9ZxIQZlk31vRBNbM6ScU8jTH41SCYE77G/lCifDr1SVw==",
"license": "MIT",
"dependencies": {
- "@algolia/client-common": "5.49.2",
- "@algolia/requester-browser-xhr": "5.49.2",
- "@algolia/requester-fetch": "5.49.2",
- "@algolia/requester-node-http": "5.49.2"
+ "@algolia/client-common": "5.50.0",
+ "@algolia/requester-browser-xhr": "5.50.0",
+ "@algolia/requester-fetch": "5.50.0",
+ "@algolia/requester-node-http": "5.50.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/client-analytics": {
- "version": "5.49.2",
- "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.49.2.tgz",
- "integrity": "sha512-jq/3qvtmj3NijZlhq7A1B0Cl41GfaBpjJxcwukGsYds6aMSCWrEAJ9pUqw/C9B3hAmILYKl7Ljz3N9SFvekD3Q==",
+ "version": "5.50.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.50.0.tgz",
+ "integrity": "sha512-5mjokeKYyPaP3Q8IYJEnutI+O4dW/Ixxx5IgsSxT04pCfGqPXxTOH311hTQxyNpcGGEOGrMv8n8Z+UMTPamioQ==",
"license": "MIT",
"dependencies": {
- "@algolia/client-common": "5.49.2",
- "@algolia/requester-browser-xhr": "5.49.2",
- "@algolia/requester-fetch": "5.49.2",
- "@algolia/requester-node-http": "5.49.2"
+ "@algolia/client-common": "5.50.0",
+ "@algolia/requester-browser-xhr": "5.50.0",
+ "@algolia/requester-fetch": "5.50.0",
+ "@algolia/requester-node-http": "5.50.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/client-common": {
- "version": "5.49.2",
- "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.49.2.tgz",
- "integrity": "sha512-bn0biLequn3epobCfjUqCxlIlurLr4RHu7RaE4trgN+RDcUq6HCVC3/yqq1hwbNYpVtulnTOJzcaxYlSr1fnuw==",
+ "version": "5.50.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.50.0.tgz",
+ "integrity": "sha512-emtOvR6dl3rX3sBJXXbofMNHU1qMQqQSWu319RMrNL5BWoBqyiq7y0Zn6cjJm7aGHV/Qbf+KCCYeWNKEMPI3BQ==",
"license": "MIT",
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/client-insights": {
- "version": "5.49.2",
- "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.49.2.tgz",
- "integrity": "sha512-z14wfFs1T3eeYbCArC8pvntAWsPo9f6hnUGoj8IoRUJTwgJiiySECkm8bmmV47/x0oGHfsVn3kBdjMX0yq0sNA==",
+ "version": "5.50.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.50.0.tgz",
+ "integrity": "sha512-IerGH2/hcj/6bwkpQg/HHRqmlGN1XwygQWythAk0gZFBrghs9danJaYuSS3ShzLSVoIVth4jY5GDPX9Lbw5cgg==",
"license": "MIT",
"dependencies": {
- "@algolia/client-common": "5.49.2",
- "@algolia/requester-browser-xhr": "5.49.2",
- "@algolia/requester-fetch": "5.49.2",
- "@algolia/requester-node-http": "5.49.2"
+ "@algolia/client-common": "5.50.0",
+ "@algolia/requester-browser-xhr": "5.50.0",
+ "@algolia/requester-fetch": "5.50.0",
+ "@algolia/requester-node-http": "5.50.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/client-personalization": {
- "version": "5.49.2",
- "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.49.2.tgz",
- "integrity": "sha512-GpRf7yuuAX93+Qt0JGEJZwgtL0MFdjFO9n7dn8s2pA9mTjzl0Sc5+uTk1VPbIAuf7xhCP9Mve+URGb6J+EYxgA==",
+ "version": "5.50.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.50.0.tgz",
+ "integrity": "sha512-3idPJeXn5L0MmgP9jk9JJqblrQ/SguN93dNK9z9gfgyupBhHnJMOEjrRYcVgTIfvG13Y04wO+Q0FxE2Ut8PVbA==",
"license": "MIT",
"dependencies": {
- "@algolia/client-common": "5.49.2",
- "@algolia/requester-browser-xhr": "5.49.2",
- "@algolia/requester-fetch": "5.49.2",
- "@algolia/requester-node-http": "5.49.2"
+ "@algolia/client-common": "5.50.0",
+ "@algolia/requester-browser-xhr": "5.50.0",
+ "@algolia/requester-fetch": "5.50.0",
+ "@algolia/requester-node-http": "5.50.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/client-query-suggestions": {
- "version": "5.49.2",
- "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.49.2.tgz",
- "integrity": "sha512-HZwApmNkp0DiAjZcLYdQLddcG4Agb88OkojiAHGgcm5DVXobT5uSZ9lmyrbw/tmQBJwgu2CNw4zTyXoIB7YbPA==",
+ "version": "5.50.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.50.0.tgz",
+ "integrity": "sha512-q7qRoWrQK1a8m5EFQEmPlo7+pg9mVQ8X5jsChtChERre0uS2pdYEDixBBl0ydBSGkdGbLUDufcACIhH/077E4g==",
"license": "MIT",
"dependencies": {
- "@algolia/client-common": "5.49.2",
- "@algolia/requester-browser-xhr": "5.49.2",
- "@algolia/requester-fetch": "5.49.2",
- "@algolia/requester-node-http": "5.49.2"
+ "@algolia/client-common": "5.50.0",
+ "@algolia/requester-browser-xhr": "5.50.0",
+ "@algolia/requester-fetch": "5.50.0",
+ "@algolia/requester-node-http": "5.50.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/client-search": {
- "version": "5.49.2",
- "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.49.2.tgz",
- "integrity": "sha512-y1IOpG6OSmTpGg/CT0YBb/EAhR2nsC18QWp9Jy8HO9iGySpcwaTvs5kHa17daP3BMTwWyaX9/1tDTDQshZzXdg==",
+ "version": "5.50.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.50.0.tgz",
+ "integrity": "sha512-Jc360x4yqb3eEg4OY4KEIdGePBxZogivKI+OGIU8aLXgAYPTECvzeOBc90312yHA1hr3AeRlAFl0rIc8lQaIrQ==",
"license": "MIT",
"dependencies": {
- "@algolia/client-common": "5.49.2",
- "@algolia/requester-browser-xhr": "5.49.2",
- "@algolia/requester-fetch": "5.49.2",
- "@algolia/requester-node-http": "5.49.2"
+ "@algolia/client-common": "5.50.0",
+ "@algolia/requester-browser-xhr": "5.50.0",
+ "@algolia/requester-fetch": "5.50.0",
+ "@algolia/requester-node-http": "5.50.0"
},
"engines": {
"node": ">= 14.0.0"
@@ -179,81 +179,81 @@
"license": "MIT"
},
"node_modules/@algolia/ingestion": {
- "version": "1.49.2",
- "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.49.2.tgz",
- "integrity": "sha512-YYJRjaZ2bqk923HxE4um7j/Cm3/xoSkF2HC2ZweOF8cXL3sqnlndSUYmCaxHFjNPWLaSHk2IfssX6J/tdKTULw==",
+ "version": "1.50.0",
+ "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.50.0.tgz",
+ "integrity": "sha512-OS3/Viao+NPpyBbEY3tf6hLewppG+UclD+9i0ju56mq2DrdMJFCkEky6Sk9S5VPcbLzxzg3BqBX6u9Q35w19aQ==",
"license": "MIT",
"dependencies": {
- "@algolia/client-common": "5.49.2",
- "@algolia/requester-browser-xhr": "5.49.2",
- "@algolia/requester-fetch": "5.49.2",
- "@algolia/requester-node-http": "5.49.2"
+ "@algolia/client-common": "5.50.0",
+ "@algolia/requester-browser-xhr": "5.50.0",
+ "@algolia/requester-fetch": "5.50.0",
+ "@algolia/requester-node-http": "5.50.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/monitoring": {
- "version": "1.49.2",
- "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.49.2.tgz",
- "integrity": "sha512-9WgH+Dha39EQQyGKCHlGYnxW/7W19DIrEbCEbnzwAMpGAv1yTWCHMPXHxYa+LcL3eCp2V/5idD1zHNlIKmHRHg==",
+ "version": "1.50.0",
+ "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.50.0.tgz",
+ "integrity": "sha512-/znwgSiGufpbJVIoDmeQaHtTq+OMdDawFRbMSJVv+12n79hW+qdQXS8/Uu3BD3yn0BzgVFJEvrsHrCsInZKdhw==",
"license": "MIT",
"dependencies": {
- "@algolia/client-common": "5.49.2",
- "@algolia/requester-browser-xhr": "5.49.2",
- "@algolia/requester-fetch": "5.49.2",
- "@algolia/requester-node-http": "5.49.2"
+ "@algolia/client-common": "5.50.0",
+ "@algolia/requester-browser-xhr": "5.50.0",
+ "@algolia/requester-fetch": "5.50.0",
+ "@algolia/requester-node-http": "5.50.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/recommend": {
- "version": "5.49.2",
- "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.49.2.tgz",
- "integrity": "sha512-K7Gp5u+JtVYgaVpBxF5rGiM+Ia8SsMdcAJMTDV93rwh00DKNllC19o1g+PwrDjDvyXNrnTEbofzbTs2GLfFyKA==",
+ "version": "5.50.0",
+ "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.50.0.tgz",
+ "integrity": "sha512-dHjUfu4jfjdQiKDpCpAnM7LP5yfG0oNShtfpF5rMCel6/4HIoqJ4DC4h5GKDzgrvJYtgAhblo0AYBmOM00T+lQ==",
"license": "MIT",
"dependencies": {
- "@algolia/client-common": "5.49.2",
- "@algolia/requester-browser-xhr": "5.49.2",
- "@algolia/requester-fetch": "5.49.2",
- "@algolia/requester-node-http": "5.49.2"
+ "@algolia/client-common": "5.50.0",
+ "@algolia/requester-browser-xhr": "5.50.0",
+ "@algolia/requester-fetch": "5.50.0",
+ "@algolia/requester-node-http": "5.50.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/requester-browser-xhr": {
- "version": "5.49.2",
- "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.49.2.tgz",
- "integrity": "sha512-3UhYCcWX6fbtN8ABcxZlhaQEwXFh3CsFtARyyadQShHMPe3mJV9Wel4FpJTa+seugRkbezFz0tt6aPTZSYTBuA==",
+ "version": "5.50.0",
+ "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.50.0.tgz",
+ "integrity": "sha512-bffIbUljAWnh/Ctu5uScORajuUavqmZ0ACYd1fQQeSSYA9NNN83ynO26pSc2dZRXpSK0fkc1//qSSFXMKGu+aw==",
"license": "MIT",
"dependencies": {
- "@algolia/client-common": "5.49.2"
+ "@algolia/client-common": "5.50.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/requester-fetch": {
- "version": "5.49.2",
- "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.49.2.tgz",
- "integrity": "sha512-G94VKSGbsr+WjsDDOBe5QDQ82QYgxvpxRGJfCHZBnYKYsy/jv9qGIDb93biza+LJWizQBUtDj7bZzp3QZyzhPQ==",
+ "version": "5.50.0",
+ "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.50.0.tgz",
+ "integrity": "sha512-y0EwNvPGvkM+yTAqqO6Gpt9wVGm3CLDtpLvNEiB3VGvN3WzfkjZGtLUsG/ru2kVJIIU7QcV0puuYgEpBeFxcJg==",
"license": "MIT",
"dependencies": {
- "@algolia/client-common": "5.49.2"
+ "@algolia/client-common": "5.50.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/requester-node-http": {
- "version": "5.49.2",
- "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.49.2.tgz",
- "integrity": "sha512-UuihBGHafG/ENsrcTGAn5rsOffrCIRuHMOsD85fZGLEY92ate+BMTUqxz60dv5zerh8ZumN4bRm8eW2z9L11jA==",
+ "version": "5.50.0",
+ "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.50.0.tgz",
+ "integrity": "sha512-xpwefe4fCOWnZgXCbkGpqQY6jgBSCf2hmgnySbyzZIccrv3SoashHKGPE4x6vVG+gdHrGciMTAcDo9HOZwH22Q==",
"license": "MIT",
"dependencies": {
- "@algolia/client-common": "5.49.2"
+ "@algolia/client-common": "5.50.0"
},
"engines": {
"node": ">= 14.0.0"
@@ -431,9 +431,9 @@
}
},
"node_modules/@babel/helper-define-polyfill-provider": {
- "version": "0.6.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.7.tgz",
- "integrity": "sha512-6Fqi8MtQ/PweQ9xvux65emkLQ83uB+qAVtfHkC9UodyHMIZdxNI01HjLCLUtybElp2KY2XNE0nOgyP1E1vXw9w==",
+ "version": "0.6.8",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz",
+ "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==",
"license": "MIT",
"dependencies": {
"@babel/helper-compilation-targets": "^7.28.6",
@@ -608,22 +608,22 @@
}
},
"node_modules/@babel/helpers": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz",
- "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==",
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz",
+ "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==",
"license": "MIT",
"dependencies": {
"@babel/template": "^7.28.6",
- "@babel/types": "^7.28.6"
+ "@babel/types": "^7.29.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz",
- "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==",
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz",
+ "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==",
"license": "MIT",
"dependencies": {
"@babel/types": "^7.29.0"
@@ -1748,9 +1748,9 @@
}
},
"node_modules/@babel/preset-env": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.0.tgz",
- "integrity": "sha512-fNEdfc0yi16lt6IZo2Qxk3knHVdfMYX33czNb4v8yWhemoBhibCpQK/uYHtSKIiO+p/zd3+8fYVXhQdOVV608w==",
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.2.tgz",
+ "integrity": "sha512-DYD23veRYGvBFhcTY1iUvJnDNpuqNd/BzBwCvzOTKUnJjKg5kpUBh3/u9585Agdkgj+QuygG7jLfOPWMa2KVNw==",
"license": "MIT",
"dependencies": {
"@babel/compat-data": "^7.29.0",
@@ -1832,12 +1832,12 @@
}
},
"node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs3": {
- "version": "0.14.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.1.tgz",
- "integrity": "sha512-ENp89vM9Pw4kv/koBb5N2f9bDZsR0hpf3BdPMOg/pkS3pwO4dzNnQZVXtBbeyAadgm865DmQG2jMMLqmZXvuCw==",
+ "version": "0.14.2",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz",
+ "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==",
"license": "MIT",
"dependencies": {
- "@babel/helper-define-polyfill-provider": "^0.6.7",
+ "@babel/helper-define-polyfill-provider": "^0.6.8",
"core-js-compat": "^3.48.0"
},
"peerDependencies": {
@@ -1907,18 +1907,18 @@
}
},
"node_modules/@babel/runtime": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz",
- "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==",
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz",
+ "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/runtime-corejs3": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.29.0.tgz",
- "integrity": "sha512-TgUkdp71C9pIbBcHudc+gXZnihEDOjUAmXO1VO4HHGES7QLZcShR0stfKIxLSNIYx2fqhmJChOjm/wkF8wv4gA==",
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.29.2.tgz",
+ "integrity": "sha512-Lc94FOD5+0aXhdb0Tdg3RUtqT6yWbI/BbFWvlaSJ3gAb9Ks+99nHRDKADVqC37er4eCB0fHyWT+y+K3QOvJKbw==",
"license": "MIT",
"dependencies": {
"core-js-pure": "^3.48.0"
@@ -3308,9 +3308,9 @@
}
},
"node_modules/@docsearch/core": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/@docsearch/core/-/core-4.6.0.tgz",
- "integrity": "sha512-IqG3oSd529jVRQ4dWZQKwZwQLVd//bWJTz2HiL0LkiHrI4U/vLrBasKB7lwQB/69nBAcCgs3TmudxTZSLH/ZQg==",
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/@docsearch/core/-/core-4.6.2.tgz",
+ "integrity": "sha512-/S0e6Dj7Zcm8m9Rru49YEX49dhU11be68c+S/BCyN8zQsTTgkKzXlhRbVL5mV6lOLC2+ZRRryaTdcm070Ug2oA==",
"license": "MIT",
"peerDependencies": {
"@types/react": ">= 16.8.0 < 20.0.0",
@@ -3330,20 +3330,20 @@
}
},
"node_modules/@docsearch/css": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-4.6.0.tgz",
- "integrity": "sha512-YlcAimkXclvqta47g47efzCM5CFxDwv2ClkDfEs/fC/Ak0OxPH2b3czwa4o8O1TRBf+ujFF2RiUwszz2fPVNJQ==",
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-4.6.2.tgz",
+ "integrity": "sha512-fH/cn8BjEEdM2nJdjNMHIvOVYupG6AIDtFVDgIZrNzdCSj4KXr9kd+hsehqsNGYjpUjObeKYKvgy/IwCb1jZYQ==",
"license": "MIT"
},
"node_modules/@docsearch/react": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-4.6.0.tgz",
- "integrity": "sha512-j8H5B4ArGxBPBWvw3X0J0Rm/Pjv2JDa2rV5OE0DLTp5oiBCptIJ/YlNOhZxuzbO2nwge+o3Z52nJRi3hryK9cA==",
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-4.6.2.tgz",
+ "integrity": "sha512-/BbtGFtqVOGwZx0dw/UfhN/0/DmMQYnulY4iv0tPRhC2JCXv0ka/+izwt3Jzo1ZxXS/2eMvv9zHsBJOK1I9f/w==",
"license": "MIT",
"dependencies": {
"@algolia/autocomplete-core": "1.19.2",
- "@docsearch/core": "4.6.0",
- "@docsearch/css": "4.6.0"
+ "@docsearch/core": "4.6.2",
+ "@docsearch/css": "4.6.2"
},
"peerDependencies": {
"@types/react": ">= 16.8.0 < 20.0.0",
@@ -4211,13 +4211,13 @@
}
},
"node_modules/@jsonjoy.com/fs-core": {
- "version": "4.56.11",
- "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.56.11.tgz",
- "integrity": "sha512-wThHjzUp01ImIjfCwhs+UnFkeGPFAymwLEkOtenHewaKe2pTP12p6r1UuwikA9NEvNf9Vlck92r8fb8n/MWM5w==",
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.57.1.tgz",
+ "integrity": "sha512-YrEi/ZPmgc+GfdO0esBF04qv8boK9Dg9WpRQw/+vM8Qt3nnVIJWIa8HwZ/LXVZ0DB11XUROM8El/7yYTJX+WtA==",
"license": "Apache-2.0",
"dependencies": {
- "@jsonjoy.com/fs-node-builtins": "4.56.11",
- "@jsonjoy.com/fs-node-utils": "4.56.11",
+ "@jsonjoy.com/fs-node-builtins": "4.57.1",
+ "@jsonjoy.com/fs-node-utils": "4.57.1",
"thingies": "^2.5.0"
},
"engines": {
@@ -4232,14 +4232,14 @@
}
},
"node_modules/@jsonjoy.com/fs-fsa": {
- "version": "4.56.11",
- "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.56.11.tgz",
- "integrity": "sha512-ZYlF3XbMayyp97xEN8ZvYutU99PCHjM64mMZvnCseXkCJXJDVLAwlF8Q/7q/xiWQRsv3pQBj1WXHd9eEyYcaCQ==",
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.57.1.tgz",
+ "integrity": "sha512-ooEPvSW/HQDivPDPZMibHGKZf/QS4WRir1czGZmXmp3MsQqLECZEpN0JobrD8iV9BzsuwdIv+PxtWX9WpPLsIA==",
"license": "Apache-2.0",
"dependencies": {
- "@jsonjoy.com/fs-core": "4.56.11",
- "@jsonjoy.com/fs-node-builtins": "4.56.11",
- "@jsonjoy.com/fs-node-utils": "4.56.11",
+ "@jsonjoy.com/fs-core": "4.57.1",
+ "@jsonjoy.com/fs-node-builtins": "4.57.1",
+ "@jsonjoy.com/fs-node-utils": "4.57.1",
"thingies": "^2.5.0"
},
"engines": {
@@ -4254,16 +4254,16 @@
}
},
"node_modules/@jsonjoy.com/fs-node": {
- "version": "4.56.11",
- "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.56.11.tgz",
- "integrity": "sha512-D65YrnP6wRuZyEWoSFnBJSr5zARVpVBGctnhie4rCsMuGXNzX7IHKaOt85/Aj7SSoG1N2+/xlNjWmkLvZ2H3Tg==",
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.57.1.tgz",
+ "integrity": "sha512-3YaKhP8gXEKN+2O49GLNfNb5l2gbnCFHyAaybbA2JkkbQP3dpdef7WcUaHAulg/c5Dg4VncHsA3NWAUSZMR5KQ==",
"license": "Apache-2.0",
"dependencies": {
- "@jsonjoy.com/fs-core": "4.56.11",
- "@jsonjoy.com/fs-node-builtins": "4.56.11",
- "@jsonjoy.com/fs-node-utils": "4.56.11",
- "@jsonjoy.com/fs-print": "4.56.11",
- "@jsonjoy.com/fs-snapshot": "4.56.11",
+ "@jsonjoy.com/fs-core": "4.57.1",
+ "@jsonjoy.com/fs-node-builtins": "4.57.1",
+ "@jsonjoy.com/fs-node-utils": "4.57.1",
+ "@jsonjoy.com/fs-print": "4.57.1",
+ "@jsonjoy.com/fs-snapshot": "4.57.1",
"glob-to-regex.js": "^1.0.0",
"thingies": "^2.5.0"
},
@@ -4279,9 +4279,9 @@
}
},
"node_modules/@jsonjoy.com/fs-node-builtins": {
- "version": "4.56.11",
- "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.56.11.tgz",
- "integrity": "sha512-CNmt3a0zMCIhniFLXtzPWuUxXFU+U+2VyQiIrgt/rRVeEJNrMQUABaRbVxR0Ouw1LyR9RjaEkPM6nYpED+y43A==",
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.57.1.tgz",
+ "integrity": "sha512-XHkFKQ5GSH3uxm8c3ZYXVrexGdscpWKIcMWKFQpMpMJc8gA3AwOMBJXJlgpdJqmrhPyQXxaY9nbkNeYpacC0Og==",
"license": "Apache-2.0",
"engines": {
"node": ">=10.0"
@@ -4295,14 +4295,14 @@
}
},
"node_modules/@jsonjoy.com/fs-node-to-fsa": {
- "version": "4.56.11",
- "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.56.11.tgz",
- "integrity": "sha512-5OzGdvJDgZVo+xXWEYo72u81zpOWlxlbG4d4nL+hSiW+LKlua/dldNgPrpWxtvhgyntmdFQad2UTxFyGjJAGhA==",
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.57.1.tgz",
+ "integrity": "sha512-pqGHyWWzNck4jRfaGV39hkqpY5QjRUQ/nRbNT7FYbBa0xf4bDG+TE1Gt2KWZrSkrkZZDE3qZUjYMbjwSliX6pg==",
"license": "Apache-2.0",
"dependencies": {
- "@jsonjoy.com/fs-fsa": "4.56.11",
- "@jsonjoy.com/fs-node-builtins": "4.56.11",
- "@jsonjoy.com/fs-node-utils": "4.56.11"
+ "@jsonjoy.com/fs-fsa": "4.57.1",
+ "@jsonjoy.com/fs-node-builtins": "4.57.1",
+ "@jsonjoy.com/fs-node-utils": "4.57.1"
},
"engines": {
"node": ">=10.0"
@@ -4316,12 +4316,12 @@
}
},
"node_modules/@jsonjoy.com/fs-node-utils": {
- "version": "4.56.11",
- "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.56.11.tgz",
- "integrity": "sha512-JADOZFDA3wRfsuxkT0+MYc4F9hJO2PYDaY66kRTG6NqGX3+bqmKu66YFYAbII/tEmQWPZeHoClUB23rtQM9UPg==",
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.57.1.tgz",
+ "integrity": "sha512-vp+7ZzIB8v43G+GLXTS4oDUSQmhAsRz532QmmWBbdYA20s465JvwhkSFvX9cVTqRRAQg+vZ7zWDaIEh0lFe2gw==",
"license": "Apache-2.0",
"dependencies": {
- "@jsonjoy.com/fs-node-builtins": "4.56.11"
+ "@jsonjoy.com/fs-node-builtins": "4.57.1"
},
"engines": {
"node": ">=10.0"
@@ -4335,12 +4335,12 @@
}
},
"node_modules/@jsonjoy.com/fs-print": {
- "version": "4.56.11",
- "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.56.11.tgz",
- "integrity": "sha512-rnaKRgCRIn8JGTjxhS0JPE38YM3Pj/H7SW4/tglhIPbfKEkky7dpPayNKV2qy25SZSL15oFVgH/62dMZ/z7cyA==",
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.57.1.tgz",
+ "integrity": "sha512-Ynct7ZJmfk6qoXDOKfpovNA36ITUx8rChLmRQtW08J73VOiuNsU8PB6d/Xs7fxJC2ohWR3a5AqyjmLojfrw5yw==",
"license": "Apache-2.0",
"dependencies": {
- "@jsonjoy.com/fs-node-utils": "4.56.11",
+ "@jsonjoy.com/fs-node-utils": "4.57.1",
"tree-dump": "^1.1.0"
},
"engines": {
@@ -4355,13 +4355,13 @@
}
},
"node_modules/@jsonjoy.com/fs-snapshot": {
- "version": "4.56.11",
- "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.56.11.tgz",
- "integrity": "sha512-IIldPX+cIRQuUol9fQzSS3hqyECxVpYMJQMqdU3dCKZFRzEl1rkIkw4P6y7Oh493sI7YdxZlKr/yWdzEWZ1wGQ==",
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.57.1.tgz",
+ "integrity": "sha512-/oG8xBNFMbDXTq9J7vepSA1kerS5vpgd3p5QZSPd+nX59uwodGJftI51gDYyHRpP57P3WCQf7LHtBYPqwUg2Bg==",
"license": "Apache-2.0",
"dependencies": {
"@jsonjoy.com/buffers": "^17.65.0",
- "@jsonjoy.com/fs-node-utils": "4.56.11",
+ "@jsonjoy.com/fs-node-utils": "4.57.1",
"@jsonjoy.com/json-pack": "^17.65.0",
"@jsonjoy.com/util": "^17.65.0"
},
@@ -5231,9 +5231,9 @@
}
},
"node_modules/@types/debug": {
- "version": "4.1.12",
- "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
- "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==",
+ "version": "4.1.13",
+ "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz",
+ "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==",
"license": "MIT",
"dependencies": {
"@types/ms": "*"
@@ -5884,34 +5884,34 @@
}
},
"node_modules/algoliasearch": {
- "version": "5.49.2",
- "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.49.2.tgz",
- "integrity": "sha512-1K0wtDaRONwfhL4h8bbJ9qTjmY6rhGgRvvagXkMBsAOMNr+3Q2SffHECh9DIuNVrMA1JwA0zCwhyepgBZVakng==",
- "license": "MIT",
- "dependencies": {
- "@algolia/abtesting": "1.15.2",
- "@algolia/client-abtesting": "5.49.2",
- "@algolia/client-analytics": "5.49.2",
- "@algolia/client-common": "5.49.2",
- "@algolia/client-insights": "5.49.2",
- "@algolia/client-personalization": "5.49.2",
- "@algolia/client-query-suggestions": "5.49.2",
- "@algolia/client-search": "5.49.2",
- "@algolia/ingestion": "1.49.2",
- "@algolia/monitoring": "1.49.2",
- "@algolia/recommend": "5.49.2",
- "@algolia/requester-browser-xhr": "5.49.2",
- "@algolia/requester-fetch": "5.49.2",
- "@algolia/requester-node-http": "5.49.2"
+ "version": "5.50.0",
+ "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.50.0.tgz",
+ "integrity": "sha512-yE5I83Q2s8euVou8Y3feXK08wyZInJWLYXgWO6Xti9jBUEZAGUahyeQ7wSZWkifLWVnQVKEz5RAmBlXG5nqxog==",
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/abtesting": "1.16.0",
+ "@algolia/client-abtesting": "5.50.0",
+ "@algolia/client-analytics": "5.50.0",
+ "@algolia/client-common": "5.50.0",
+ "@algolia/client-insights": "5.50.0",
+ "@algolia/client-personalization": "5.50.0",
+ "@algolia/client-query-suggestions": "5.50.0",
+ "@algolia/client-search": "5.50.0",
+ "@algolia/ingestion": "1.50.0",
+ "@algolia/monitoring": "1.50.0",
+ "@algolia/recommend": "5.50.0",
+ "@algolia/requester-browser-xhr": "5.50.0",
+ "@algolia/requester-fetch": "5.50.0",
+ "@algolia/requester-node-http": "5.50.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/algoliasearch-helper": {
- "version": "3.28.0",
- "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.28.0.tgz",
- "integrity": "sha512-GBN0xsxGggaCPElZq24QzMdfphrjIiV2xA+hRXE4/UMpN3nsF2WrM8q+x80OGvGpJWtB7F+4Hq5eSfWwuejXrg==",
+ "version": "3.28.1",
+ "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.28.1.tgz",
+ "integrity": "sha512-6iXpbkkrAI5HFpCWXlNmIDSBuoN/U1XnEvb2yJAoWfqrZ+DrybI7MQ5P5mthFaprmocq+zbi6HxnR28xnZAYBw==",
"license": "MIT",
"dependencies": {
"@algolia/events": "^4.0.1"
@@ -6138,13 +6138,13 @@
}
},
"node_modules/babel-plugin-polyfill-corejs2": {
- "version": "0.4.16",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.16.tgz",
- "integrity": "sha512-xaVwwSfebXf0ooE11BJovZYKhFjIvQo7TsyVpETuIeH2JHv0k/T6Y5j22pPTvqYqmpkxdlPAJlyJ0tfOJAoMxw==",
+ "version": "0.4.17",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz",
+ "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==",
"license": "MIT",
"dependencies": {
"@babel/compat-data": "^7.28.6",
- "@babel/helper-define-polyfill-provider": "^0.6.7",
+ "@babel/helper-define-polyfill-provider": "^0.6.8",
"semver": "^6.3.1"
},
"peerDependencies": {
@@ -6174,12 +6174,12 @@
}
},
"node_modules/babel-plugin-polyfill-regenerator": {
- "version": "0.6.7",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.7.tgz",
- "integrity": "sha512-OTYbUlSwXhNgr4g6efMZgsO8//jA61P7ZbRX3iTT53VON8l+WQS8IAUEVo4a4cWknrg2W8Cj4gQhRYNCJ8GkAA==",
+ "version": "0.6.8",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz",
+ "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==",
"license": "MIT",
"dependencies": {
- "@babel/helper-define-polyfill-provider": "^0.6.7"
+ "@babel/helper-define-polyfill-provider": "^0.6.8"
},
"peerDependencies": {
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
@@ -6196,15 +6196,18 @@
}
},
"node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "license": "MIT"
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
+ "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+ "license": "MIT",
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
},
"node_modules/baseline-browser-mapping": {
- "version": "2.10.7",
- "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.7.tgz",
- "integrity": "sha512-1ghYO3HnxGec0TCGBXiDLVns4eCSx4zJpxnHrlqFQajmhfKMQBzUGDdkMK7fUW7PTHTeLf+j87aTuKuuwWzMGw==",
+ "version": "2.10.12",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.12.tgz",
+ "integrity": "sha512-qyq26DxfY4awP2gIRXhhLWfwzwI+N5Nxk6iQi8EFizIaWIjqicQTE4sLnZZVdeKPRcVNoJOkkpfzoIYuvCKaIQ==",
"license": "Apache-2.0",
"bin": {
"baseline-browser-mapping": "dist/cli.cjs"
@@ -6327,13 +6330,15 @@
}
},
"node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
+ "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
"license": "MIT",
"dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
}
},
"node_modules/braces": {
@@ -6538,9 +6543,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001778",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001778.tgz",
- "integrity": "sha512-PN7uxFL+ExFJO61aVmP1aIEG4i9whQd4eoSCebav62UwDyp5OHh06zN4jqKSMePVgxHifCw1QJxdRkA1Pisekg==",
+ "version": "1.0.30001781",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001781.tgz",
+ "integrity": "sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw==",
"funding": [
{
"type": "opencollective",
@@ -6955,12 +6960,6 @@
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
},
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "license": "MIT"
- },
"node_modules/config-chain": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
@@ -7121,9 +7120,9 @@
}
},
"node_modules/core-js": {
- "version": "3.48.0",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.48.0.tgz",
- "integrity": "sha512-zpEHTy1fjTMZCKLHUZoVeylt9XrzaIN2rbPXEt0k+q7JE5CkCZdo6bNq55bn24a69CH7ErAVLKijxJja4fw+UQ==",
+ "version": "3.49.0",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.49.0.tgz",
+ "integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==",
"hasInstallScript": true,
"license": "MIT",
"funding": {
@@ -7132,9 +7131,9 @@
}
},
"node_modules/core-js-compat": {
- "version": "3.48.0",
- "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.48.0.tgz",
- "integrity": "sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==",
+ "version": "3.49.0",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.49.0.tgz",
+ "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==",
"license": "MIT",
"dependencies": {
"browserslist": "^4.28.1"
@@ -7145,9 +7144,9 @@
}
},
"node_modules/core-js-pure": {
- "version": "3.48.0",
- "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.48.0.tgz",
- "integrity": "sha512-1slJgk89tWC51HQ1AEqG+s2VuwpTRr8ocu4n20QUcH1v9lAN0RXen0Q0AABa/DK1I7RrNWLucplOHMx8hfTGTw==",
+ "version": "3.49.0",
+ "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.49.0.tgz",
+ "integrity": "sha512-XM4RFka59xATyJv/cS3O3Kml72hQXUeGRuuTmMYFxwzc9/7C8OYTaIR/Ji+Yt8DXzsFLNhat15cE/JP15HrCgw==",
"hasInstallScript": true,
"license": "MIT",
"funding": {
@@ -8026,9 +8025,9 @@
"license": "MIT"
},
"node_modules/electron-to-chromium": {
- "version": "1.5.313",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.313.tgz",
- "integrity": "sha512-QBMrTWEf00GXZmJyx2lbYD45jpI3TUFnNIzJ5BBc8piGUDwMPa1GV6HJWTZVvY/eiN3fSopl7NRbgGp9sZ9LTA==",
+ "version": "1.5.328",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.328.tgz",
+ "integrity": "sha512-QNQ5l45DzYytThO21403XN3FvK0hOkWDG8viNf6jqS42msJ8I4tGDSpBCgvDRRPnkffafiwAym2X2eHeGD2V0w==",
"license": "ISC"
},
"node_modules/emoji-regex": {
@@ -8072,9 +8071,9 @@
}
},
"node_modules/enhanced-resolve": {
- "version": "5.20.0",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz",
- "integrity": "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==",
+ "version": "5.20.1",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.1.tgz",
+ "integrity": "sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==",
"license": "MIT",
"dependencies": {
"graceful-fs": "^4.2.4",
@@ -8524,12 +8523,6 @@
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
},
- "node_modules/express/node_modules/path-to-regexp": {
- "version": "0.1.12",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
- "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
- "license": "MIT"
- },
"node_modules/express/node_modules/range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
@@ -9446,12 +9439,6 @@
"wbuf": "^1.1.0"
}
},
- "node_modules/hpack.js/node_modules/isarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
- "license": "MIT"
- },
"node_modules/hpack.js/node_modules/readable-stream": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
@@ -10192,9 +10179,9 @@
}
},
"node_modules/isarray": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
- "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==",
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
"license": "MIT"
},
"node_modules/isexe": {
@@ -10396,9 +10383,9 @@
}
},
"node_modules/launch-editor": {
- "version": "2.13.1",
- "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.13.1.tgz",
- "integrity": "sha512-lPSddlAAluRKJ7/cjRFoXUFzaX7q/YKI7yPHuEvSJVqoXvFnJov1/Ud87Aa4zULIbA9Nja4mSPK8l0z/7eV2wA==",
+ "version": "2.13.2",
+ "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.13.2.tgz",
+ "integrity": "sha512-4VVDnbOpLXy/s8rdRCSXb+zfMeFR0WlJWpET1iA9CQdlZDfwyLjUuGQzXU4VeOoey6AicSAluWan7Etga6Kcmg==",
"license": "MIT",
"dependencies": {
"picocolors": "^1.1.1",
@@ -10999,19 +10986,19 @@
}
},
"node_modules/memfs": {
- "version": "4.56.11",
- "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.56.11.tgz",
- "integrity": "sha512-/GodtwVeKVIHZKLUSr2ZdOxKBC5hHki4JNCU22DoCGPEHr5o2PD5U721zvESKyWwCfTfavFl9WZYgA13OAYK0g==",
+ "version": "4.57.1",
+ "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.57.1.tgz",
+ "integrity": "sha512-WvzrWPwMQT+PtbX2Et64R4qXKK0fj/8pO85MrUCzymX3twwCiJCdvntW3HdhG1teLJcHDDLIKx5+c3HckWYZtQ==",
"license": "Apache-2.0",
"dependencies": {
- "@jsonjoy.com/fs-core": "4.56.11",
- "@jsonjoy.com/fs-fsa": "4.56.11",
- "@jsonjoy.com/fs-node": "4.56.11",
- "@jsonjoy.com/fs-node-builtins": "4.56.11",
- "@jsonjoy.com/fs-node-to-fsa": "4.56.11",
- "@jsonjoy.com/fs-node-utils": "4.56.11",
- "@jsonjoy.com/fs-print": "4.56.11",
- "@jsonjoy.com/fs-snapshot": "4.56.11",
+ "@jsonjoy.com/fs-core": "4.57.1",
+ "@jsonjoy.com/fs-fsa": "4.57.1",
+ "@jsonjoy.com/fs-node": "4.57.1",
+ "@jsonjoy.com/fs-node-builtins": "4.57.1",
+ "@jsonjoy.com/fs-node-to-fsa": "4.57.1",
+ "@jsonjoy.com/fs-node-utils": "4.57.1",
+ "@jsonjoy.com/fs-print": "4.57.1",
+ "@jsonjoy.com/fs-snapshot": "4.57.1",
"@jsonjoy.com/json-pack": "^1.11.0",
"@jsonjoy.com/util": "^1.9.0",
"glob-to-regex.js": "^1.0.1",
@@ -12912,9 +12899,9 @@
}
},
"node_modules/mini-css-extract-plugin": {
- "version": "2.10.1",
- "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.10.1.tgz",
- "integrity": "sha512-k7G3Y5QOegl380tXmZ68foBRRjE9Ljavx835ObdvmZjQ639izvZD8CS7BkWw1qKPPzHsGL/JDhl0uyU1zc2rJw==",
+ "version": "2.10.2",
+ "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.10.2.tgz",
+ "integrity": "sha512-AOSS0IdEB95ayVkxn5oGzNQwqAi2J0Jb/kKm43t7H73s8+f5873g0yuj0PNvK4dO75mu5DHg4nlgp4k6Kga8eg==",
"license": "MIT",
"dependencies": {
"schema-utils": "^4.0.0",
@@ -13572,12 +13559,13 @@
"license": "MIT"
},
"node_modules/path-to-regexp": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz",
- "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==",
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.0.tgz",
+ "integrity": "sha512-PuseHIvAnz3bjrM2rGJtSgo1zjgxapTLZ7x2pjhzWwlp4SJQgK3f3iZIQwkpEnBaKz6seKBADpM4B4ySkuYypg==",
"license": "MIT",
- "dependencies": {
- "isarray": "0.0.1"
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
}
},
"node_modules/path-type": {
@@ -13596,12 +13584,12 @@
"license": "ISC"
},
"node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"license": "MIT",
"engines": {
- "node": ">=8.6"
+ "node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
@@ -13623,9 +13611,9 @@
}
},
"node_modules/pkijs": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/pkijs/-/pkijs-3.3.3.tgz",
- "integrity": "sha512-+KD8hJtqQMYoTuL1bbGOqxb4z+nZkTAwVdNtWwe8Tc2xNbEmdJYIYoc6Qt0uF55e6YW6KuTHw1DjQ18gMhzepw==",
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/pkijs/-/pkijs-3.4.0.tgz",
+ "integrity": "sha512-emEcLuomt2j03vxD54giVB4SxTjnsqkU692xZOZXHDVoYyypEm+b3jpiTcc+Cf+myooc+/Ly0z01jqeNHVgJGw==",
"license": "BSD-3-Clause",
"dependencies": {
"@noble/hashes": "1.4.0",
@@ -15300,15 +15288,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/randombytes": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
- "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "^5.1.0"
- }
- },
"node_modules/range-parser": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
@@ -15449,9 +15428,9 @@
}
},
"node_modules/react-loadable-ssr-addon-v5-slorber": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz",
- "integrity": "sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.3.tgz",
+ "integrity": "sha512-GXfh9VLwB5ERaCsU6RULh7tkemeX15aNh6wuMEBtfdyMa7fFG8TXrhXlx1SoEK2Ty/l6XIkzzYIQmyaWW3JgdQ==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.10.3"
@@ -16148,9 +16127,9 @@
"license": "MIT"
},
"node_modules/sax": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/sax/-/sax-1.5.0.tgz",
- "integrity": "sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz",
+ "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==",
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=11.0.0"
@@ -16302,12 +16281,12 @@
}
},
"node_modules/serialize-javascript": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
- "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.0.5.tgz",
+ "integrity": "sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==",
"license": "BSD-3-Clause",
- "dependencies": {
- "randombytes": "^2.1.0"
+ "engines": {
+ "node": ">=20.0.0"
}
},
"node_modules/serve-handler": {
@@ -16325,12 +16304,6 @@
"range-parser": "1.2.0"
}
},
- "node_modules/serve-handler/node_modules/path-to-regexp": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz",
- "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==",
- "license": "MIT"
- },
"node_modules/serve-index": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.2.tgz",
@@ -17018,9 +16991,9 @@
}
},
"node_modules/tapable": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
- "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.2.tgz",
+ "integrity": "sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA==",
"license": "MIT",
"engines": {
"node": ">=6"
@@ -17031,9 +17004,9 @@
}
},
"node_modules/terser": {
- "version": "5.46.0",
- "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz",
- "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==",
+ "version": "5.46.1",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.1.tgz",
+ "integrity": "sha512-vzCjQO/rgUuK9sf8VJZvjqiqiHFaZLnOiimmUuOKODxWL8mm/xua7viT7aqX7dgPY60otQjUotzFMmCB4VdmqQ==",
"license": "BSD-2-Clause",
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
@@ -17117,9 +17090,9 @@
"license": "MIT"
},
"node_modules/thingies": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.5.0.tgz",
- "integrity": "sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw==",
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.6.0.tgz",
+ "integrity": "sha512-rMHRjmlFLM1R96UYPvpmnc3LYtdFrT33JIB7L9hetGue1qAPfn1N2LJeEjxUSidu1Iku+haLZXDuEXUHNGO/lg==",
"license": "MIT",
"engines": {
"node": ">=10.18"
@@ -18078,9 +18051,9 @@
}
},
"node_modules/webpack-dev-server/node_modules/ws": {
- "version": "8.19.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
- "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz",
+ "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
diff --git a/docs/package.json b/docs/package.json
index e61ba2b..60aff0c 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -15,8 +15,8 @@
"typecheck": "tsc"
},
"dependencies": {
- "@docusaurus/core": "3.9.2",
- "@docusaurus/preset-classic": "3.9.2",
+ "@docusaurus/core": "^3.5.2",
+ "@docusaurus/preset-classic": "^3.5.2",
"@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0",
"prism-react-renderer": "^2.3.0",
@@ -43,5 +43,11 @@
},
"engines": {
"node": ">=20.0"
+ },
+ "overrides": {
+ "serialize-javascript": ">=7.0.5",
+ "path-to-regexp": ">=8.2.0",
+ "picomatch": ">=4.0.2",
+ "brace-expansion": ">=2.0.2"
}
}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..0beabf2
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.caching=true
+org.gradle.parallel=true
+org.gradle.jvmargs=-Xmx2g
diff --git a/mvnw b/mvnw
new file mode 100755
index 0000000..bd8896b
--- /dev/null
+++ b/mvnw
@@ -0,0 +1,295 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.3.4
+#
+# Optional ENV vars
+# -----------------
+# JAVA_HOME - location of a JDK home dir, required when download maven via java source
+# MVNW_REPOURL - repo url base for downloading maven distribution
+# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
+# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
+# ----------------------------------------------------------------------------
+
+set -euf
+[ "${MVNW_VERBOSE-}" != debug ] || set -x
+
+# OS specific support.
+native_path() { printf %s\\n "$1"; }
+case "$(uname)" in
+CYGWIN* | MINGW*)
+ [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
+ native_path() { cygpath --path --windows "$1"; }
+ ;;
+esac
+
+# set JAVACMD and JAVACCMD
+set_java_home() {
+ # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
+ if [ -n "${JAVA_HOME-}" ]; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ]; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ JAVACCMD="$JAVA_HOME/jre/sh/javac"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ JAVACCMD="$JAVA_HOME/bin/javac"
+
+ if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
+ echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
+ echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
+ return 1
+ fi
+ fi
+ else
+ JAVACMD="$(
+ 'set' +e
+ 'unset' -f command 2>/dev/null
+ 'command' -v java
+ )" || :
+ JAVACCMD="$(
+ 'set' +e
+ 'unset' -f command 2>/dev/null
+ 'command' -v javac
+ )" || :
+
+ if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
+ echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
+ return 1
+ fi
+ fi
+}
+
+# hash string like Java String::hashCode
+hash_string() {
+ str="${1:-}" h=0
+ while [ -n "$str" ]; do
+ char="${str%"${str#?}"}"
+ h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
+ str="${str#?}"
+ done
+ printf %x\\n $h
+}
+
+verbose() { :; }
+[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
+
+die() {
+ printf %s\\n "$1" >&2
+ exit 1
+}
+
+trim() {
+ # MWRAPPER-139:
+ # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
+ # Needed for removing poorly interpreted newline sequences when running in more
+ # exotic environments such as mingw bash on Windows.
+ printf "%s" "${1}" | tr -d '[:space:]'
+}
+
+scriptDir="$(dirname "$0")"
+scriptName="$(basename "$0")"
+
+# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
+while IFS="=" read -r key value; do
+ case "${key-}" in
+ distributionUrl) distributionUrl=$(trim "${value-}") ;;
+ distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
+ esac
+done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties"
+[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
+
+case "${distributionUrl##*/}" in
+maven-mvnd-*bin.*)
+ MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
+ case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
+ *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
+ :Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
+ :Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
+ :Linux*x86_64*) distributionPlatform=linux-amd64 ;;
+ *)
+ echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
+ distributionPlatform=linux-amd64
+ ;;
+ esac
+ distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
+ ;;
+maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
+*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
+esac
+
+# apply MVNW_REPOURL and calculate MAVEN_HOME
+# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/
+[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
+distributionUrlName="${distributionUrl##*/}"
+distributionUrlNameMain="${distributionUrlName%.*}"
+distributionUrlNameMain="${distributionUrlNameMain%-bin}"
+MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
+MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
+
+exec_maven() {
+ unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
+ exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
+}
+
+if [ -d "$MAVEN_HOME" ]; then
+ verbose "found existing MAVEN_HOME at $MAVEN_HOME"
+ exec_maven "$@"
+fi
+
+case "${distributionUrl-}" in
+*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
+*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
+esac
+
+# prepare tmp dir
+if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
+ clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
+ trap clean HUP INT TERM EXIT
+else
+ die "cannot create temp dir"
+fi
+
+mkdir -p -- "${MAVEN_HOME%/*}"
+
+# Download and Install Apache Maven
+verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
+verbose "Downloading from: $distributionUrl"
+verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
+
+# select .zip or .tar.gz
+if ! command -v unzip >/dev/null; then
+ distributionUrl="${distributionUrl%.zip}.tar.gz"
+ distributionUrlName="${distributionUrl##*/}"
+fi
+
+# verbose opt
+__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
+[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
+
+# normalize http auth
+case "${MVNW_PASSWORD:+has-password}" in
+'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
+has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
+esac
+
+if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
+ verbose "Found wget ... using wget"
+ wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
+elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
+ verbose "Found curl ... using curl"
+ curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
+elif set_java_home; then
+ verbose "Falling back to use Java to download"
+ javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
+ targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
+ cat >"$javaSource" <<-END
+ public class Downloader extends java.net.Authenticator
+ {
+ protected java.net.PasswordAuthentication getPasswordAuthentication()
+ {
+ return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
+ }
+ public static void main( String[] args ) throws Exception
+ {
+ setDefault( new Downloader() );
+ java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
+ }
+ }
+ END
+ # For Cygwin/MinGW, switch paths to Windows format before running javac and java
+ verbose " - Compiling Downloader.java ..."
+ "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
+ verbose " - Running Downloader.java ..."
+ "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
+fi
+
+# If specified, validate the SHA-256 sum of the Maven distribution zip file
+if [ -n "${distributionSha256Sum-}" ]; then
+ distributionSha256Result=false
+ if [ "$MVN_CMD" = mvnd.sh ]; then
+ echo "Checksum validation is not supported for maven-mvnd." >&2
+ echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
+ exit 1
+ elif command -v sha256sum >/dev/null; then
+ if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then
+ distributionSha256Result=true
+ fi
+ elif command -v shasum >/dev/null; then
+ if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
+ distributionSha256Result=true
+ fi
+ else
+ echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
+ echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
+ exit 1
+ fi
+ if [ $distributionSha256Result = false ]; then
+ echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
+ echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
+ exit 1
+ fi
+fi
+
+# unzip and move
+if command -v unzip >/dev/null; then
+ unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
+else
+ tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
+fi
+
+# Find the actual extracted directory name (handles snapshots where filename != directory name)
+actualDistributionDir=""
+
+# First try the expected directory name (for regular distributions)
+if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then
+ if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then
+ actualDistributionDir="$distributionUrlNameMain"
+ fi
+fi
+
+# If not found, search for any directory with the Maven executable (for snapshots)
+if [ -z "$actualDistributionDir" ]; then
+ # enable globbing to iterate over items
+ set +f
+ for dir in "$TMP_DOWNLOAD_DIR"/*; do
+ if [ -d "$dir" ]; then
+ if [ -f "$dir/bin/$MVN_CMD" ]; then
+ actualDistributionDir="$(basename "$dir")"
+ break
+ fi
+ fi
+ done
+ set -f
+fi
+
+if [ -z "$actualDistributionDir" ]; then
+ verbose "Contents of $TMP_DOWNLOAD_DIR:"
+ verbose "$(ls -la "$TMP_DOWNLOAD_DIR")"
+ die "Could not find Maven distribution directory in extracted archive"
+fi
+
+verbose "Found extracted Maven distribution directory: $actualDistributionDir"
+printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url"
+mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
+
+clean || :
+exec_maven "$@"
diff --git a/mvnw.cmd b/mvnw.cmd
new file mode 100644
index 0000000..92450f9
--- /dev/null
+++ b/mvnw.cmd
@@ -0,0 +1,189 @@
+<# : batch portion
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.3.4
+@REM
+@REM Optional ENV vars
+@REM MVNW_REPOURL - repo url base for downloading maven distribution
+@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
+@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
+@REM ----------------------------------------------------------------------------
+
+@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
+@SET __MVNW_CMD__=
+@SET __MVNW_ERROR__=
+@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
+@SET PSModulePath=
+@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
+ IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
+)
+@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
+@SET __MVNW_PSMODULEP_SAVE=
+@SET __MVNW_ARG0_NAME__=
+@SET MVNW_USERNAME=
+@SET MVNW_PASSWORD=
+@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*)
+@echo Cannot start maven from wrapper >&2 && exit /b 1
+@GOTO :EOF
+: end batch / begin powershell #>
+
+$ErrorActionPreference = "Stop"
+if ($env:MVNW_VERBOSE -eq "true") {
+ $VerbosePreference = "Continue"
+}
+
+# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
+$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
+if (!$distributionUrl) {
+ Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
+}
+
+switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
+ "maven-mvnd-*" {
+ $USE_MVND = $true
+ $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
+ $MVN_CMD = "mvnd.cmd"
+ break
+ }
+ default {
+ $USE_MVND = $false
+ $MVN_CMD = $script -replace '^mvnw','mvn'
+ break
+ }
+}
+
+# apply MVNW_REPOURL and calculate MAVEN_HOME
+# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/
+if ($env:MVNW_REPOURL) {
+ $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" }
+ $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')"
+}
+$distributionUrlName = $distributionUrl -replace '^.*/',''
+$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
+
+$MAVEN_M2_PATH = "$HOME/.m2"
+if ($env:MAVEN_USER_HOME) {
+ $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME"
+}
+
+if (-not (Test-Path -Path $MAVEN_M2_PATH)) {
+ New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null
+}
+
+$MAVEN_WRAPPER_DISTS = $null
+if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) {
+ $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists"
+} else {
+ $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists"
+}
+
+$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain"
+$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
+$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
+
+if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
+ Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
+ Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
+ exit $?
+}
+
+if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
+ Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
+}
+
+# prepare tmp dir
+$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
+$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
+$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
+trap {
+ if ($TMP_DOWNLOAD_DIR.Exists) {
+ try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
+ catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
+ }
+}
+
+New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
+
+# Download and Install Apache Maven
+Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
+Write-Verbose "Downloading from: $distributionUrl"
+Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
+
+$webclient = New-Object System.Net.WebClient
+if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
+ $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
+}
+[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
+$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
+
+# If specified, validate the SHA-256 sum of the Maven distribution zip file
+$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
+if ($distributionSha256Sum) {
+ if ($USE_MVND) {
+ Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
+ }
+ Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
+ if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
+ Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
+ }
+}
+
+# unzip and move
+Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
+
+# Find the actual extracted directory name (handles snapshots where filename != directory name)
+$actualDistributionDir = ""
+
+# First try the expected directory name (for regular distributions)
+$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain"
+$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD"
+if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) {
+ $actualDistributionDir = $distributionUrlNameMain
+}
+
+# If not found, search for any directory with the Maven executable (for snapshots)
+if (!$actualDistributionDir) {
+ Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object {
+ $testPath = Join-Path $_.FullName "bin/$MVN_CMD"
+ if (Test-Path -Path $testPath -PathType Leaf) {
+ $actualDistributionDir = $_.Name
+ }
+ }
+}
+
+if (!$actualDistributionDir) {
+ Write-Error "Could not find Maven distribution directory in extracted archive"
+}
+
+Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir"
+Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null
+try {
+ Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
+} catch {
+ if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
+ Write-Error "fail to move MAVEN_HOME"
+ }
+} finally {
+ try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
+ catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
+}
+
+Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
diff --git a/pom.xml b/pom.xml
index 320a5b4..1832a4e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,7 +1,7 @@
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.agenteval
@@ -21,6 +21,7 @@
+ agenteval-bom
agenteval-core
agenteval-judge
agenteval-embeddings
@@ -57,8 +58,27 @@
3.6.0
10.21.4
4.9.1.0
+ 3.5.0
+ 0.8.12
+ 3.3.1
+ 3.11.2
+ 3.2.7
+
+ scm:git:git://github.com/pratyush618/agenteval.git
+ scm:git:ssh://github.com:pratyush618/agenteval.git
+ https://github.com/pratyush618/agenteval/tree/main
+
+
+
+
+ pratyush618
+ Pratyush
+ https://github.com/pratyush618
+
+
+
@@ -167,6 +187,58 @@
org.apache.maven.plugins
maven-surefire-plugin
${maven-surefire-plugin.version}
+
+ eval
+
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+ ${maven-enforcer-plugin.version}
+
+
+ enforce-build-environment
+ validate
+
+ enforce
+
+
+
+
+ [21,)
+ Java 21+ is required to build AgentEval.
+
+
+ [3.9,)
+ Maven 3.9+ is required to build AgentEval.
+
+
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ ${jacoco-maven-plugin.version}
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ ${maven-source-plugin.version}
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ ${maven-javadoc-plugin.version}
+
+ none
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ ${maven-gpg-plugin.version}
org.apache.maven.plugins
@@ -258,6 +330,103 @@
com.github.spotbugs
spotbugs-maven-plugin
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+
+
+
+
+
+ eval-tests
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ eval
+
+
+
+
+
+
+
+
+ coverage
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+
+
+ prepare-agent
+
+ prepare-agent
+
+
+
+ report
+ verify
+
+ report
+
+
+
+
+
+
+
+
+
+
+ release
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+ attach-sources
+
+ jar-no-fork
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+
+
+ attach-javadocs
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+
+
+
+
+
+
diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml
index 8a050bf..383d223 100644
--- a/spotbugs-exclude.xml
+++ b/spotbugs-exclude.xml
@@ -1,21 +1,21 @@
+ defensive copies are made in build() -->
+ (AgentTestCase has mutable capture-time fields by design) -->
+ throw; all concrete subclasses are final -->
@@ -40,6 +40,10 @@
+
+
+
+
@@ -66,7 +70,7 @@
+ records expose their components by design -->
@@ -121,7 +125,7 @@
+ BenchmarkResult exposes variant results by design -->
@@ -134,8 +138,8 @@
+ SnapshotStore shares ObjectMapper (thread-safe);
+ SnapshotReporter stores config/store references intentionally -->